补充主题静态资源与归档模板
This commit is contained in:
1 parent
1268a55dd0
commit
3247db7ed1
265 files changed
+59174
No files matched your search
@@ -0,0 +1,965 @@
|
||||
/**
|
||||
* AKSRT Runtime Infrastructure
|
||||
*
|
||||
* Unified core primitives for the entire frontend:
|
||||
* aksrt.tbquire(deps, cb) — lazy script/CSS loader
|
||||
* aksrt.notyf(msg, opts) — unified toast (same-ID update)
|
||||
* aksrt.confirm(msg, opts) — i18n confirm dialog
|
||||
* aksrt.refreshModal(opts) — remote content modal
|
||||
* aksrt.scrollTopTo(target, off) — smart scroll with header offset
|
||||
* aksrt.loading(el, show) — element-level loading overlay
|
||||
* aksrt.Drawer(opts) — mobile fullscreen drawer + route
|
||||
* aksrt.route(url, title) — push/replace URL + title
|
||||
*
|
||||
* Declarative interactions (event delegation on body):
|
||||
* [data-toggle-class] — toggle class on target
|
||||
* [data-close] — close target element
|
||||
* [data-onclick] — trigger click on another element
|
||||
* [data-confirm] — confirm before action
|
||||
* [data-action] — universal AJAX action button (like/follow/checkin)
|
||||
* [ajax-action] — general AJAX button with modal response
|
||||
*
|
||||
* Body scroll direction bus:
|
||||
* body.scroll-down / body.scroll-up (threshold 100px)
|
||||
*
|
||||
* @package AKSRT
|
||||
* @since 5.0.0
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var aksrt = window.aksrt || {};
|
||||
window.aksrt = aksrt;
|
||||
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
// §10.11 — tbquire: lazy script/CSS loader
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
|
||||
var _loadedScripts = {};
|
||||
var _loadingPromises = {};
|
||||
|
||||
function loadSingleScript(src) {
|
||||
if (_loadedScripts[src]) return Promise.resolve();
|
||||
if (_loadingPromises[src]) return _loadingPromises[src];
|
||||
|
||||
_loadingPromises[src] = new Promise(function (resolve, reject) {
|
||||
var isCSS = /\.css(\?|$)/i.test(src);
|
||||
var el;
|
||||
|
||||
if (isCSS) {
|
||||
el = document.createElement('link');
|
||||
el.rel = 'stylesheet';
|
||||
el.href = src;
|
||||
} else {
|
||||
el = document.createElement('script');
|
||||
el.src = src;
|
||||
el.async = true;
|
||||
}
|
||||
|
||||
el.onload = function () {
|
||||
_loadedScripts[src] = true;
|
||||
delete _loadingPromises[src];
|
||||
resolve();
|
||||
};
|
||||
el.onerror = function () {
|
||||
delete _loadingPromises[src];
|
||||
reject(new Error('Failed to load: ' + src));
|
||||
};
|
||||
|
||||
(document.head || document.documentElement).appendChild(el);
|
||||
});
|
||||
|
||||
return _loadingPromises[src];
|
||||
}
|
||||
|
||||
aksrt.tbquire = function (deps, callback) {
|
||||
if (typeof deps === 'string') deps = [deps];
|
||||
if (!Array.isArray(deps) || !deps.length) {
|
||||
if (typeof callback === 'function') callback();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
var resolvedDeps = deps.map(function (dep) {
|
||||
if (/^https?:\/\/|^\//.test(dep)) return dep;
|
||||
var map = (window.aksrtData && aksrtData.tbquireMap) || {};
|
||||
return map[dep] || dep;
|
||||
});
|
||||
|
||||
var p = Promise.all(resolvedDeps.map(loadSingleScript));
|
||||
if (typeof callback === 'function') {
|
||||
p.then(callback).catch(function (err) {
|
||||
console.error('[AKSRT tbquire]', err);
|
||||
});
|
||||
}
|
||||
return p;
|
||||
};
|
||||
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
// §10.10 — notyf: unified toast with same-ID update
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
|
||||
var _notyfContainer = null;
|
||||
var _notyfMap = {};
|
||||
var NOTYF_DURATION = 5000;
|
||||
|
||||
function getNotyfContainer() {
|
||||
if (_notyfContainer && _notyfContainer.parentNode) return _notyfContainer;
|
||||
_notyfContainer = document.createElement('div');
|
||||
_notyfContainer.className = 'aksrt-notyf';
|
||||
_notyfContainer.setAttribute('role', 'alert');
|
||||
_notyfContainer.setAttribute('aria-live', 'polite');
|
||||
document.body.appendChild(_notyfContainer);
|
||||
return _notyfContainer;
|
||||
}
|
||||
|
||||
function createNotyfItem(msg, opts) {
|
||||
var el = document.createElement('div');
|
||||
el.className = 'aksrt-notyf__item aksrt-notyf--' + (opts.type || 'info');
|
||||
if (opts.type === 'load') el.classList.add('aksrt-notyf--loading');
|
||||
|
||||
var iconMap = {
|
||||
success: '<i class="fas fa-check-circle"></i>',
|
||||
danger: '<i class="fas fa-exclamation-circle"></i>',
|
||||
error: '<i class="fas fa-exclamation-circle"></i>',
|
||||
warning: '<i class="fas fa-exclamation-triangle"></i>',
|
||||
load: '<i class="fas fa-spinner fa-spin"></i>',
|
||||
info: '<i class="fas fa-info-circle"></i>'
|
||||
};
|
||||
|
||||
el.innerHTML =
|
||||
'<span class="aksrt-notyf__icon">' + (iconMap[opts.type] || iconMap.info) + '</span>' +
|
||||
'<span class="aksrt-notyf__text">' + escapeHtml(msg) + '</span>' +
|
||||
'<button type="button" class="aksrt-notyf__close" aria-label="Close">×</button>';
|
||||
|
||||
el.querySelector('.aksrt-notyf__close').addEventListener('click', function () {
|
||||
removeNotyf(el, opts.id);
|
||||
});
|
||||
|
||||
return el;
|
||||
}
|
||||
|
||||
function removeNotyf(el, id) {
|
||||
el.classList.add('aksrt-notyf--out');
|
||||
setTimeout(function () {
|
||||
if (el.parentNode) el.parentNode.removeChild(el);
|
||||
}, 300);
|
||||
if (id && _notyfMap[id]) {
|
||||
clearTimeout(_notyfMap[id].timer);
|
||||
delete _notyfMap[id];
|
||||
}
|
||||
}
|
||||
|
||||
aksrt.notyf = function (msg, opts) {
|
||||
if (typeof opts === 'string') opts = { type: opts };
|
||||
opts = opts || {};
|
||||
var type = opts.type || 'info';
|
||||
var duration = type === 'load' ? 0 : (opts.duration || NOTYF_DURATION);
|
||||
var id = opts.id || null;
|
||||
|
||||
var container = getNotyfContainer();
|
||||
|
||||
if (id && _notyfMap[id]) {
|
||||
var existing = _notyfMap[id];
|
||||
clearTimeout(existing.timer);
|
||||
existing.el.className = 'aksrt-notyf__item aksrt-notyf--' + type;
|
||||
existing.el.querySelector('.aksrt-notyf__text').textContent = msg;
|
||||
var iconSpan = existing.el.querySelector('.aksrt-notyf__icon');
|
||||
var iconMap2 = {
|
||||
success: '<i class="fas fa-check-circle"></i>',
|
||||
danger: '<i class="fas fa-exclamation-circle"></i>',
|
||||
error: '<i class="fas fa-exclamation-circle"></i>',
|
||||
warning: '<i class="fas fa-exclamation-triangle"></i>',
|
||||
load: '<i class="fas fa-spinner fa-spin"></i>',
|
||||
info: '<i class="fas fa-info-circle"></i>'
|
||||
};
|
||||
iconSpan.innerHTML = iconMap2[type] || iconMap2.info;
|
||||
if (duration > 0) {
|
||||
existing.timer = setTimeout(function () { removeNotyf(existing.el, id); }, duration);
|
||||
}
|
||||
return existing.el;
|
||||
}
|
||||
|
||||
var el = createNotyfItem(msg, { type: type, id: id });
|
||||
container.appendChild(el);
|
||||
|
||||
requestAnimationFrame(function () {
|
||||
el.classList.add('aksrt-notyf--in');
|
||||
});
|
||||
|
||||
var timer = null;
|
||||
if (duration > 0) {
|
||||
timer = setTimeout(function () { removeNotyf(el, id); }, duration);
|
||||
}
|
||||
|
||||
if (id) {
|
||||
_notyfMap[id] = { el: el, timer: timer };
|
||||
}
|
||||
|
||||
return el;
|
||||
};
|
||||
|
||||
aksrt.notyf.close = function (id) {
|
||||
if (_notyfMap[id]) removeNotyf(_notyfMap[id].el, id);
|
||||
};
|
||||
|
||||
// Backward compat: wire window.aksrtToast to notyf
|
||||
window.aksrtToast = function (msg, type) {
|
||||
aksrt.notyf(msg, { type: type || 'info', duration: 2200 });
|
||||
};
|
||||
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
// §10.10 — confirm: i18n confirm dialog + [data-confirm]
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
|
||||
var _i18n = (window.aksrtData && aksrtData.i18n) || {};
|
||||
|
||||
function __(key, fallback) {
|
||||
return _i18n[key] || fallback || key;
|
||||
}
|
||||
|
||||
aksrt.__ = __;
|
||||
|
||||
aksrt.confirm = function (msg, opts) {
|
||||
opts = opts || {};
|
||||
return new Promise(function (resolve) {
|
||||
var overlay = document.createElement('div');
|
||||
overlay.className = 'aksrt-confirm-overlay';
|
||||
|
||||
var dialog = document.createElement('div');
|
||||
dialog.className = 'aksrt-confirm-dialog';
|
||||
dialog.setAttribute('role', 'alertdialog');
|
||||
dialog.setAttribute('aria-modal', 'true');
|
||||
|
||||
dialog.innerHTML =
|
||||
'<div class="aksrt-confirm__body">' + escapeHtml(msg) + '</div>' +
|
||||
'<div class="aksrt-confirm__actions">' +
|
||||
'<button type="button" class="aksrt-confirm__cancel btn-ghost">' +
|
||||
escapeHtml(opts.cancelText || __('cancel', '取消')) +
|
||||
'</button>' +
|
||||
'<button type="button" class="aksrt-confirm__ok btn-primary">' +
|
||||
escapeHtml(opts.okText || __('confirm', '确定')) +
|
||||
'</button>' +
|
||||
'</div>';
|
||||
|
||||
overlay.appendChild(dialog);
|
||||
document.body.appendChild(overlay);
|
||||
|
||||
requestAnimationFrame(function () { overlay.classList.add('is-open'); });
|
||||
|
||||
function close(result) {
|
||||
overlay.classList.remove('is-open');
|
||||
setTimeout(function () { overlay.remove(); }, 200);
|
||||
resolve(result);
|
||||
}
|
||||
|
||||
dialog.querySelector('.aksrt-confirm__cancel').addEventListener('click', function () { close(false); });
|
||||
dialog.querySelector('.aksrt-confirm__ok').addEventListener('click', function () { close(true); });
|
||||
overlay.addEventListener('click', function (e) { if (e.target === overlay) close(false); });
|
||||
|
||||
dialog.querySelector('.aksrt-confirm__ok').focus();
|
||||
});
|
||||
};
|
||||
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
// §10.10 — scrollTopTo: smart scroll with header offset
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
|
||||
aksrt.scrollTopTo = function (target, extraOffset) {
|
||||
var top = 0;
|
||||
if (typeof target === 'number') {
|
||||
top = target;
|
||||
} else if (target && target.getBoundingClientRect) {
|
||||
top = target.getBoundingClientRect().top + window.pageYOffset;
|
||||
}
|
||||
|
||||
var navFixed = document.querySelector('.site-nav.is-fixed, .site-header.is-fixed');
|
||||
var headerOffset = navFixed ? (navFixed.offsetHeight + 20) : 0;
|
||||
top = Math.max(0, top - headerOffset - (extraOffset || 0));
|
||||
|
||||
var current = window.pageYOffset;
|
||||
if (Math.abs(top - current) < 80) return;
|
||||
|
||||
window.scrollTo({ top: top, behavior: 'smooth' });
|
||||
};
|
||||
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
// §10.10 — loading: element-level loading overlay
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
|
||||
aksrt.loading = function (el, show) {
|
||||
if (!el) return;
|
||||
if (show === false) {
|
||||
var mask = el.querySelector('.aksrt-loading-mask');
|
||||
if (mask) {
|
||||
mask.classList.add('aksrt-loading-mask--out');
|
||||
setTimeout(function () { mask.remove(); }, 300);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (el.querySelector('.aksrt-loading-mask')) return;
|
||||
var pos = getComputedStyle(el).position;
|
||||
if (pos === 'static') el.style.position = 'relative';
|
||||
|
||||
var mask = document.createElement('div');
|
||||
mask.className = 'aksrt-loading-mask';
|
||||
mask.innerHTML = '<svg class="aksrt-loading-mask__spinner" width="36" height="36" viewBox="0 0 36 36">' +
|
||||
'<circle cx="18" cy="18" r="15" fill="none" stroke="currentColor" stroke-width="3" stroke-dasharray="80 40" stroke-linecap="round">' +
|
||||
'<animateTransform attributeName="transform" type="rotate" from="0 18 18" to="360 18 18" dur="0.8s" repeatCount="indefinite"/>' +
|
||||
'</circle></svg>';
|
||||
el.appendChild(mask);
|
||||
};
|
||||
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
// §10.10 — refreshModal: remote content modal
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
|
||||
var _refreshModalEl = null;
|
||||
|
||||
function getRefreshModalEl() {
|
||||
if (_refreshModalEl && _refreshModalEl.parentNode) return _refreshModalEl;
|
||||
_refreshModalEl = document.createElement('div');
|
||||
_refreshModalEl.className = 'aksrt-refresh-modal';
|
||||
_refreshModalEl.innerHTML =
|
||||
'<div class="aksrt-refresh-modal__overlay"></div>' +
|
||||
'<div class="aksrt-refresh-modal__dialog">' +
|
||||
'<div class="aksrt-refresh-modal__header">' +
|
||||
'<h3 class="aksrt-refresh-modal__title"></h3>' +
|
||||
'<button type="button" class="aksrt-refresh-modal__close">×</button>' +
|
||||
'</div>' +
|
||||
'<div class="aksrt-refresh-modal__body"></div>' +
|
||||
'</div>';
|
||||
document.body.appendChild(_refreshModalEl);
|
||||
|
||||
_refreshModalEl.querySelector('.aksrt-refresh-modal__close').addEventListener('click', closeRefreshModal);
|
||||
_refreshModalEl.querySelector('.aksrt-refresh-modal__overlay').addEventListener('click', function (e) {
|
||||
if (e.target === e.currentTarget) closeRefreshModal();
|
||||
});
|
||||
|
||||
return _refreshModalEl;
|
||||
}
|
||||
|
||||
function closeRefreshModal() {
|
||||
if (!_refreshModalEl) return;
|
||||
_refreshModalEl.classList.remove('is-open', 'from-bottom');
|
||||
document.body.classList.remove('modal-open');
|
||||
setTimeout(function () {
|
||||
var body = _refreshModalEl.querySelector('.aksrt-refresh-modal__body');
|
||||
if (body) body.innerHTML = '';
|
||||
}, 300);
|
||||
}
|
||||
|
||||
aksrt.refreshModal = function (opts) {
|
||||
opts = opts || {};
|
||||
var modal = getRefreshModalEl();
|
||||
var body = modal.querySelector('.aksrt-refresh-modal__body');
|
||||
var title = modal.querySelector('.aksrt-refresh-modal__title');
|
||||
|
||||
if (opts.title) title.textContent = opts.title;
|
||||
else title.textContent = '';
|
||||
|
||||
var isMobile = window.innerWidth < 768;
|
||||
modal.classList.toggle('from-bottom', !!(opts.mobile_from_bottom && isMobile));
|
||||
|
||||
if (opts.class) modal.querySelector('.aksrt-refresh-modal__dialog').className = 'aksrt-refresh-modal__dialog ' + opts.class;
|
||||
|
||||
body.innerHTML = '';
|
||||
aksrt.loading(body, true);
|
||||
modal.classList.add('is-open');
|
||||
document.body.classList.add('modal-open');
|
||||
|
||||
if (opts.content) {
|
||||
aksrt.loading(body, false);
|
||||
body.innerHTML = opts.content;
|
||||
if (window.AksrtFrontend) AksrtFrontend.rehydrate(body, 'modal');
|
||||
return Promise.resolve(modal);
|
||||
}
|
||||
|
||||
if (opts.remote) {
|
||||
return fetch(opts.remote, { credentials: 'same-origin' })
|
||||
.then(function (r) { return r.text(); })
|
||||
.then(function (html) {
|
||||
aksrt.loading(body, false);
|
||||
body.innerHTML = html;
|
||||
if (window.AksrtFrontend) AksrtFrontend.rehydrate(body, 'modal');
|
||||
return modal;
|
||||
})
|
||||
.catch(function (err) {
|
||||
aksrt.loading(body, false);
|
||||
body.innerHTML = '<p class="aksrt-refresh-modal__error">' + escapeHtml(err.message) + '</p>';
|
||||
return modal;
|
||||
});
|
||||
}
|
||||
|
||||
if (opts.action) {
|
||||
var ajaxUrl = (window.aksrtData && aksrtData.ajaxUrl) || '/wp-admin/admin-ajax.php';
|
||||
var params = new URLSearchParams();
|
||||
params.set('action', opts.action);
|
||||
if (window.aksrtData && aksrtData.nonce) params.set('nonce', aksrtData.nonce);
|
||||
if (opts.data) {
|
||||
Object.keys(opts.data).forEach(function (k) { params.set(k, opts.data[k]); });
|
||||
}
|
||||
|
||||
return fetch(ajaxUrl, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
|
||||
credentials: 'same-origin',
|
||||
body: params.toString()
|
||||
})
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (json) {
|
||||
aksrt.loading(body, false);
|
||||
if (json && json.data && json.data.html) {
|
||||
body.innerHTML = json.data.html;
|
||||
} else if (json && json.data && json.data.show_modal) {
|
||||
body.innerHTML = json.data.show_modal;
|
||||
} else {
|
||||
body.innerHTML = '<p>' + escapeHtml(json.data && json.data.message || '') + '</p>';
|
||||
}
|
||||
if (window.AksrtFrontend) AksrtFrontend.rehydrate(body, 'modal');
|
||||
return modal;
|
||||
})
|
||||
.catch(function (err) {
|
||||
aksrt.loading(body, false);
|
||||
body.innerHTML = '<p class="aksrt-refresh-modal__error">' + escapeHtml(err.message) + '</p>';
|
||||
return modal;
|
||||
});
|
||||
}
|
||||
|
||||
aksrt.loading(body, false);
|
||||
return Promise.resolve(modal);
|
||||
};
|
||||
|
||||
aksrt.refreshModal.close = closeRefreshModal;
|
||||
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
// §10.11 — Drawer: mobile fullscreen slide-in + route
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
|
||||
aksrt.Drawer = function (opts) {
|
||||
opts = opts || {};
|
||||
var drawerEl = document.createElement('div');
|
||||
drawerEl.className = 'aksrt-drawer' + (opts.class ? ' ' + opts.class : '');
|
||||
|
||||
drawerEl.innerHTML =
|
||||
'<div class="aksrt-drawer__header">' +
|
||||
'<button type="button" class="aksrt-drawer__back"><i class="fas fa-arrow-left"></i></button>' +
|
||||
'<span class="aksrt-drawer__title">' + escapeHtml(opts.title || '') + '</span>' +
|
||||
'</div>' +
|
||||
'<div class="aksrt-drawer__body"></div>';
|
||||
|
||||
var body = drawerEl.querySelector('.aksrt-drawer__body');
|
||||
|
||||
if (opts.content) {
|
||||
body.innerHTML = opts.content;
|
||||
} else if (opts.remote) {
|
||||
aksrt.loading(body, true);
|
||||
fetch(opts.remote, { credentials: 'same-origin' })
|
||||
.then(function (r) { return r.text(); })
|
||||
.then(function (html) {
|
||||
aksrt.loading(body, false);
|
||||
body.innerHTML = html;
|
||||
if (window.AksrtFrontend) AksrtFrontend.rehydrate(body, 'drawer');
|
||||
})
|
||||
.catch(function () { aksrt.loading(body, false); });
|
||||
}
|
||||
|
||||
document.body.appendChild(drawerEl);
|
||||
document.body.classList.add('drawer-open');
|
||||
|
||||
requestAnimationFrame(function () { drawerEl.classList.add('is-open'); });
|
||||
|
||||
if (opts.route) {
|
||||
aksrt.route(opts.route, opts.title);
|
||||
}
|
||||
|
||||
function close() {
|
||||
drawerEl.classList.remove('is-open');
|
||||
document.body.classList.remove('drawer-open');
|
||||
setTimeout(function () { drawerEl.remove(); }, 300);
|
||||
if (opts.route) {
|
||||
window.history.back();
|
||||
}
|
||||
if (typeof opts.onClose === 'function') opts.onClose();
|
||||
}
|
||||
|
||||
drawerEl.querySelector('.aksrt-drawer__back').addEventListener('click', close);
|
||||
|
||||
// minitouch right-swipe close
|
||||
if (window.aksrt.minitouch) {
|
||||
aksrt.minitouch(drawerEl, {
|
||||
direction: 'right',
|
||||
onEnd: close
|
||||
});
|
||||
}
|
||||
|
||||
return { el: drawerEl, body: body, close: close };
|
||||
};
|
||||
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
// §10.11 — route: tab route + popstate
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
|
||||
aksrt.route = function (url, title) {
|
||||
if (!window.history || !history.pushState) return;
|
||||
history.pushState({ aksrt: true }, title || '', url);
|
||||
if (title) document.title = title;
|
||||
};
|
||||
|
||||
aksrt.routeReplace = function (url, title) {
|
||||
if (!window.history || !history.replaceState) return;
|
||||
history.replaceState({ aksrt: true }, title || '', url);
|
||||
if (title) document.title = title;
|
||||
};
|
||||
|
||||
// Tab route: elements with [data-route] push URL on activation
|
||||
window.addEventListener('popstate', function (e) {
|
||||
var routeTabs = document.querySelectorAll('[data-route]');
|
||||
if (!routeTabs.length) return;
|
||||
|
||||
var path = window.location.pathname + window.location.search;
|
||||
routeTabs.forEach(function (tab) {
|
||||
var tabRoute = tab.getAttribute('data-route');
|
||||
var isMatch = path === tabRoute || path.indexOf(tabRoute) === 0;
|
||||
tab.classList.toggle('is-active', isMatch);
|
||||
var target = tab.getAttribute('data-route-target');
|
||||
if (target) {
|
||||
var panel = document.querySelector(target);
|
||||
if (panel) panel.classList.toggle('is-active', isMatch);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
// §10.2 — Unified body scroll direction bus
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
|
||||
var _lastScrollTop = 0;
|
||||
var _scrollTicking = false;
|
||||
var SCROLL_BUS_THRESHOLD = 100;
|
||||
|
||||
function updateScrollBus() {
|
||||
var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
||||
var body = document.body;
|
||||
|
||||
if (scrollTop > SCROLL_BUS_THRESHOLD) {
|
||||
body.classList.add('body-scroll');
|
||||
} else {
|
||||
body.classList.remove('body-scroll');
|
||||
}
|
||||
|
||||
if (scrollTop > _lastScrollTop + 10) {
|
||||
body.classList.add('scroll-down');
|
||||
body.classList.remove('scroll-up');
|
||||
} else if (scrollTop < _lastScrollTop - 10) {
|
||||
body.classList.remove('scroll-down');
|
||||
body.classList.add('scroll-up');
|
||||
}
|
||||
|
||||
_lastScrollTop = Math.max(0, scrollTop);
|
||||
_scrollTicking = false;
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', function () {
|
||||
if (!_scrollTicking) {
|
||||
_scrollTicking = true;
|
||||
requestAnimationFrame(updateScrollBus);
|
||||
}
|
||||
}, { passive: true });
|
||||
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
// §10.11 — Declarative interactions (event delegation)
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
|
||||
document.addEventListener('click', function (e) {
|
||||
var target = e.target.closest('[data-toggle-class]');
|
||||
if (target) {
|
||||
e.preventDefault();
|
||||
var cls = target.getAttribute('data-toggle-class');
|
||||
var sel = target.getAttribute('data-target') || target.getAttribute('data-toggle-target');
|
||||
var el = sel ? document.querySelector(sel) : target;
|
||||
if (el && cls) el.classList.toggle(cls);
|
||||
return;
|
||||
}
|
||||
|
||||
target = e.target.closest('[data-close]');
|
||||
if (target) {
|
||||
e.preventDefault();
|
||||
var sel2 = target.getAttribute('data-close');
|
||||
var el2 = sel2 ? document.querySelector(sel2) : target.parentElement;
|
||||
if (el2) {
|
||||
el2.classList.remove('is-open', 'is-active', 'is-visible');
|
||||
el2.hidden = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
target = e.target.closest('[data-onclick]');
|
||||
if (target) {
|
||||
e.preventDefault();
|
||||
var sel3 = target.getAttribute('data-onclick');
|
||||
var el3 = document.querySelector(sel3);
|
||||
if (el3) el3.click();
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
// [data-confirm] — intercept submission
|
||||
document.addEventListener('click', function (e) {
|
||||
var target = e.target.closest('[data-confirm]');
|
||||
if (!target) return;
|
||||
|
||||
var msg = target.getAttribute('data-confirm');
|
||||
if (!msg) return;
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
aksrt.confirm(msg).then(function (ok) {
|
||||
if (!ok) return;
|
||||
target.removeAttribute('data-confirm');
|
||||
target.click();
|
||||
target.setAttribute('data-confirm', msg);
|
||||
});
|
||||
}, true);
|
||||
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
// §10.11 — [data-action] / [ajax-action] universal buttons
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
|
||||
document.addEventListener('click', function (e) {
|
||||
// [data-action] — like/follow/checkin with localStorage de-dup
|
||||
var btn = e.target.closest('[data-action]');
|
||||
if (btn) {
|
||||
e.preventDefault();
|
||||
handleDataAction(btn);
|
||||
return;
|
||||
}
|
||||
|
||||
// [ajax-action] — general AJAX button
|
||||
btn = e.target.closest('[ajax-action]');
|
||||
if (btn) {
|
||||
e.preventDefault();
|
||||
handleAjaxAction(btn);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
function handleDataAction(btn) {
|
||||
if (btn.classList.contains('is-loading')) return;
|
||||
|
||||
var action = btn.getAttribute('data-action');
|
||||
var id = btn.getAttribute('data-id') || '';
|
||||
var storageKey = 'aksrt_action_' + action + '_' + id;
|
||||
|
||||
if (action === 'like' || action === 'favorite') {
|
||||
try {
|
||||
if (localStorage.getItem(storageKey) && !btn.classList.contains('is-active')) {
|
||||
aksrt.notyf(__('already_done', '已操作'), 'warning');
|
||||
return;
|
||||
}
|
||||
} catch (ex) { /* storage unavailable */ }
|
||||
}
|
||||
|
||||
btn.classList.add('is-loading');
|
||||
|
||||
var ajaxUrl = (window.aksrtData && aksrtData.ajaxUrl) || '/wp-admin/admin-ajax.php';
|
||||
var params = new URLSearchParams();
|
||||
params.set('action', 'aksrt_' + action);
|
||||
if (window.aksrtData && aksrtData.nonce) params.set('nonce', aksrtData.nonce);
|
||||
params.set('id', id);
|
||||
|
||||
var extraData = btn.getAttribute('data-action-data');
|
||||
if (extraData) {
|
||||
try {
|
||||
var ed = JSON.parse(extraData);
|
||||
Object.keys(ed).forEach(function (k) { params.set(k, ed[k]); });
|
||||
} catch (ex) { /* ignore */ }
|
||||
}
|
||||
|
||||
fetch(ajaxUrl, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
|
||||
credentials: 'same-origin',
|
||||
body: params.toString()
|
||||
})
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (json) {
|
||||
btn.classList.remove('is-loading');
|
||||
if (json && json.success) {
|
||||
var isActive = !!json.data && !!json.data.active;
|
||||
btn.classList.toggle('is-active', isActive);
|
||||
|
||||
var countEl = btn.querySelector('[data-count]') || btn.querySelector('.action-count');
|
||||
if (countEl && json.data && json.data.count !== undefined) {
|
||||
countEl.textContent = String(json.data.count);
|
||||
}
|
||||
|
||||
try {
|
||||
if (isActive) localStorage.setItem(storageKey, '1');
|
||||
else localStorage.removeItem(storageKey);
|
||||
} catch (ex) { /* */ }
|
||||
|
||||
if (json.data && json.data.message) {
|
||||
aksrt.notyf(json.data.message, 'success');
|
||||
}
|
||||
|
||||
if (json.data && json.data.goto) {
|
||||
window.location.href = json.data.goto;
|
||||
}
|
||||
} else {
|
||||
aksrt.notyf((json.data && json.data.message) || __('action_failed', '操作失败'), 'danger');
|
||||
}
|
||||
})
|
||||
.catch(function (err) {
|
||||
btn.classList.remove('is-loading');
|
||||
aksrt.notyf(err.message || __('network_error', '网络错误'), 'danger');
|
||||
});
|
||||
}
|
||||
|
||||
function handleAjaxAction(btn) {
|
||||
if (btn.classList.contains('is-loading')) return;
|
||||
btn.classList.add('is-loading');
|
||||
|
||||
var action = btn.getAttribute('ajax-action');
|
||||
var ajaxUrl = (window.aksrtData && aksrtData.ajaxUrl) || '/wp-admin/admin-ajax.php';
|
||||
var params = new URLSearchParams();
|
||||
params.set('action', action);
|
||||
if (window.aksrtData && aksrtData.nonce) params.set('nonce', aksrtData.nonce);
|
||||
|
||||
var form = btn.closest('form');
|
||||
if (form) {
|
||||
new FormData(form).forEach(function (v, k) { params.set(k, v); });
|
||||
}
|
||||
|
||||
fetch(ajaxUrl, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
|
||||
credentials: 'same-origin',
|
||||
body: params.toString()
|
||||
})
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (json) {
|
||||
btn.classList.remove('is-loading');
|
||||
if (json && json.success) {
|
||||
if (json.data && json.data.show_modal) {
|
||||
aksrt.refreshModal({ content: json.data.show_modal, mobile_from_bottom: true });
|
||||
} else if (json.data && json.data.message) {
|
||||
aksrt.notyf(json.data.message, 'success');
|
||||
}
|
||||
if (json.data && json.data.goto) {
|
||||
window.location.href = json.data.goto;
|
||||
}
|
||||
if (json.data && json.data.reload) {
|
||||
window.location.reload();
|
||||
}
|
||||
} else {
|
||||
aksrt.notyf((json.data && json.data.message) || __('action_failed', '操作失败'), 'danger');
|
||||
}
|
||||
})
|
||||
.catch(function (err) {
|
||||
btn.classList.remove('is-loading');
|
||||
aksrt.notyf(err.message || __('network_error', '网络错误'), 'danger');
|
||||
});
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
// §10.11 — Ripple (broad coverage)
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
|
||||
var RIPPLE_SELECTORS = '.toggle-radius,.but-ripple,.but,.btn,.btn-primary,.btn-ghost,.btn-outline,.item-thumbnail,.menu-item>a,.aksrt-ripple,.yiyan-box,.aksrt-card';
|
||||
|
||||
document.addEventListener('click', function (e) {
|
||||
var target = e.target.closest(RIPPLE_SELECTORS);
|
||||
if (!target) return;
|
||||
if (target.querySelector('.aksrt-wave')) return;
|
||||
|
||||
var rect = target.getBoundingClientRect();
|
||||
var size = Math.max(rect.width, rect.height) * 2;
|
||||
var x = e.clientX - rect.left - size / 2;
|
||||
var y = e.clientY - rect.top - size / 2;
|
||||
|
||||
var wave = document.createElement('span');
|
||||
wave.className = 'aksrt-wave';
|
||||
wave.style.cssText = 'width:' + size + 'px;height:' + size + 'px;left:' + x + 'px;top:' + y + 'px;';
|
||||
|
||||
var pos = getComputedStyle(target).position;
|
||||
if (pos === 'static') target.style.position = 'relative';
|
||||
|
||||
target.appendChild(wave);
|
||||
setTimeout(function () { wave.remove(); }, 600);
|
||||
});
|
||||
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
// §10.11 — auto_fun: extended rehydration coverage
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
|
||||
aksrt.autoFun = function (root) {
|
||||
root = root || document;
|
||||
if (window.AksrtFrontend) {
|
||||
AksrtFrontend.rehydrate(root, 'ajax');
|
||||
}
|
||||
|
||||
// Tooltips
|
||||
root.querySelectorAll('[data-tooltip]').forEach(function (el) {
|
||||
if (el.dataset.tooltipBound) return;
|
||||
el.dataset.tooltipBound = '1';
|
||||
el.addEventListener('mouseenter', function () {
|
||||
var tip = document.createElement('div');
|
||||
tip.className = 'aksrt-tooltip';
|
||||
tip.textContent = el.getAttribute('data-tooltip');
|
||||
document.body.appendChild(tip);
|
||||
var rect = el.getBoundingClientRect();
|
||||
tip.style.left = (rect.left + rect.width / 2 - tip.offsetWidth / 2) + 'px';
|
||||
tip.style.top = (rect.top - tip.offsetHeight - 8 + window.pageYOffset) + 'px';
|
||||
el._aksrtTooltip = tip;
|
||||
});
|
||||
el.addEventListener('mouseleave', function () {
|
||||
if (el._aksrtTooltip) { el._aksrtTooltip.remove(); el._aksrtTooltip = null; }
|
||||
});
|
||||
});
|
||||
|
||||
// Lazy images
|
||||
root.querySelectorAll('img.aksrt-lazy[data-src]').forEach(function (img) {
|
||||
if (img.classList.contains('aksrt-loaded')) return;
|
||||
if ('IntersectionObserver' in window) {
|
||||
var obs = new IntersectionObserver(function (entries) {
|
||||
entries.forEach(function (entry) {
|
||||
if (!entry.isIntersecting) return;
|
||||
img.src = img.dataset.src;
|
||||
img.classList.remove('aksrt-lazy');
|
||||
img.classList.add('aksrt-loaded');
|
||||
obs.unobserve(img);
|
||||
});
|
||||
}, { rootMargin: '200px' });
|
||||
obs.observe(img);
|
||||
} else {
|
||||
img.src = img.dataset.src;
|
||||
img.classList.remove('aksrt-lazy');
|
||||
img.classList.add('aksrt-loaded');
|
||||
}
|
||||
});
|
||||
|
||||
// Swiper re-init
|
||||
if (typeof Swiper !== 'undefined') {
|
||||
root.querySelectorAll('[data-swiper-config]:not(.swiper-initialized)').forEach(function (el) {
|
||||
try {
|
||||
var cfg = JSON.parse(el.dataset.swiperConfig || '{}');
|
||||
new Swiper(el, cfg);
|
||||
} catch (ex) { /* */ }
|
||||
});
|
||||
}
|
||||
|
||||
// Countdowns
|
||||
root.querySelectorAll('[data-countdown]').forEach(function (el) {
|
||||
if (el.dataset.countdownBound) return;
|
||||
el.dataset.countdownBound = '1';
|
||||
var end = parseInt(el.getAttribute('data-countdown'), 10);
|
||||
if (!end) return;
|
||||
var iv = setInterval(function () {
|
||||
var left = Math.max(0, end - Math.floor(Date.now() / 1000));
|
||||
if (left <= 0) { clearInterval(iv); el.textContent = '00:00'; return; }
|
||||
var m = Math.floor(left / 60);
|
||||
var s = left % 60;
|
||||
el.textContent = (m < 10 ? '0' : '') + m + ':' + (s < 10 ? '0' : '') + s;
|
||||
}, 1000);
|
||||
});
|
||||
};
|
||||
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
// §10.11 — minitouch: general direction gesture
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
|
||||
aksrt.minitouch = function (el, opts) {
|
||||
opts = opts || {};
|
||||
var direction = opts.direction || 'any';
|
||||
var startX = 0, startY = 0, currentX = 0, currentY = 0;
|
||||
var active = false;
|
||||
|
||||
el.addEventListener('touchstart', function (e) {
|
||||
if (e.touches.length !== 1) return;
|
||||
startX = e.touches[0].clientX;
|
||||
startY = e.touches[0].clientY;
|
||||
currentX = startX;
|
||||
currentY = startY;
|
||||
active = true;
|
||||
if (typeof opts.onStart === 'function') {
|
||||
var stop = opts.onStart({ x: startX, y: startY, el: el });
|
||||
if (stop === false) active = false;
|
||||
}
|
||||
}, { passive: true });
|
||||
|
||||
el.addEventListener('touchmove', function (e) {
|
||||
if (!active) return;
|
||||
currentX = e.touches[0].clientX;
|
||||
currentY = e.touches[0].clientY;
|
||||
var dx = currentX - startX;
|
||||
var dy = currentY - startY;
|
||||
var dist = Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
if (dist < 10) return;
|
||||
|
||||
var angle = Math.atan2(dy, dx) * 180 / Math.PI;
|
||||
var dir = getDirection(angle);
|
||||
|
||||
if (direction !== 'any' && dir !== direction) {
|
||||
if (typeof opts.stop === 'function' && opts.stop({ direction: dir, dx: dx, dy: dy })) {
|
||||
active = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof opts.onIng === 'function') {
|
||||
opts.onIng({ dx: dx, dy: dy, direction: dir, distance: dist, el: el });
|
||||
}
|
||||
}, { passive: true });
|
||||
|
||||
el.addEventListener('touchend', function () {
|
||||
if (!active) return;
|
||||
active = false;
|
||||
var dx = currentX - startX;
|
||||
var dy = currentY - startY;
|
||||
var dist = Math.sqrt(dx * dx + dy * dy);
|
||||
var angle = Math.atan2(dy, dx) * 180 / Math.PI;
|
||||
var dir = getDirection(angle);
|
||||
|
||||
if (typeof opts.onEnd === 'function') {
|
||||
opts.onEnd({ dx: dx, dy: dy, direction: dir, distance: dist, el: el });
|
||||
}
|
||||
}, { passive: true });
|
||||
};
|
||||
|
||||
function getDirection(angle) {
|
||||
if (angle >= -45 && angle < 45) return 'right';
|
||||
if (angle >= 45 && angle < 135) return 'bottom';
|
||||
if (angle >= -135 && angle < -45) return 'top';
|
||||
return 'left';
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
// Helpers
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
|
||||
function escapeHtml(str) {
|
||||
if (!str) return '';
|
||||
return String(str)
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"');
|
||||
}
|
||||
|
||||
// ── DOMContentLoaded ──
|
||||
|
||||
function initRuntime() {
|
||||
updateScrollBus();
|
||||
aksrt.autoFun(document);
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initRuntime);
|
||||
} else {
|
||||
initRuntime();
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
/**
|
||||
* AKSRT Author Page
|
||||
*
|
||||
* Handles public author dashboard tabs and profile cover uploads.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
/* global aksrtAuthorPage */
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function notify(message, type) {
|
||||
if (!message) return;
|
||||
if (typeof window.AksrtToast === 'function') {
|
||||
window.AksrtToast(message, type || 'info');
|
||||
return;
|
||||
}
|
||||
if (typeof window.showToast === 'function') {
|
||||
window.showToast(message, type || 'info');
|
||||
return;
|
||||
}
|
||||
if (typeof window.aksrtToast === 'function') {
|
||||
window.aksrtToast(message, type || 'info');
|
||||
return;
|
||||
}
|
||||
window.alert(message);
|
||||
}
|
||||
|
||||
function updateTabUrl(root, name, defaultTab) {
|
||||
if (!window.history || typeof window.history.replaceState !== 'function') return;
|
||||
var url = new URL(window.location.href);
|
||||
if (!name || name === defaultTab) {
|
||||
url.searchParams.delete('tab');
|
||||
} else {
|
||||
url.searchParams.set('tab', name);
|
||||
}
|
||||
window.history.replaceState({}, '', url.toString());
|
||||
}
|
||||
|
||||
function initPublicDashboards() {
|
||||
document.querySelectorAll('.dashboard--public').forEach(function (root) {
|
||||
if (root.dataset.aksrtAuthorBound === '1') return;
|
||||
root.dataset.aksrtAuthorBound = '1';
|
||||
|
||||
var tabs = Array.prototype.slice.call(root.querySelectorAll('.dashboard-tabs [data-tab]'));
|
||||
if (!tabs.length) return;
|
||||
|
||||
var defaultTab = root.dataset.defaultTab || tabs[0].getAttribute('data-tab') || 'posts';
|
||||
var panels = {};
|
||||
|
||||
tabs.forEach(function (tab) {
|
||||
var name = tab.getAttribute('data-tab');
|
||||
var panel = root.querySelector('#panel-' + name);
|
||||
if (name && panel) {
|
||||
panels[name] = {
|
||||
tab: tab,
|
||||
panel: panel
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
function switchTo(name, syncUrl) {
|
||||
if (!panels[name]) {
|
||||
name = defaultTab;
|
||||
}
|
||||
|
||||
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);
|
||||
if (active) {
|
||||
panels[key].panel.removeAttribute('hidden');
|
||||
} else {
|
||||
panels[key].panel.setAttribute('hidden', '');
|
||||
}
|
||||
});
|
||||
|
||||
if (syncUrl) {
|
||||
updateTabUrl(root, name, defaultTab);
|
||||
}
|
||||
}
|
||||
|
||||
function resolveInitialTab() {
|
||||
var url = new URL(window.location.href);
|
||||
return url.searchParams.get('tab') || defaultTab;
|
||||
}
|
||||
|
||||
tabs.forEach(function (tab) {
|
||||
tab.addEventListener('click', function () {
|
||||
switchTo(tab.getAttribute('data-tab'), true);
|
||||
});
|
||||
});
|
||||
|
||||
switchTo(resolveInitialTab(), false);
|
||||
});
|
||||
}
|
||||
|
||||
function initCoverUpload() {
|
||||
var cfg = window.aksrtAuthorPage || {};
|
||||
var upload = cfg.coverUpload || null;
|
||||
if (!upload || !upload.enabled || !upload.restUrl) return;
|
||||
|
||||
var btn = document.getElementById(upload.buttonId || 'aksrt-upload-bg-btn');
|
||||
var input = document.getElementById(upload.inputId || 'aksrt-bg-file-input');
|
||||
if (!btn || !input || btn.dataset.aksrtCoverBound === '1') return;
|
||||
|
||||
btn.dataset.aksrtCoverBound = '1';
|
||||
|
||||
var label = btn.querySelector('span');
|
||||
var idleText = upload.idleText || (label ? label.textContent : '');
|
||||
var loadingText = upload.loadingText || idleText;
|
||||
|
||||
function setBusy(busy) {
|
||||
btn.disabled = !!busy;
|
||||
if (label) {
|
||||
label.textContent = busy ? loadingText : idleText;
|
||||
}
|
||||
}
|
||||
|
||||
function resetImage(previousUrl) {
|
||||
var image = document.getElementById(upload.imageId || 'aksrt-cover-img');
|
||||
if (!image) return;
|
||||
if (previousUrl) {
|
||||
image.src = previousUrl;
|
||||
return;
|
||||
}
|
||||
if (upload.fallbackImage) {
|
||||
image.src = upload.fallbackImage;
|
||||
}
|
||||
}
|
||||
|
||||
function applyImage(nextUrl) {
|
||||
var image = document.getElementById(upload.imageId || 'aksrt-cover-img');
|
||||
if (image && nextUrl) {
|
||||
image.src = nextUrl;
|
||||
}
|
||||
}
|
||||
|
||||
btn.addEventListener('click', function () {
|
||||
input.click();
|
||||
});
|
||||
|
||||
input.addEventListener('change', function () {
|
||||
var file = input.files && input.files[0];
|
||||
if (!file) return;
|
||||
|
||||
if (upload.maxSize && file.size > upload.maxSize) {
|
||||
notify(upload.tooLargeText || '图片大小不能超过 2MB', 'warning');
|
||||
input.value = '';
|
||||
return;
|
||||
}
|
||||
|
||||
setBusy(true);
|
||||
|
||||
var formData = new FormData();
|
||||
formData.append(upload.fieldName || 'background', file);
|
||||
|
||||
fetch(upload.restUrl, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'X-WP-Nonce': upload.restNonce || ''
|
||||
},
|
||||
body: formData
|
||||
})
|
||||
.then(function (response) {
|
||||
return response.json().catch(function () {
|
||||
return null;
|
||||
}).then(function (payload) {
|
||||
if (!response.ok) {
|
||||
throw payload || { message: upload.errorText || '上传失败' };
|
||||
}
|
||||
return payload;
|
||||
});
|
||||
})
|
||||
.then(function (payload) {
|
||||
if (payload && payload.success && payload.url) {
|
||||
applyImage(payload.url);
|
||||
notify(upload.successText || '背景图已更新', 'success');
|
||||
return;
|
||||
}
|
||||
throw payload || { message: upload.errorText || '上传失败' };
|
||||
})
|
||||
.catch(function (error) {
|
||||
var previousUrl = error && error.data && error.data.previous_url !== undefined
|
||||
? error.data.previous_url
|
||||
: '';
|
||||
resetImage(previousUrl);
|
||||
notify((error && error.message) || upload.networkErrorText || '网络错误,请重试', 'error');
|
||||
})
|
||||
.finally(function () {
|
||||
setBusy(false);
|
||||
input.value = '';
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
initPublicDashboards();
|
||||
initCoverUpload();
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,456 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
var page = document.querySelector("[data-aksrt-cart-page]");
|
||||
if (!page || !window.aksrtData) {
|
||||
return;
|
||||
}
|
||||
|
||||
var CART_KEY = "aksrt_cart";
|
||||
var currencySymbol = page.getAttribute("data-currency-symbol") || "¥";
|
||||
var itemsEl = page.querySelector("[data-aksrt-cart-items]");
|
||||
var subtotalEl = page.querySelector("[data-aksrt-summary-subtotal]");
|
||||
var shippingEl = page.querySelector("[data-aksrt-summary-shipping]");
|
||||
var discountEl = page.querySelector("[data-aksrt-summary-discount]");
|
||||
var totalEl = page.querySelector("[data-aksrt-summary-total]");
|
||||
var previewMessageEl = page.querySelector("[data-aksrt-preview-message]");
|
||||
var createBtn = page.querySelector("[data-aksrt-create-order]");
|
||||
var previewBtn = page.querySelector("[data-aksrt-preview-checkout]");
|
||||
|
||||
var previewState = null;
|
||||
var searchParams = new URLSearchParams(window.location.search);
|
||||
|
||||
function getCart() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(CART_KEY) || "[]");
|
||||
return Array.isArray(parsed) ? parsed : [];
|
||||
} catch (error) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function setCart(items) {
|
||||
localStorage.setItem(CART_KEY, JSON.stringify(items));
|
||||
}
|
||||
|
||||
function money(value) {
|
||||
return currencySymbol + Number(value || 0).toFixed(2);
|
||||
}
|
||||
|
||||
function selectedValue(name) {
|
||||
var checked = page.querySelector('input[name="' + name + '"]:checked');
|
||||
return checked ? checked.value : "";
|
||||
}
|
||||
|
||||
function getPayload() {
|
||||
var items = getCart().map(function (item) {
|
||||
return {
|
||||
product_id: Number(item.product_id || item.id || 0),
|
||||
quantity: Number(item.qty || item.quantity || 1)
|
||||
};
|
||||
}).filter(function (item) {
|
||||
return item.product_id > 0;
|
||||
});
|
||||
|
||||
return {
|
||||
items: items,
|
||||
coupon_code: (page.querySelector("[data-aksrt-coupon-code]") || {}).value || "",
|
||||
shipping_method: selectedValue("aksrt_cart_shipping"),
|
||||
address_id: Number(selectedValue("aksrt_cart_address") || 0),
|
||||
payment_method: selectedValue("aksrt_cart_payment"),
|
||||
customer_note: (page.querySelector("[data-aksrt-customer-note]") || {}).value || ""
|
||||
};
|
||||
}
|
||||
|
||||
function renderCart() {
|
||||
var items = getCart();
|
||||
if (!items.length) {
|
||||
itemsEl.innerHTML = '' +
|
||||
'<div class="aksrt-cart-page__empty">' +
|
||||
'<i class="fas fa-shopping-cart" aria-hidden="true"></i>' +
|
||||
"<p>购物车为空,去商品页添加想购买的内容。</p>" +
|
||||
'<a href="/" class="btn-outline btn-sm">继续浏览</a>' +
|
||||
"</div>";
|
||||
subtotalEl.textContent = money(0);
|
||||
shippingEl.textContent = money(0);
|
||||
discountEl.textContent = "-" + money(0);
|
||||
totalEl.textContent = money(0);
|
||||
createBtn.disabled = true;
|
||||
previewState = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var total = 0;
|
||||
var html = "";
|
||||
items.forEach(function (item, index) {
|
||||
var qty = Number(item.qty || item.quantity || 1);
|
||||
var price = Number(item.price || 0);
|
||||
var lineTotal = qty * price;
|
||||
total += lineTotal;
|
||||
|
||||
html += '' +
|
||||
'<article class="aksrt-cart-page__item" data-cart-index="' + index + '">' +
|
||||
(item.image ? '<img class="aksrt-cart-page__item-image" src="' + item.image + '" alt="">' : '<div class="aksrt-cart-page__item-image aksrt-cart-page__item-image--placeholder"><i class="fas fa-box"></i></div>') +
|
||||
'<div class="aksrt-cart-page__item-main">' +
|
||||
'<h3>' + (item.title || "商品") + "</h3>" +
|
||||
'<p>' + money(price) + "</p>" +
|
||||
"</div>" +
|
||||
'<div class="aksrt-cart-page__item-qty">' +
|
||||
'<button type="button" data-qty-action="dec">-</button>' +
|
||||
"<span>" + qty + "</span>" +
|
||||
'<button type="button" data-qty-action="inc">+</button>' +
|
||||
"</div>" +
|
||||
'<strong class="aksrt-cart-page__item-total">' + money(lineTotal) + "</strong>" +
|
||||
'<button type="button" class="aksrt-cart-page__item-remove" data-qty-action="remove"><i class="fas fa-trash"></i></button>' +
|
||||
"</article>";
|
||||
});
|
||||
|
||||
itemsEl.innerHTML = html;
|
||||
subtotalEl.textContent = money(total);
|
||||
|
||||
if (!previewState) {
|
||||
shippingEl.textContent = money(0);
|
||||
discountEl.textContent = "-" + money(0);
|
||||
totalEl.textContent = money(total);
|
||||
}
|
||||
}
|
||||
|
||||
function setSummary(data) {
|
||||
previewState = data || null;
|
||||
subtotalEl.textContent = money((data && data.subtotal) || 0);
|
||||
shippingEl.textContent = money((data && data.shipping_fee) || 0);
|
||||
discountEl.textContent = "-" + money((data && data.discount) || 0);
|
||||
totalEl.textContent = money((data && data.total) || 0);
|
||||
createBtn.disabled = !data;
|
||||
}
|
||||
|
||||
function request(path, body) {
|
||||
return fetch("/wp-json/aksrt/v1" + path, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-WP-Nonce": aksrtData.restNonce
|
||||
},
|
||||
body: JSON.stringify(body || {})
|
||||
}).then(function (response) {
|
||||
return response.json();
|
||||
});
|
||||
}
|
||||
|
||||
function previewCheckout() {
|
||||
var payload = getPayload();
|
||||
if (!payload.items.length) {
|
||||
previewMessageEl.textContent = "请先添加商品后再试算。";
|
||||
return;
|
||||
}
|
||||
|
||||
previewBtn.disabled = true;
|
||||
previewMessageEl.textContent = "正在试算订单...";
|
||||
|
||||
request("/shop/frontend/checkout/preview", payload)
|
||||
.then(function (result) {
|
||||
if (!result.success) {
|
||||
setSummary(null);
|
||||
previewMessageEl.textContent = result.message || "试算失败。";
|
||||
return;
|
||||
}
|
||||
|
||||
setSummary(result.data);
|
||||
previewMessageEl.textContent = "已完成试算,可直接创建订单。";
|
||||
})
|
||||
.catch(function () {
|
||||
setSummary(null);
|
||||
previewMessageEl.textContent = "网络错误,请稍后重试。";
|
||||
})
|
||||
.finally(function () {
|
||||
previewBtn.disabled = false;
|
||||
});
|
||||
}
|
||||
|
||||
function createOrder() {
|
||||
var payload = getPayload();
|
||||
if (!previewState) {
|
||||
previewCheckout();
|
||||
return;
|
||||
}
|
||||
|
||||
createBtn.disabled = true;
|
||||
request("/shop/frontend/orders", payload)
|
||||
.then(function (result) {
|
||||
if (!result.success) {
|
||||
previewMessageEl.textContent = result.message || "订单创建失败。";
|
||||
createBtn.disabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
localStorage.removeItem(CART_KEY);
|
||||
var orderNumber = (result.data && result.data.order_number) || "";
|
||||
var ordersUrl = window.location.pathname.replace("cart", "orders") + "?order_status=pending";
|
||||
|
||||
if (!orderNumber) {
|
||||
window.location.href = ordersUrl;
|
||||
return;
|
||||
}
|
||||
|
||||
// 立即发起支付:跳转型网关直接前往第三方,余额型同步完成。
|
||||
request("/shop/frontend/orders/" + orderNumber + "/pay", {})
|
||||
.then(function (pay) {
|
||||
var data = (pay && pay.data) || {};
|
||||
if (pay && pay.success && data.redirect && data.payment_url && /^https?:\/\//i.test(data.payment_url)) {
|
||||
window.location.href = data.payment_url;
|
||||
return;
|
||||
}
|
||||
// 二维码 / 余额 / 失败:统一回订单中心处理(含 ?payment 提示)。
|
||||
window.location.href = ordersUrl;
|
||||
})
|
||||
.catch(function () {
|
||||
window.location.href = ordersUrl;
|
||||
});
|
||||
})
|
||||
.catch(function () {
|
||||
previewMessageEl.textContent = "网络错误,请稍后重试。";
|
||||
createBtn.disabled = false;
|
||||
});
|
||||
}
|
||||
|
||||
page.addEventListener("click", function (event) {
|
||||
var actionButton = event.target.closest("[data-qty-action]");
|
||||
if (actionButton) {
|
||||
var itemEl = actionButton.closest("[data-cart-index]");
|
||||
var index = Number(itemEl.getAttribute("data-cart-index"));
|
||||
var items = getCart();
|
||||
if (!items[index]) {
|
||||
return;
|
||||
}
|
||||
|
||||
var action = actionButton.getAttribute("data-qty-action");
|
||||
if (action === "inc") {
|
||||
items[index].qty = Number(items[index].qty || 1) + 1;
|
||||
} else if (action === "dec") {
|
||||
items[index].qty = Math.max(1, Number(items[index].qty || 1) - 1);
|
||||
} else if (action === "remove") {
|
||||
items.splice(index, 1);
|
||||
}
|
||||
|
||||
setCart(items);
|
||||
setSummary(null);
|
||||
renderCart();
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.target.closest("[data-aksrt-clear-cart]")) {
|
||||
localStorage.removeItem(CART_KEY);
|
||||
setSummary(null);
|
||||
renderCart();
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.target.closest("[data-aksrt-preview-checkout]")) {
|
||||
previewCheckout();
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.target.closest("[data-aksrt-create-order]")) {
|
||||
createOrder();
|
||||
return;
|
||||
}
|
||||
|
||||
var resumeButton = event.target.closest("[data-aksrt-resume-order]");
|
||||
if (resumeButton) {
|
||||
window.location.href = window.location.pathname.replace("cart", "orders") + "?order_status=pending";
|
||||
}
|
||||
});
|
||||
|
||||
var couponInput = page.querySelector("[data-aksrt-coupon-code]");
|
||||
if (couponInput && searchParams.has("coupon")) {
|
||||
couponInput.value = searchParams.get("coupon") || "";
|
||||
}
|
||||
|
||||
/* ── Address Book Management ── */
|
||||
|
||||
var addressModal = page.querySelector("[data-aksrt-address-modal]");
|
||||
var addressForm = page.querySelector("[data-aksrt-address-form]");
|
||||
var addressList = page.querySelector("[data-aksrt-address-list]");
|
||||
var addressTitle = page.querySelector("[data-aksrt-address-modal-title]");
|
||||
|
||||
function openAddressModal(mode, address) {
|
||||
if (!addressModal || !addressForm) return;
|
||||
addressForm.reset();
|
||||
addressForm.querySelector('[name="address_id"]').value = "";
|
||||
|
||||
if (mode === "edit" && address) {
|
||||
addressTitle.textContent = "编辑地址";
|
||||
addressForm.querySelector('[name="address_id"]').value = address.id || "";
|
||||
addressForm.querySelector('[name="name"]').value = address.name || "";
|
||||
addressForm.querySelector('[name="phone"]').value = address.phone || "";
|
||||
addressForm.querySelector('[name="province"]').value = address.province || "";
|
||||
addressForm.querySelector('[name="city"]').value = address.city || "";
|
||||
addressForm.querySelector('[name="district"]').value = address.district || "";
|
||||
addressForm.querySelector('[name="address"]').value = address.address || "";
|
||||
addressForm.querySelector('[name="is_default"]').checked = !!address.is_default;
|
||||
} else {
|
||||
addressTitle.textContent = "新增地址";
|
||||
}
|
||||
|
||||
addressModal.hidden = false;
|
||||
}
|
||||
|
||||
function closeAddressModal() {
|
||||
if (addressModal) addressModal.hidden = true;
|
||||
}
|
||||
|
||||
function refreshAddressList() {
|
||||
fetch("/wp-json/aksrt/v1/shop/frontend/address", {
|
||||
headers: { "X-WP-Nonce": aksrtData.restNonce }
|
||||
})
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (result) {
|
||||
if (!result.success || !addressList) return;
|
||||
var addresses = (result.data && result.data.addresses) || [];
|
||||
renderAddressList(addresses);
|
||||
})
|
||||
.catch(function () {});
|
||||
}
|
||||
|
||||
function renderAddressList(addresses) {
|
||||
if (!addressList) return;
|
||||
if (!addresses.length) {
|
||||
addressList.innerHTML =
|
||||
'<div class="aksrt-cart-page__address-empty" data-aksrt-address-empty>' +
|
||||
'<i class="fas fa-map-marker-alt" aria-hidden="true"></i>' +
|
||||
"<p>暂无收货地址,请先新增。</p>" +
|
||||
"</div>";
|
||||
return;
|
||||
}
|
||||
|
||||
var html = "";
|
||||
addresses.forEach(function (addr, index) {
|
||||
html +=
|
||||
'<div class="aksrt-cart-page__option-card aksrt-cart-page__address-card" data-aksrt-address-card="' + addr.id + '">' +
|
||||
'<label class="aksrt-cart-page__address-label">' +
|
||||
'<input type="radio" name="aksrt_cart_address" value="' + addr.id + '"' + (index === 0 || addr.is_default ? " checked" : "") + ">" +
|
||||
'<span class="aksrt-cart-page__option-body">' +
|
||||
"<strong>" + escHtml(addr.name) + (addr.is_default ? ' <span class="aksrt-cart-page__default-tag">默认</span>' : "") + "</strong>" +
|
||||
"<span>" + escHtml(addr.phone) + "</span>" +
|
||||
"<span>" + escHtml(addr.full_text) + "</span>" +
|
||||
"</span></label>" +
|
||||
'<div class="aksrt-cart-page__address-actions">' +
|
||||
'<button type="button" class="btn-ghost btn-xs" data-aksrt-address-edit="' + addr.id + '">编辑</button>' +
|
||||
'<button type="button" class="btn-ghost btn-xs" data-aksrt-address-delete="' + addr.id + '">删除</button>' +
|
||||
(addr.is_default ? "" : '<button type="button" class="btn-ghost btn-xs" data-aksrt-address-set-default="' + addr.id + '">设为默认</button>') +
|
||||
"</div></div>";
|
||||
});
|
||||
addressList.innerHTML = html;
|
||||
}
|
||||
|
||||
function escHtml(str) {
|
||||
var div = document.createElement("div");
|
||||
div.appendChild(document.createTextNode(str || ""));
|
||||
return div.innerHTML;
|
||||
}
|
||||
|
||||
function getAddressById(id) {
|
||||
var cards = addressList ? addressList.querySelectorAll("[data-aksrt-address-card]") : [];
|
||||
var found = null;
|
||||
cards.forEach(function (card) {
|
||||
if (String(card.getAttribute("data-aksrt-address-card")) === String(id)) {
|
||||
var body = card.querySelector(".aksrt-cart-page__option-body");
|
||||
if (body) {
|
||||
var spans = body.querySelectorAll("span");
|
||||
var strong = body.querySelector("strong");
|
||||
found = {
|
||||
id: id,
|
||||
name: strong ? strong.textContent.replace("默认", "").trim() : "",
|
||||
phone: spans[0] ? spans[0].textContent : "",
|
||||
full_text: spans[1] ? spans[1].textContent : ""
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
return found;
|
||||
}
|
||||
|
||||
// Address event delegation
|
||||
page.addEventListener("click", function (event) {
|
||||
if (event.target.closest("[data-aksrt-address-add]")) {
|
||||
openAddressModal("add");
|
||||
return;
|
||||
}
|
||||
|
||||
var editBtn = event.target.closest("[data-aksrt-address-edit]");
|
||||
if (editBtn) {
|
||||
var editId = editBtn.getAttribute("data-aksrt-address-edit");
|
||||
var addr = getAddressById(editId);
|
||||
openAddressModal("edit", addr);
|
||||
return;
|
||||
}
|
||||
|
||||
var deleteBtn = event.target.closest("[data-aksrt-address-delete]");
|
||||
if (deleteBtn) {
|
||||
var deleteId = deleteBtn.getAttribute("data-aksrt-address-delete");
|
||||
if (!confirm("确定删除该地址吗?")) return;
|
||||
request("/shop/frontend/address/" + deleteId, {}).then(function (result) {
|
||||
if (!result.success) {
|
||||
alert(result.message || "删除失败。");
|
||||
return;
|
||||
}
|
||||
refreshAddressList();
|
||||
}).catch(function () { alert("网络错误。"); });
|
||||
return;
|
||||
}
|
||||
|
||||
var defaultBtn = event.target.closest("[data-aksrt-address-set-default]");
|
||||
if (defaultBtn) {
|
||||
var defaultId = defaultBtn.getAttribute("data-aksrt-address-set-default");
|
||||
request("/shop/frontend/address/" + defaultId + "/default", {}).then(function (result) {
|
||||
if (!result.success) {
|
||||
alert(result.message || "设置失败。");
|
||||
return;
|
||||
}
|
||||
refreshAddressList();
|
||||
}).catch(function () { alert("网络错误。"); });
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.target.closest("[data-aksrt-address-modal-close]") || event.target.classList.contains("aksrt-modal__overlay")) {
|
||||
closeAddressModal();
|
||||
}
|
||||
});
|
||||
|
||||
if (addressForm) {
|
||||
addressForm.addEventListener("submit", function (event) {
|
||||
event.preventDefault();
|
||||
var formData = new FormData(addressForm);
|
||||
var addressId = formData.get("address_id");
|
||||
var payload = {
|
||||
name: (formData.get("name") || "").trim(),
|
||||
phone: (formData.get("phone") || "").trim(),
|
||||
province: (formData.get("province") || "").trim(),
|
||||
city: (formData.get("city") || "").trim(),
|
||||
district: (formData.get("district") || "").trim(),
|
||||
address: (formData.get("address") || "").trim(),
|
||||
is_default: formData.get("is_default") === "1"
|
||||
};
|
||||
|
||||
if (!payload.name || !payload.phone || !payload.address) {
|
||||
alert("请填写必填项。");
|
||||
return;
|
||||
}
|
||||
|
||||
var url = addressId
|
||||
? "/shop/frontend/address/" + addressId
|
||||
: "/shop/frontend/address";
|
||||
|
||||
request(url, payload).then(function (result) {
|
||||
if (!result.success) {
|
||||
alert(result.message || "保存失败。");
|
||||
return;
|
||||
}
|
||||
closeAddressModal();
|
||||
refreshAddressList();
|
||||
}).catch(function () { alert("网络错误。"); });
|
||||
});
|
||||
}
|
||||
|
||||
renderCart();
|
||||
})();
|
||||
@@ -0,0 +1,344 @@
|
||||
/**
|
||||
* AKSRT CMS Download
|
||||
*
|
||||
* 功能:
|
||||
* - 监听 [data-action="aksrt-download"] 按钮点击
|
||||
* - 调 POST /aksrt/v1/download/request
|
||||
* - 弹窗显示下载链接(含提取码)
|
||||
*
|
||||
* 依赖:
|
||||
* - window.aksrtData.{ ajaxUrl, nonce, siteUrl }
|
||||
* - 主题已加载 fetch (现代浏览器)
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
if (!window.aksrtData) return;
|
||||
const REST_BASE = window.aksrtData.siteUrl ? window.aksrtData.siteUrl.replace(/\/$/, '') + '/wp-json/aksrt/v1' : '/wp-json/aksrt/v1';
|
||||
|
||||
function tt(key, zh) { return zh; }
|
||||
|
||||
function escapeHtml(value) {
|
||||
return String(value == null ? '' : value)
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
function escapeAttr(value) {
|
||||
return escapeHtml(value);
|
||||
}
|
||||
|
||||
// ===== Focus trap state =====
|
||||
let lastFocusedElement = null;
|
||||
|
||||
function getFocusableElements(container) {
|
||||
if (!container) return [];
|
||||
return Array.prototype.slice.call(container.querySelectorAll(
|
||||
'a[href], area[href], button:not([disabled]), input:not([disabled]):not([type="hidden"]),' +
|
||||
' select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'
|
||||
)).filter(function (el) {
|
||||
return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length);
|
||||
});
|
||||
}
|
||||
|
||||
function trapFocus(e, modal) {
|
||||
if (e.key !== 'Tab') return;
|
||||
const focusables = getFocusableElements(modal);
|
||||
if (!focusables.length) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
const first = focusables[0];
|
||||
const last = focusables[focusables.length - 1];
|
||||
if (e.shiftKey && document.activeElement === first) {
|
||||
e.preventDefault();
|
||||
last.focus();
|
||||
} else if (!e.shiftKey && document.activeElement === last) {
|
||||
e.preventDefault();
|
||||
first.focus();
|
||||
}
|
||||
}
|
||||
|
||||
// ===== Modal helper =====
|
||||
function buildModal() {
|
||||
let modal = document.getElementById('aksrt-dl-modal');
|
||||
if (modal) return modal;
|
||||
modal = document.createElement('div');
|
||||
modal.id = 'aksrt-dl-modal';
|
||||
modal.className = 'aksrt-dl-modal';
|
||||
modal.setAttribute('role', 'dialog');
|
||||
modal.setAttribute('aria-modal', 'true');
|
||||
modal.setAttribute('aria-hidden', 'true');
|
||||
modal.setAttribute('aria-labelledby', 'aksrt-dl-modal-title');
|
||||
modal.innerHTML =
|
||||
'<div class="aksrt-dl-modal__backdrop" data-close></div>' +
|
||||
'<div class="aksrt-dl-modal__panel" role="document" tabindex="-1">' +
|
||||
' <button type="button" class="aksrt-dl-modal__close" aria-label="' + tt('close', '关闭') + '" data-close>×</button>' +
|
||||
' <div class="aksrt-dl-modal__body" data-body></div>' +
|
||||
'</div>';
|
||||
document.body.appendChild(modal);
|
||||
|
||||
modal.addEventListener('click', function (e) {
|
||||
if (e.target.matches('[data-close]')) close();
|
||||
});
|
||||
modal.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'Escape' && modal.classList.contains('is-open')) {
|
||||
e.preventDefault();
|
||||
close();
|
||||
} else if (e.key === 'Tab' && modal.classList.contains('is-open')) {
|
||||
trapFocus(e, modal);
|
||||
}
|
||||
});
|
||||
return modal;
|
||||
}
|
||||
|
||||
function open(html, returnFocusEl) {
|
||||
// 记录调用方按钮以便关闭后回焦
|
||||
lastFocusedElement = returnFocusEl || document.activeElement;
|
||||
|
||||
const modal = buildModal();
|
||||
const body = modal.querySelector('[data-body]');
|
||||
// 给标题加 id,与 aria-labelledby 联动
|
||||
body.innerHTML = html.replace(/aksrt-dl-modal__title/, 'aksrt-dl-modal__title" id="aksrt-dl-modal-title');
|
||||
modal.classList.add('is-open');
|
||||
modal.setAttribute('aria-hidden', 'false');
|
||||
document.body.classList.add('aksrt-dl-modal-open');
|
||||
|
||||
// 进入后将焦点放在第一个可聚焦元素,否则放 panel
|
||||
setTimeout(function () {
|
||||
const focusables = getFocusableElements(modal);
|
||||
if (focusables.length) {
|
||||
focusables[0].focus();
|
||||
} else {
|
||||
modal.querySelector('.aksrt-dl-modal__panel').focus();
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function close() {
|
||||
const modal = document.getElementById('aksrt-dl-modal');
|
||||
if (!modal) return;
|
||||
modal.classList.remove('is-open');
|
||||
modal.setAttribute('aria-hidden', 'true');
|
||||
document.body.classList.remove('aksrt-dl-modal-open');
|
||||
// 焦点回到触发按钮
|
||||
if (lastFocusedElement && typeof lastFocusedElement.focus === 'function') {
|
||||
try { lastFocusedElement.focus(); } catch (_) { /* ignore */ }
|
||||
}
|
||||
lastFocusedElement = null;
|
||||
}
|
||||
|
||||
// ===== 错误提示渲染 =====
|
||||
function renderError(msg, data, returnFocusEl, code) {
|
||||
let title = tt('failed', '下载失败');
|
||||
let extra = '';
|
||||
|
||||
if (code === 'aksrt_need_login' && data && data.login_url) {
|
||||
title = tt('need_login', '请先登录');
|
||||
msg = tt('login_hint', '登录后即可继续下载,访客不可使用此资源。');
|
||||
extra = '<a class="btn-primary btn-sm" href="' + data.login_url + '">' + tt('go_login', '前往登录') + '</a>';
|
||||
} else if (code === 'aksrt_credits_insufficient') {
|
||||
title = tt('credit_low', '积分不够');
|
||||
const balance = typeof (data && data.balance) === 'number' ? data.balance : 0;
|
||||
const cost = typeof (data && data.cost) === 'number' ? data.cost : 0;
|
||||
msg = tt('credit_hint',
|
||||
'当前余额 ' + balance + ' 积分,需要 ' + cost + ' 积分。可通过签到、阅读、邀请好友等方式获取积分。'
|
||||
);
|
||||
} else if (data && data.login_url) {
|
||||
extra = '<a class="btn-primary btn-sm" href="' + data.login_url + '">' + tt('go_login', '前往登录') + '</a>';
|
||||
}
|
||||
|
||||
open(
|
||||
'<h3 class="aksrt-dl-modal__title">' + title + '</h3>' +
|
||||
'<p class="aksrt-dl-modal__msg">' + (msg || '') + '</p>' +
|
||||
(extra ? '<div class="aksrt-dl-modal__actions">' + extra + '</div>' : ''),
|
||||
returnFocusEl
|
||||
);
|
||||
}
|
||||
|
||||
// ===== 成功渲染 =====
|
||||
function renderSuccess(payload, returnFocusEl) {
|
||||
const code = String(payload.extract_code || '').trim();
|
||||
const has = !!payload.has_extract || code !== '';
|
||||
const safeCode = escapeHtml(code);
|
||||
const safeCodeAttr = escapeAttr(code);
|
||||
const dlUrl = escapeAttr(payload.dl_url || '#');
|
||||
const extractHtml = code !== ''
|
||||
? '<div class="aksrt-dl-modal__row"><span class="aksrt-dl-modal__label">' + tt('extract', '提取码') + '</span><code class="aksrt-dl-modal__code">' + safeCode + '</code><button type="button" class="aksrt-dl-modal__copy" data-copy="' + safeCodeAttr + '"><span class="aksrt-dl-modal__copy-text">' + tt('copy', '复制') + '</span></button></div>'
|
||||
: (has ? '<p class="aksrt-dl-modal__msg aksrt-dl-modal__msg--warn">' + tt('extract_missing', '下载源标记了提取码,但接口未返回具体内容,请检查资源下载源的 extract_code 字段。') + '</p>' : '');
|
||||
open(
|
||||
'<h3 class="aksrt-dl-modal__title">' + tt('ready', '下载已就绪') + '</h3>' +
|
||||
(extractHtml || '<p class="aksrt-dl-modal__msg">' + tt('hint', '点击下方按钮开始下载,链接 10 分钟内有效。') + '</p>') +
|
||||
'<div class="aksrt-dl-modal__actions">' +
|
||||
' <a class="btn-primary aksrt-dl-modal__download" href="' + dlUrl + '" target="_blank" rel="noopener noreferrer">' + tt('go', '立即下载') + '</a>' +
|
||||
(typeof payload.balance === 'number' ? ' <span class="aksrt-dl-modal__balance">' + tt('balance', '余额:') + payload.balance + '</span>' : '') +
|
||||
'</div>',
|
||||
returnFocusEl
|
||||
);
|
||||
|
||||
// 复制按钮
|
||||
document.querySelectorAll('[data-copy]').forEach(function (btn) {
|
||||
btn.addEventListener('click', function () {
|
||||
const text = btn.getAttribute('data-copy') || '';
|
||||
const label = btn.querySelector('.aksrt-dl-modal__copy-text') || btn;
|
||||
if (navigator.clipboard) {
|
||||
navigator.clipboard.writeText(text).then(function () {
|
||||
label.textContent = tt('copied', '已复制');
|
||||
setTimeout(function () { label.textContent = tt('copy', '复制'); }, 2000);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ===== 主流程 =====
|
||||
function collectCaptchaPayload(sourceEl) {
|
||||
// 优先从触发按钮所属的下载卡片中查找验证码容器(支持双下载框场景:侧栏+移动端)
|
||||
var container = null;
|
||||
if (sourceEl) {
|
||||
var box = sourceEl.closest('.resource-download-box');
|
||||
if (box) container = box.querySelector('[data-aksrt-download-captcha]');
|
||||
}
|
||||
// 回退到全局查找
|
||||
if (!container) container = document.querySelector('[data-aksrt-download-captcha]');
|
||||
if (!container) return {};
|
||||
const out = {};
|
||||
const keys = [
|
||||
'captcha_verified',
|
||||
'cf_turnstile_response',
|
||||
'tencent_ticket', 'tencent_randstr', 'tencent_sid',
|
||||
'geetest_lot_number', 'geetest_captcha_output', 'geetest_pass_token', 'geetest_gen_time',
|
||||
'aliyun_captcha_verify_param',
|
||||
];
|
||||
keys.forEach(function (k) {
|
||||
const el = container.querySelector('input[name="' + k + '"]');
|
||||
if (el && el.value !== '') out[k] = el.value;
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
function isCaptchaActive() {
|
||||
const card = document.querySelector('.resource-download-box');
|
||||
if (!card) return false;
|
||||
return card.getAttribute('data-captcha') === '1';
|
||||
}
|
||||
|
||||
function ensureCaptchaThen(callback) {
|
||||
if (!isCaptchaActive()) { callback(); return; }
|
||||
const state = window.AKSRTCaptchaState;
|
||||
const scene = state && state.scenes && state.scenes.download;
|
||||
if (!scene || typeof scene.verify !== 'function') {
|
||||
// captcha 组件还未就绪,直接发,由后端兜底报错
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
scene.verify(function () { callback(); });
|
||||
}
|
||||
|
||||
function performDownloadRequest(button) {
|
||||
const card = button.closest('.resource-download-box');
|
||||
if (!card) return;
|
||||
const postId = parseInt(card.getAttribute('data-post-id'), 10);
|
||||
const sourceIndex = parseInt(button.getAttribute('data-source-index'), 10);
|
||||
if (!postId || isNaN(sourceIndex)) return;
|
||||
|
||||
button.disabled = true;
|
||||
const original = button.innerHTML;
|
||||
button.innerHTML = '<i class="fas fa-spinner fa-spin" aria-hidden="true"></i> ' + tt('processing', '处理中…');
|
||||
|
||||
const restNonce = window.aksrtData.restNonce || '';
|
||||
const captchaPayload = collectCaptchaPayload(button);
|
||||
|
||||
fetch(REST_BASE + '/download/request', {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-WP-Nonce': restNonce,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
post_id: postId,
|
||||
source_index: sourceIndex,
|
||||
captcha: captchaPayload,
|
||||
}),
|
||||
})
|
||||
.then(function (resp) { return resp.json().then(function (j) { return { ok: resp.ok, json: j }; }); })
|
||||
.then(function (r) {
|
||||
button.disabled = false;
|
||||
button.innerHTML = original;
|
||||
if (!r.ok || (r.json && r.json.code)) {
|
||||
renderError(r.json.message || tt('default_err', '请稍后重试'), r.json.data || {}, button, r.json.code);
|
||||
// 验证码已被消费,重置以便用户重试
|
||||
try {
|
||||
const scene = window.AKSRTCaptchaState && window.AKSRTCaptchaState.scenes && window.AKSRTCaptchaState.scenes.download;
|
||||
if (scene && typeof scene.reset === 'function') scene.reset();
|
||||
} catch (_) { /* ignore */ }
|
||||
return;
|
||||
}
|
||||
renderSuccess(r.json, button);
|
||||
})
|
||||
.catch(function () {
|
||||
button.disabled = false;
|
||||
button.innerHTML = original;
|
||||
renderError(tt('network_err', '网络错误,请稍后重试'), {}, button);
|
||||
});
|
||||
}
|
||||
|
||||
function requestDownload(button) {
|
||||
ensureCaptchaThen(function () {
|
||||
performDownloadRequest(button);
|
||||
});
|
||||
}
|
||||
|
||||
// ===== 积分不足按钮(前置拦截,不发请求) =====
|
||||
function showLowCreditModal(button) {
|
||||
const balance = parseInt(button.getAttribute('data-balance'), 10) || 0;
|
||||
const cost = parseInt(button.getAttribute('data-cost'), 10) || 0;
|
||||
renderError('', { balance: balance, cost: cost }, button, 'aksrt_credits_insufficient');
|
||||
}
|
||||
|
||||
// ===== 事件绑定 =====
|
||||
document.addEventListener('click', function (e) {
|
||||
const lowBtn = e.target.closest('[data-action="aksrt-need-credits"]');
|
||||
if (lowBtn) {
|
||||
e.preventDefault();
|
||||
showLowCreditModal(lowBtn);
|
||||
return;
|
||||
}
|
||||
|
||||
const btn = e.target.closest('[data-action="aksrt-download"]');
|
||||
if (!btn) return;
|
||||
if (btn.disabled || btn.getAttribute('aria-disabled') === 'true') return;
|
||||
e.preventDefault();
|
||||
requestDownload(btn);
|
||||
});
|
||||
|
||||
// ===== 注入 modal 基础样式(避免必须额外加载 CSS)=====
|
||||
const style = document.createElement('style');
|
||||
style.textContent =
|
||||
'.aksrt-dl-modal{position:fixed;inset:0;z-index:10000;display:none;}' +
|
||||
'.aksrt-dl-modal.is-open{display:flex;align-items:center;justify-content:center;}' +
|
||||
'.aksrt-dl-modal__backdrop{position:absolute;inset:0;background:rgba(0,0,0,.55);}' +
|
||||
'.aksrt-dl-modal__panel{position:relative;background:#fff;border-radius:14px;padding:26px 28px 24px;width:min(420px,calc(100vw - 32px));box-shadow:0 24px 56px rgba(15,23,42,.24);color:#111827;}' +
|
||||
'.aksrt-dl-modal__close{position:absolute;top:10px;right:12px;background:transparent;border:0;font-size:24px;line-height:1;cursor:pointer;color:#6b7280;}' +
|
||||
'.aksrt-dl-modal__title{font:700 20px/1.3 inherit;margin:0 28px 18px 0;color:#111827;}' +
|
||||
'.aksrt-dl-modal__msg{margin:0 0 18px;color:#4b5563;font-size:14px;line-height:1.65;}' +
|
||||
'.aksrt-dl-modal__msg--warn{color:#92400e;background:transparent;border:0;border-top:1px solid #fde68a;border-bottom:1px solid #fde68a;padding:12px 0;}' +
|
||||
'.aksrt-dl-modal__row{display:grid;grid-template-columns:64px minmax(0,1fr) 72px;align-items:center;gap:12px;margin:0 0 18px;padding:12px 0;border-top:1px solid #e5e7eb;border-bottom:1px solid #e5e7eb;}' +
|
||||
'.aksrt-dl-modal__label{font-size:13px;font-weight:600;color:#6b7280;white-space:nowrap;}' +
|
||||
'.aksrt-dl-modal__code{display:block;min-width:0;color:#111827;font:800 18px/1.25 ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;letter-spacing:.06em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}' +
|
||||
'.aksrt-dl-modal__copy{appearance:none!important;display:inline-flex!important;align-items:center!important;justify-content:center!important;width:72px!important;height:32px!important;background:#eff6ff!important;border:1px solid #bfdbfe!important;border-radius:8px!important;padding:0!important;cursor:pointer!important;color:#2563eb!important;-webkit-text-fill-color:#2563eb!important;font-size:0!important;font-weight:700!important;line-height:1!important;font-family:inherit!important;text-indent:0!important;opacity:1!important;visibility:visible!important;white-space:nowrap!important;overflow:visible!important;}' +
|
||||
'.aksrt-dl-modal__copy::before,.aksrt-dl-modal__copy::after{content:none!important;display:none!important;}' +
|
||||
'.aksrt-dl-modal__copy:hover{background:#dbeafe!important;border-color:#93c5fd!important;color:#1d4ed8!important;-webkit-text-fill-color:#1d4ed8!important;}' +
|
||||
'.aksrt-dl-modal__copy-text{display:inline-flex!important;align-items:center!important;justify-content:center!important;position:relative!important;z-index:2!important;color:#2563eb!important;-webkit-text-fill-color:#2563eb!important;font-size:13px!important;font-weight:700!important;line-height:1!important;font-family:inherit!important;text-indent:0!important;opacity:1!important;visibility:visible!important;white-space:nowrap!important;}' +
|
||||
'.aksrt-dl-modal__copy:hover .aksrt-dl-modal__copy-text{color:#1d4ed8!important;-webkit-text-fill-color:#1d4ed8!important;}' +
|
||||
'.aksrt-dl-modal__actions{display:flex;align-items:center;gap:12px;padding-top:4px;}' +
|
||||
'.aksrt-dl-modal__download{min-height:40px;padding:0 18px;border-radius:9px;display:inline-flex;align-items:center;justify-content:center;text-decoration:none;}' +
|
||||
'.aksrt-dl-modal__balance{font-size:13px;color:#6b7280;margin-left:auto;white-space:nowrap;}' +
|
||||
'@media(max-width:480px){.aksrt-dl-modal__panel{padding:24px 20px 22px;}.aksrt-dl-modal__row{grid-template-columns:1fr 72px;gap:8px 12px;}.aksrt-dl-modal__label{grid-column:1 / -1;}.aksrt-dl-modal__code{font-size:17px;}.aksrt-dl-modal__actions{align-items:flex-start;flex-direction:column;}.aksrt-dl-modal__download{width:100%;}.aksrt-dl-modal__balance{margin-left:0;}}' +
|
||||
'body.aksrt-dl-modal-open{overflow:hidden;}';
|
||||
document.head.appendChild(style);
|
||||
})();
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* AKSRT CMS Home Modules
|
||||
*
|
||||
* - Tab 切换:[data-aksrt-tabs] / [data-tab-target] / [data-tab-id]
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function initTabs(scope) {
|
||||
const tablists = (scope || document).querySelectorAll('[data-aksrt-tabs]');
|
||||
tablists.forEach(function (list) {
|
||||
const buttons = list.querySelectorAll('.home-module__tab');
|
||||
const section = list.closest('.home-module--tabs');
|
||||
if (!section) return;
|
||||
const panels = section.querySelectorAll('.home-module__tab-panel');
|
||||
|
||||
buttons.forEach(function (btn) {
|
||||
btn.addEventListener('click', function () {
|
||||
const target = btn.getAttribute('data-tab-target');
|
||||
if (!target) return;
|
||||
|
||||
buttons.forEach(function (b) {
|
||||
b.classList.toggle('is-active', b === btn);
|
||||
b.setAttribute('aria-selected', b === btn ? 'true' : 'false');
|
||||
});
|
||||
panels.forEach(function (p) {
|
||||
const isMatch = p.getAttribute('data-tab-id') === target;
|
||||
p.classList.toggle('is-active', isMatch);
|
||||
if (isMatch) {
|
||||
p.removeAttribute('hidden');
|
||||
} else {
|
||||
p.setAttribute('hidden', '');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 监听 postMessage:iframe 预览模式下接收 reload 请求
|
||||
window.addEventListener('message', function (e) {
|
||||
if (!e.data || e.data.type !== 'aksrt-preview-reload') return;
|
||||
// 简单做:直接 reload
|
||||
window.location.reload();
|
||||
});
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', function () { initTabs(); });
|
||||
} else {
|
||||
initTabs();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,147 @@
|
||||
/**
|
||||
* AKSRT Color Extract
|
||||
*
|
||||
* Extracts dominant colors from images and applies them as dynamic accents.
|
||||
* Uses canvas-based color sampling — no external dependencies.
|
||||
*
|
||||
* Usage:
|
||||
* <img data-aksrt-color-extract data-aksrt-color-target=".card">
|
||||
* <!-- Will set --aksrt-dynamic-color on .card based on image colors -->
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var canvas = null;
|
||||
var ctx = null;
|
||||
|
||||
function getCanvas() {
|
||||
if (!canvas) {
|
||||
canvas = document.createElement('canvas');
|
||||
canvas.width = 40;
|
||||
canvas.height = 40;
|
||||
ctx = canvas.getContext('2d', { willReadFrequently: true });
|
||||
}
|
||||
return { canvas: canvas, ctx: ctx };
|
||||
}
|
||||
|
||||
function extractColor(img) {
|
||||
try {
|
||||
var c = getCanvas();
|
||||
c.ctx.drawImage(img, 0, 0, 40, 40);
|
||||
var data = c.ctx.getImageData(0, 0, 40, 40).data;
|
||||
|
||||
var r = 0, g = 0, b = 0, count = 0;
|
||||
var step = 4; // sample every 4th pixel for speed
|
||||
|
||||
for (var i = 0; i < data.length; i += 4 * step) {
|
||||
var pr = data[i], pg = data[i + 1], pb = data[i + 2];
|
||||
// Skip very dark or very light pixels
|
||||
var brightness = (pr + pg + pb) / 3;
|
||||
if (brightness < 20 || brightness > 240) continue;
|
||||
// Skip near-transparent
|
||||
if (data[i + 3] < 128) continue;
|
||||
|
||||
r += pr;
|
||||
g += pg;
|
||||
b += pb;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count === 0) return null;
|
||||
|
||||
r = Math.round(r / count);
|
||||
g = Math.round(g / count);
|
||||
b = Math.round(b / count);
|
||||
|
||||
return { r: r, g: g, b: b, hex: rgbToHex(r, g, b) };
|
||||
} catch (e) {
|
||||
// CORS or tainted canvas — silently fail
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function rgbToHex(r, g, b) {
|
||||
return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
|
||||
}
|
||||
|
||||
function lighten(r, g, b, amount) {
|
||||
return rgbToHex(
|
||||
Math.min(255, r + amount),
|
||||
Math.min(255, g + amount),
|
||||
Math.min(255, b + amount)
|
||||
);
|
||||
}
|
||||
|
||||
function darken(r, g, b, amount) {
|
||||
return rgbToHex(
|
||||
Math.max(0, r - amount),
|
||||
Math.max(0, g - amount),
|
||||
Math.max(0, b - amount)
|
||||
);
|
||||
}
|
||||
|
||||
function applyColor(target, color) {
|
||||
if (!target || !color) return;
|
||||
|
||||
var r = color.r, g = color.g, b = color.b;
|
||||
target.style.setProperty('--aksrt-dynamic-color', color.hex);
|
||||
target.style.setProperty('--aksrt-dynamic-color-rgb', r + ',' + g + ',' + b);
|
||||
target.style.setProperty('--aksrt-dynamic-color-light', lighten(r, g, b, 60));
|
||||
target.style.setProperty('--aksrt-dynamic-color-dark', darken(r, g, b, 40));
|
||||
|
||||
// Add a subtle tinted background if target doesn't already have one
|
||||
if (!target.style.background && !target.style.backgroundColor) {
|
||||
target.style.setProperty('--aksrt-dynamic-bg', 'rgba(' + r + ',' + g + ',' + b + ',0.05)');
|
||||
}
|
||||
}
|
||||
|
||||
function processImage(img) {
|
||||
if (img.dataset.aksrtColorDone) return;
|
||||
|
||||
// Need crossOrigin for canvas access
|
||||
if (!img.crossOrigin && img.src.indexOf(window.location.origin) !== 0) {
|
||||
img.crossOrigin = 'anonymous';
|
||||
}
|
||||
|
||||
function extract() {
|
||||
var color = extractColor(img);
|
||||
if (!color) return;
|
||||
|
||||
img.dataset.aksrtColorDone = '1';
|
||||
|
||||
var targetSelector = img.dataset.aksrtColorTarget;
|
||||
var target = targetSelector
|
||||
? img.closest(targetSelector) || document.querySelector(targetSelector)
|
||||
: img.parentElement;
|
||||
|
||||
applyColor(target, color);
|
||||
}
|
||||
|
||||
if (img.complete && img.naturalWidth > 0) {
|
||||
extract();
|
||||
} else {
|
||||
img.addEventListener('load', extract, { once: true });
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
document.querySelectorAll('[data-aksrt-color-extract]').forEach(processImage);
|
||||
}
|
||||
|
||||
// Public API
|
||||
window.AksrtColorExtract = {
|
||||
extract: extractColor,
|
||||
apply: applyColor,
|
||||
process: processImage,
|
||||
init: init
|
||||
};
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,241 @@
|
||||
/**
|
||||
* AKSRT Comment Actions client
|
||||
*
|
||||
* Single client for per-comment actions via REST aksrt/v1:
|
||||
* like / edit / delete / moderate (approve|hold|spam) / pin
|
||||
*
|
||||
* Comment SUBMISSION is owned by main.js initCommentSystem() (the native
|
||||
* wp-comments-post.php flow, which runs captcha verification, rate limiting and
|
||||
* the moderation pipeline, then re-renders the list through the canonical
|
||||
* server callback). This file deliberately does NOT bind the submit form, so
|
||||
* there is exactly one comment-submit contract.
|
||||
*
|
||||
* Markup contract (rendered by aksrt_comment_callback, identical on first
|
||||
* paint, load-more and post-submit reload):
|
||||
* li.aksrt-comment[data-comment-id]
|
||||
* .aksrt-comment__text (content)
|
||||
* .aksrt-comment__actions
|
||||
* [data-comment-action="like|edit|delete|approve|hold|spam|pin"]
|
||||
*
|
||||
* Depends on: aksrtData.restNonce (wp_rest) + aksrtData.siteUrl.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
if (!window.aksrtData) return;
|
||||
|
||||
var COMMENT_SELECTOR = '.aksrt-comment, .comment';
|
||||
var CONTENT_SELECTOR = '.aksrt-comment__text';
|
||||
|
||||
var REST_BASE = (aksrtData.siteUrl || '').replace(/\/$/, '') + '/wp-json/aksrt/v1';
|
||||
var REST_NONCE = aksrtData.restNonce || '';
|
||||
|
||||
function restPost(endpoint, body) {
|
||||
return fetch(REST_BASE + endpoint, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', 'X-WP-Nonce': REST_NONCE },
|
||||
body: JSON.stringify(body),
|
||||
credentials: 'same-origin'
|
||||
}).then(function (r) { return r.json(); });
|
||||
}
|
||||
|
||||
function notify(message, type) {
|
||||
if (typeof window.AksrtToast === 'function') { window.AksrtToast(message, type || 'info'); return; }
|
||||
if (typeof window.aksrtToast === 'function') { window.aksrtToast(message, type || 'info'); return; }
|
||||
if (typeof window.showToast === 'function') { window.showToast(message, type || 'info'); return; }
|
||||
if (type === 'error') { window.alert(message); }
|
||||
}
|
||||
|
||||
function getCommentId(el) {
|
||||
return parseInt(el.getAttribute('data-comment-id') || (el.id || '').replace('comment-', ''), 10) || 0;
|
||||
}
|
||||
|
||||
// ── Comment actions (event delegation) ───────────────────────────
|
||||
|
||||
document.addEventListener('click', function (e) {
|
||||
var actionBtn = e.target.closest('[data-comment-action]');
|
||||
if (!actionBtn) return;
|
||||
|
||||
var action = actionBtn.getAttribute('data-comment-action');
|
||||
var commentEl = actionBtn.closest(COMMENT_SELECTOR);
|
||||
if (!commentEl) return;
|
||||
|
||||
var commentId = getCommentId(commentEl);
|
||||
if (!commentId) return;
|
||||
|
||||
switch (action) {
|
||||
case 'like': handleLike(actionBtn, commentId); break;
|
||||
case 'edit': handleEdit(commentEl); break;
|
||||
case 'save-edit': saveEdit(commentEl, commentId, actionBtn); break;
|
||||
case 'cancel-edit': cancelEdit(commentEl); break;
|
||||
case 'delete': handleDelete(commentEl, commentId); break;
|
||||
case 'pin': handlePin(commentEl, actionBtn, commentId); break;
|
||||
case 'approve':
|
||||
case 'hold':
|
||||
case 'spam': handleModerate(commentEl, commentId, action); break;
|
||||
}
|
||||
});
|
||||
|
||||
function handleLike(btn, commentId) {
|
||||
if (btn.dataset.busy === '1') return;
|
||||
btn.dataset.busy = '1';
|
||||
var nextActive = btn.getAttribute('data-active') !== '1';
|
||||
|
||||
restPost('/comment/like', { comment_id: commentId, active: nextActive })
|
||||
.then(function (result) {
|
||||
if (!result.success) { notify((result.data && result.data.message) || result.message || '操作失败', 'error'); return; }
|
||||
var active = !!(result.data && result.data.active);
|
||||
var count = (result.data && result.data.count) || 0;
|
||||
btn.setAttribute('data-active', active ? '1' : '0');
|
||||
btn.setAttribute('aria-pressed', active ? 'true' : 'false');
|
||||
btn.classList.toggle('is-active', active);
|
||||
var icon = btn.querySelector('i');
|
||||
if (icon) { icon.classList.toggle('fas', active); icon.classList.toggle('far', !active); }
|
||||
var countEl = btn.querySelector('.aksrt-comment__like-count');
|
||||
if (countEl) {
|
||||
countEl.textContent = String(count);
|
||||
if (count > 0) { countEl.removeAttribute('hidden'); } else { countEl.setAttribute('hidden', ''); }
|
||||
}
|
||||
})
|
||||
.catch(function () { notify('网络错误', 'error'); })
|
||||
.finally(function () { btn.dataset.busy = ''; });
|
||||
}
|
||||
|
||||
function handleEdit(commentEl) {
|
||||
var contentEl = commentEl.querySelector(CONTENT_SELECTOR);
|
||||
if (!contentEl || commentEl.querySelector('.aksrt-comment-edit-form')) return;
|
||||
|
||||
var temp = document.createElement('div');
|
||||
temp.innerHTML = contentEl.innerHTML;
|
||||
var originalText = (temp.textContent || temp.innerText || '').trim();
|
||||
|
||||
var editForm = document.createElement('div');
|
||||
editForm.className = 'aksrt-comment-edit-form';
|
||||
editForm.innerHTML =
|
||||
'<textarea class="aksrt-comment-edit-textarea"></textarea>' +
|
||||
'<div class="aksrt-comment-actions">' +
|
||||
'<button type="button" data-comment-action="save-edit" class="aksrt-comment-action-btn aksrt-comment-action-btn--success">保存</button>' +
|
||||
'<button type="button" data-comment-action="cancel-edit" class="aksrt-comment-action-btn">取消</button>' +
|
||||
'</div>';
|
||||
editForm.querySelector('textarea').value = originalText;
|
||||
|
||||
contentEl.style.display = 'none';
|
||||
contentEl.parentNode.insertBefore(editForm, contentEl.nextSibling);
|
||||
editForm.querySelector('textarea').focus();
|
||||
}
|
||||
|
||||
function cancelEdit(commentEl) {
|
||||
var editForm = commentEl.querySelector('.aksrt-comment-edit-form');
|
||||
if (!editForm) return;
|
||||
var contentEl = commentEl.querySelector(CONTENT_SELECTOR);
|
||||
if (contentEl) contentEl.style.display = '';
|
||||
editForm.remove();
|
||||
}
|
||||
|
||||
function saveEdit(commentEl, commentId, saveBtn) {
|
||||
var editForm = commentEl.querySelector('.aksrt-comment-edit-form');
|
||||
if (!editForm) return;
|
||||
var textarea = editForm.querySelector('.aksrt-comment-edit-textarea');
|
||||
var newContent = textarea ? textarea.value.trim() : '';
|
||||
if (!newContent) return;
|
||||
|
||||
if (saveBtn) { saveBtn.disabled = true; saveBtn.textContent = '保存中...'; }
|
||||
|
||||
restPost('/comment/edit', { comment_id: commentId, content: newContent })
|
||||
.then(function (result) {
|
||||
if (result.success) {
|
||||
var contentEl = commentEl.querySelector(CONTENT_SELECTOR);
|
||||
if (contentEl) { contentEl.innerHTML = result.data.content; contentEl.style.display = ''; }
|
||||
editForm.remove();
|
||||
} else {
|
||||
notify((result.data && result.data.message) || result.message || '编辑失败', 'error');
|
||||
if (saveBtn) { saveBtn.disabled = false; saveBtn.textContent = '保存'; }
|
||||
}
|
||||
})
|
||||
.catch(function () {
|
||||
notify('网络错误', 'error');
|
||||
if (saveBtn) { saveBtn.disabled = false; saveBtn.textContent = '保存'; }
|
||||
});
|
||||
}
|
||||
|
||||
function handleDelete(commentEl, commentId) {
|
||||
var msg = (window.aksrt && aksrt.__) ? aksrt.__('comment_confirm_delete', '确定要删除这条评论吗?') : '确定要删除这条评论吗?';
|
||||
var doDelete = function () {
|
||||
restPost('/comment/delete', { comment_id: commentId })
|
||||
.then(function (result) {
|
||||
if (result.success) {
|
||||
commentEl.style.transition = 'opacity 0.3s, max-height 0.3s';
|
||||
commentEl.style.maxHeight = commentEl.scrollHeight + 'px';
|
||||
requestAnimationFrame(function () {
|
||||
commentEl.style.opacity = '0';
|
||||
commentEl.style.maxHeight = '0';
|
||||
commentEl.style.overflow = 'hidden';
|
||||
});
|
||||
setTimeout(function () { commentEl.remove(); }, 300);
|
||||
} else {
|
||||
notify((result.data && result.data.message) || result.message || '删除失败', 'error');
|
||||
}
|
||||
})
|
||||
.catch(function () { notify('网络错误', 'error'); });
|
||||
};
|
||||
|
||||
if (window.aksrt && aksrt.confirm) {
|
||||
aksrt.confirm(msg).then(function (ok) { if (ok) doDelete(); });
|
||||
} else if (window.confirm(msg)) {
|
||||
doDelete();
|
||||
}
|
||||
}
|
||||
|
||||
function handlePin(commentEl, btn, commentId) {
|
||||
var nextPinned = btn.getAttribute('data-pinned') !== '1';
|
||||
|
||||
restPost('/comment/pin', { comment_id: commentId, pinned: nextPinned })
|
||||
.then(function (result) {
|
||||
if (!result.success) { notify((result.data && result.data.message) || result.message || '操作失败', 'error'); return; }
|
||||
var pinned = !!(result.data && result.data.pinned);
|
||||
btn.setAttribute('data-pinned', pinned ? '1' : '0');
|
||||
btn.innerHTML = '<i class="fas fa-thumbtack" aria-hidden="true"></i> ' + (pinned ? '取消置顶' : '置顶');
|
||||
commentEl.classList.toggle('aksrt-comment--pinned', pinned);
|
||||
syncPinnedBadge(commentEl, pinned);
|
||||
notify(result.message || (pinned ? '评论已置顶。' : '已取消置顶。'), 'success');
|
||||
})
|
||||
.catch(function () { notify('网络错误', 'error'); });
|
||||
}
|
||||
|
||||
function syncPinnedBadge(commentEl, pinned) {
|
||||
var header = commentEl.querySelector('.aksrt-comment__header');
|
||||
if (!header) return;
|
||||
var badge = header.querySelector('.aksrt-comment__badge--pinned');
|
||||
if (pinned && !badge) {
|
||||
badge = document.createElement('span');
|
||||
badge.className = 'aksrt-comment__badge aksrt-comment__badge--pinned';
|
||||
badge.innerHTML = '<i class="fas fa-thumbtack" aria-hidden="true"></i> 置顶';
|
||||
var time = header.querySelector('.aksrt-comment__time');
|
||||
header.insertBefore(badge, time || null);
|
||||
} else if (!pinned && badge) {
|
||||
badge.remove();
|
||||
}
|
||||
}
|
||||
|
||||
function handleModerate(commentEl, commentId, action) {
|
||||
restPost('/comment/moderate', { comment_id: commentId, status: action })
|
||||
.then(function (result) {
|
||||
if (result.success) {
|
||||
commentEl.setAttribute('data-comment-status', result.data.status === 'approved' ? '1' : (result.data.status === 'spam' ? 'spam' : '0'));
|
||||
commentEl.style.opacity = '0.6';
|
||||
setTimeout(function () { commentEl.style.opacity = '1'; }, 400);
|
||||
if (action === 'approve') {
|
||||
var note = commentEl.querySelector('.awaiting-moderation');
|
||||
if (note) note.remove();
|
||||
}
|
||||
notify(result.message || '操作成功。', 'success');
|
||||
} else {
|
||||
notify((result.data && result.data.message) || result.message || '操作失败', 'error');
|
||||
}
|
||||
})
|
||||
.catch(function () { notify('网络错误', 'error'); });
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,422 @@
|
||||
/**
|
||||
* AKSRT Comment Tools
|
||||
*
|
||||
* Handles comment toolbar actions (emoji, code, bold, italic, quote, link),
|
||||
* Ctrl+Enter submit, and quick quote from selection.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var COMMENT_TOOLS = {
|
||||
emojiPicker: null,
|
||||
quickReplyPanel: null,
|
||||
quickQuoteEnabled: false,
|
||||
quickReplyTemplates: [
|
||||
'感谢分享,这篇内容对我很有帮助!',
|
||||
'已收藏,后面会按这个思路继续研究。',
|
||||
'这个细节讲得很清楚,学习了。',
|
||||
'我这边也复现成功了,补充一点经验:',
|
||||
'先留个脚印,等我测试后再回来反馈结果。'
|
||||
],
|
||||
|
||||
init: function () {
|
||||
this.bindToolbar();
|
||||
this.bindCtrlEnter();
|
||||
this.bindQuickQuote();
|
||||
},
|
||||
|
||||
/**
|
||||
* Insert text at cursor position in textarea
|
||||
*/
|
||||
insertAtCursor: function (textarea, before, after) {
|
||||
if (!textarea) return;
|
||||
var start = textarea.selectionStart;
|
||||
var end = textarea.selectionEnd;
|
||||
var text = textarea.value;
|
||||
var selected = text.substring(start, end);
|
||||
var replacement = before + (selected || '') + (after || '');
|
||||
textarea.value = text.substring(0, start) + replacement + text.substring(end);
|
||||
textarea.focus();
|
||||
var newPos = start + before.length + selected.length;
|
||||
textarea.setSelectionRange(newPos, newPos);
|
||||
},
|
||||
|
||||
/**
|
||||
* Wrap selected text with markers
|
||||
*/
|
||||
wrapSelection: function (textarea, marker) {
|
||||
this.insertAtCursor(textarea, marker, marker);
|
||||
},
|
||||
|
||||
uploadImage: function (btn, textarea) {
|
||||
if (!window.aksrtData || !aksrtData.commentUploadEnabled || !aksrtData.commentUploadUrl) {
|
||||
return;
|
||||
}
|
||||
|
||||
var input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
input.accept = 'image/jpeg,image/png,image/gif,image/webp';
|
||||
input.style.display = 'none';
|
||||
document.body.appendChild(input);
|
||||
|
||||
var self = this;
|
||||
input.addEventListener('change', function () {
|
||||
var file = input.files && input.files[0];
|
||||
if (!file) {
|
||||
input.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
var maxSize = parseInt(aksrtData.commentUploadMaxSize || 0, 10) || (2 * 1024 * 1024);
|
||||
if (file.size > maxSize) {
|
||||
window.alert('图片大小不能超过 2MB');
|
||||
input.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
btn.disabled = true;
|
||||
var originalHtml = btn.innerHTML;
|
||||
btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
|
||||
|
||||
var formData = new FormData();
|
||||
formData.append('comment_image', file);
|
||||
|
||||
fetch(aksrtData.commentUploadUrl, {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'X-WP-Nonce': aksrtData.restNonce || ''
|
||||
}
|
||||
})
|
||||
.then(function (response) { return response.json(); })
|
||||
.then(function (payload) {
|
||||
if (!payload || payload.success !== true || !payload.url) {
|
||||
throw new Error((payload && payload.message) || '上传失败');
|
||||
}
|
||||
self.insertAtCursor(textarea, '[img]' + payload.url + '[/img]', '');
|
||||
})
|
||||
.catch(function (error) {
|
||||
window.alert(error && error.message ? error.message : '上传失败');
|
||||
})
|
||||
.finally(function () {
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = originalHtml;
|
||||
input.remove();
|
||||
});
|
||||
});
|
||||
|
||||
input.click();
|
||||
},
|
||||
|
||||
/**
|
||||
* Bind toolbar button actions
|
||||
*/
|
||||
bindToolbar: function () {
|
||||
var self = this;
|
||||
document.addEventListener('click', function (e) {
|
||||
var btn = e.target.closest('[data-toolbar-action]');
|
||||
if (!btn) return;
|
||||
|
||||
var action = btn.getAttribute('data-toolbar-action');
|
||||
var form = btn.closest('.comment-form');
|
||||
var textarea = form ? form.querySelector('textarea') : document.getElementById('comment');
|
||||
if (!textarea) return;
|
||||
|
||||
switch (action) {
|
||||
case 'bold':
|
||||
self.wrapSelection(textarea, '**');
|
||||
break;
|
||||
case 'italic':
|
||||
self.wrapSelection(textarea, '*');
|
||||
break;
|
||||
case 'code':
|
||||
var selected = textarea.value.substring(textarea.selectionStart, textarea.selectionEnd);
|
||||
if (selected.indexOf('\n') >= 0) {
|
||||
self.insertAtCursor(textarea, '```\n', '\n```');
|
||||
} else {
|
||||
self.wrapSelection(textarea, '`');
|
||||
}
|
||||
break;
|
||||
case 'quote':
|
||||
self.insertAtCursor(textarea, '> ', '\n');
|
||||
break;
|
||||
case 'link':
|
||||
self.askUrl(btn, '链接地址', function (url) {
|
||||
if (url) {
|
||||
var linkText = textarea.value.substring(textarea.selectionStart, textarea.selectionEnd) || '链接文字';
|
||||
self.insertAtCursor(textarea, '[' + linkText + '](' + url + ')');
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'image':
|
||||
self.askUrl(btn, '图片地址', function (url) {
|
||||
if (url) {
|
||||
self.insertAtCursor(textarea, '[img]' + url + '[/img]');
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'upload-image':
|
||||
self.uploadImage(btn, textarea);
|
||||
break;
|
||||
case 'emoji':
|
||||
self.toggleEmojiPicker(btn, textarea);
|
||||
break;
|
||||
case 'quick-reply':
|
||||
self.toggleQuickReply(btn, textarea);
|
||||
break;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Inline URL input — replaces native prompt() with a small input below the button.
|
||||
*/
|
||||
askUrl: function (anchor, placeholder, callback) {
|
||||
var existing = document.querySelector('.aksrt-inline-url-input');
|
||||
if (existing) existing.remove();
|
||||
|
||||
var input = document.createElement('input');
|
||||
input.type = 'url';
|
||||
input.className = 'aksrt-inline-url-input';
|
||||
input.placeholder = placeholder || 'https://';
|
||||
input.value = 'https://';
|
||||
input.style.cssText = 'display:block;width:100%;max-width:320px;margin:4px 0;padding:6px 10px;border:1px solid #dce3ec;border-radius:8px;font-size:13px;';
|
||||
|
||||
var parent = anchor.parentElement;
|
||||
parent.insertBefore(input, anchor.nextSibling);
|
||||
input.focus();
|
||||
input.select();
|
||||
|
||||
function done() {
|
||||
var val = input.value.trim();
|
||||
input.remove();
|
||||
callback(val);
|
||||
}
|
||||
|
||||
input.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'Enter') { e.preventDefault(); done(); }
|
||||
if (e.key === 'Escape') { input.remove(); callback(''); }
|
||||
});
|
||||
input.addEventListener('blur', function () { done(); });
|
||||
},
|
||||
|
||||
/**
|
||||
* Simple emoji picker
|
||||
*/
|
||||
toggleEmojiPicker: function (btn, textarea) {
|
||||
var self = this;
|
||||
this.removeQuickReplyPanel();
|
||||
if (this.emojiPicker) {
|
||||
this.emojiPicker.remove();
|
||||
this.emojiPicker = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var emojis = [
|
||||
{ key: 'grinning', emoji: '😀' },
|
||||
{ key: 'joy', emoji: '😂' },
|
||||
{ key: 'rofl', emoji: '🤣' },
|
||||
{ key: 'blush', emoji: '😊' },
|
||||
{ key: 'heart-eyes', emoji: '😍' },
|
||||
{ key: 'smiling-hearts', emoji: '🥰' },
|
||||
{ key: 'sunglasses', emoji: '😎' },
|
||||
{ key: 'thinking', emoji: '🤔' },
|
||||
{ key: 'cry', emoji: '😢' },
|
||||
{ key: 'sob', emoji: '😭' },
|
||||
{ key: 'angry', emoji: '😡' },
|
||||
{ key: 'pleading', emoji: '🥺' },
|
||||
{ key: 'scream', emoji: '😱' },
|
||||
{ key: 'rolling-eyes', emoji: '🙄' },
|
||||
{ key: 'sleeping', emoji: '😴' },
|
||||
{ key: 'nauseated', emoji: '🤮' },
|
||||
{ key: 'thumbs-up', emoji: '👍' },
|
||||
{ key: 'thumbs-down', emoji: '👎' },
|
||||
{ key: 'clap', emoji: '👏' },
|
||||
{ key: 'pray', emoji: '🙏' },
|
||||
{ key: 'muscle', emoji: '💪' },
|
||||
{ key: 'heart', emoji: '❤️' },
|
||||
{ key: 'fire', emoji: '🔥' },
|
||||
{ key: 'star', emoji: '⭐' },
|
||||
{ key: 'tada', emoji: '🎉' },
|
||||
{ key: 'confetti', emoji: '🎊' },
|
||||
{ key: 'check', emoji: '✅' },
|
||||
{ key: 'cross', emoji: '❌' },
|
||||
{ key: 'warning', emoji: '⚠️' },
|
||||
{ key: 'hundred', emoji: '💯' },
|
||||
{ key: 'ok', emoji: '🆗' },
|
||||
{ key: 'new', emoji: '🆕' }
|
||||
];
|
||||
|
||||
var picker = document.createElement('div');
|
||||
picker.className = 'aksrt-emoji-picker';
|
||||
picker.style.cssText = 'position:absolute;bottom:100%;left:0;background:#fff;border:1px solid #e8e8e8;border-radius:8px;padding:8px;display:grid;grid-template-columns:repeat(8,1fr);gap:4px;z-index:100;box-shadow:0 4px 12px rgba(0,0,0,0.1);';
|
||||
|
||||
emojis.forEach(function (entry) {
|
||||
var item = document.createElement('button');
|
||||
item.type = 'button';
|
||||
item.style.cssText = 'border:none;background:none;cursor:pointer;font-size:18px;padding:4px;border-radius:4px;transition:background 0.15s;';
|
||||
item.textContent = entry.emoji;
|
||||
item.setAttribute('title', entry.key);
|
||||
item.addEventListener('mouseenter', function () { item.style.background = '#f5f5f5'; });
|
||||
item.addEventListener('mouseleave', function () { item.style.background = 'none'; });
|
||||
item.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
self.insertAtCursor(textarea, '[g=' + entry.key + ']', '');
|
||||
picker.remove();
|
||||
self.emojiPicker = null;
|
||||
});
|
||||
picker.appendChild(item);
|
||||
});
|
||||
|
||||
btn.style.position = 'relative';
|
||||
btn.appendChild(picker);
|
||||
this.emojiPicker = picker;
|
||||
|
||||
// Close on outside click
|
||||
var closeHandler = function (e) {
|
||||
if (!picker.contains(e.target) && e.target !== btn) {
|
||||
picker.remove();
|
||||
self.emojiPicker = null;
|
||||
document.removeEventListener('click', closeHandler);
|
||||
}
|
||||
};
|
||||
setTimeout(function () { document.addEventListener('click', closeHandler); }, 0);
|
||||
},
|
||||
|
||||
removeQuickReplyPanel: function () {
|
||||
if (this.quickReplyPanel) {
|
||||
this.quickReplyPanel.remove();
|
||||
this.quickReplyPanel = null;
|
||||
}
|
||||
},
|
||||
|
||||
toggleQuickReply: function (btn, textarea) {
|
||||
var self = this;
|
||||
if (this.quickReplyPanel) {
|
||||
this.removeQuickReplyPanel();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.emojiPicker) {
|
||||
this.emojiPicker.remove();
|
||||
this.emojiPicker = null;
|
||||
}
|
||||
|
||||
var panel = document.createElement('div');
|
||||
panel.className = 'comment-quick-reply';
|
||||
|
||||
var title = document.createElement('div');
|
||||
title.className = 'comment-quick-reply__title';
|
||||
title.textContent = '快捷回复';
|
||||
panel.appendChild(title);
|
||||
|
||||
var templates = document.createElement('div');
|
||||
templates.className = 'comment-quick-reply__templates';
|
||||
|
||||
this.quickReplyTemplates.forEach(function (text) {
|
||||
var item = document.createElement('button');
|
||||
item.type = 'button';
|
||||
item.className = 'comment-quick-reply__template';
|
||||
item.textContent = text;
|
||||
item.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
var needsLineBreak = textarea.value && !/\n\s*$/.test(textarea.value);
|
||||
var prefix = needsLineBreak ? '\n' : '';
|
||||
self.insertAtCursor(textarea, prefix + text, '');
|
||||
self.removeQuickReplyPanel();
|
||||
});
|
||||
templates.appendChild(item);
|
||||
});
|
||||
|
||||
panel.appendChild(templates);
|
||||
|
||||
var toolbar = btn.closest('.comment-toolbar');
|
||||
if (toolbar && toolbar.parentNode) {
|
||||
toolbar.parentNode.insertBefore(panel, toolbar.nextSibling);
|
||||
} else {
|
||||
btn.parentNode.appendChild(panel);
|
||||
}
|
||||
|
||||
this.quickReplyPanel = panel;
|
||||
|
||||
var closeHandler = function (e) {
|
||||
if (!panel.contains(e.target) && e.target !== btn) {
|
||||
self.removeQuickReplyPanel();
|
||||
document.removeEventListener('click', closeHandler);
|
||||
}
|
||||
};
|
||||
setTimeout(function () { document.addEventListener('click', closeHandler); }, 0);
|
||||
},
|
||||
|
||||
/**
|
||||
* Ctrl+Enter to submit comment
|
||||
*/
|
||||
bindCtrlEnter: function () {
|
||||
document.addEventListener('keydown', function (e) {
|
||||
if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
|
||||
var textarea = e.target;
|
||||
if (textarea.tagName !== 'TEXTAREA') return;
|
||||
var form = textarea.closest('form');
|
||||
if (!form) return;
|
||||
var submitBtn = form.querySelector('[type="submit"]');
|
||||
if (submitBtn) {
|
||||
submitBtn.click();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Quick quote: select text on page, show "quote in comment" button
|
||||
*/
|
||||
bindQuickQuote: function () {
|
||||
if (!this.quickQuoteEnabled) return;
|
||||
var self = this;
|
||||
var quoteBtn = null;
|
||||
|
||||
document.addEventListener('mouseup', function () {
|
||||
setTimeout(function () {
|
||||
if (quoteBtn) {
|
||||
quoteBtn.remove();
|
||||
quoteBtn = null;
|
||||
}
|
||||
|
||||
var selection = window.getSelection();
|
||||
var text = selection.toString().trim();
|
||||
if (text.length < 5 || text.length > 500) return;
|
||||
|
||||
var range = selection.getRangeAt(0);
|
||||
var rect = range.getBoundingClientRect();
|
||||
|
||||
quoteBtn = document.createElement('button');
|
||||
quoteBtn.type = 'button';
|
||||
quoteBtn.textContent = '引用评论';
|
||||
quoteBtn.style.cssText = 'position:fixed;top:' + (rect.top - 36) + 'px;left:' + (rect.left + rect.width / 2) + 'px;transform:translateX(-50%);padding:4px 12px;background:#1890ff;color:#fff;border:none;border-radius:4px;font-size:12px;cursor:pointer;z-index:9999;box-shadow:0 2px 8px rgba(0,0,0,0.15);';
|
||||
quoteBtn.addEventListener('click', function () {
|
||||
var textarea = document.getElementById('comment');
|
||||
if (textarea) {
|
||||
var quoted = text.split('\n').map(function (line) { return '> ' + line; }).join('\n') + '\n\n';
|
||||
self.insertAtCursor(textarea, quoted, '');
|
||||
textarea.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
textarea.focus();
|
||||
}
|
||||
quoteBtn.remove();
|
||||
quoteBtn = null;
|
||||
});
|
||||
document.body.appendChild(quoteBtn);
|
||||
}, 10);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
// Initialize when DOM is ready
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', function () { COMMENT_TOOLS.init(); });
|
||||
} else {
|
||||
COMMENT_TOOLS.init();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
* AKSRT Content Protection — Copy copyright / Right-click disable / F12 detection
|
||||
*
|
||||
* All features are DEFAULT OFF and configurable via Settings.
|
||||
* This is a "soft" protection — it increases the barrier but cannot truly prevent copying.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var config = (window.aksrtData && window.aksrtData.contentProtect) || {};
|
||||
|
||||
// Bail if nothing enabled
|
||||
if (!config.enabled) return;
|
||||
|
||||
/* ============================================================
|
||||
* 1. 复制时追加版权声明
|
||||
* ============================================================ */
|
||||
if (config.copyNotice) {
|
||||
document.addEventListener('copy', function (e) {
|
||||
var selection = window.getSelection();
|
||||
if (!selection || selection.isCollapsed) return;
|
||||
|
||||
var text = selection.toString();
|
||||
if (text.length < 20) return; // Too short, skip
|
||||
|
||||
var notice = '\n\n---\n' +
|
||||
'版权声明:本文' + (config.copyNoticeText || '来自本站,请尊重原创版权。') + '\n' +
|
||||
'链接:' + window.location.href;
|
||||
|
||||
// Append notice to clipboard
|
||||
var clipboardData = e.clipboardData || window.clipboardData;
|
||||
if (clipboardData) {
|
||||
e.preventDefault();
|
||||
clipboardData.setData('text/plain', text + notice);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 2. 禁用右键菜单
|
||||
* ============================================================ */
|
||||
if (config.disableRightClick) {
|
||||
document.addEventListener('contextmenu', function (e) {
|
||||
// Allow on input/textarea elements
|
||||
var tag = e.target.tagName;
|
||||
if (tag === 'INPUT' || tag === 'TEXTAREA' || e.target.isContentEditable) return;
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
// Show brief notification
|
||||
showProtectionNotice('本站已禁用右键菜单');
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 3. F12 / DevTools 检测(仅提示,不阻止)
|
||||
* ============================================================ */
|
||||
if (config.detectDevTools) {
|
||||
document.addEventListener('keydown', function (e) {
|
||||
// F12
|
||||
if (e.key === 'F12' || e.keyCode === 123) {
|
||||
e.preventDefault();
|
||||
showProtectionNotice('本站已禁用开发者工具');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ctrl+Shift+I / Cmd+Option+I
|
||||
if ((e.ctrlKey || e.metaKey) && e.shiftKey && (e.key === 'I' || e.key === 'i' || e.keyCode === 73)) {
|
||||
e.preventDefault();
|
||||
showProtectionNotice('本站已禁用开发者工具');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ctrl+Shift+J / Cmd+Option+J
|
||||
if ((e.ctrlKey || e.metaKey) && e.shiftKey && (e.key === 'J' || e.key === 'j' || e.keyCode === 74)) {
|
||||
e.preventDefault();
|
||||
showProtectionNotice('本站已禁用开发者工具');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ctrl+U (view source)
|
||||
if ((e.ctrlKey || e.metaKey) && (e.key === 'u' || e.key === 'U' || e.keyCode === 85)) {
|
||||
e.preventDefault();
|
||||
showProtectionNotice('本站已禁用查看源代码');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Protection notice toast
|
||||
* ============================================================ */
|
||||
var noticeTimer = null;
|
||||
|
||||
function showProtectionNotice(text) {
|
||||
if (noticeTimer) clearTimeout(noticeTimer);
|
||||
|
||||
var el = document.getElementById('aksrt-protection-notice');
|
||||
if (!el) {
|
||||
el = document.createElement('div');
|
||||
el.id = 'aksrt-protection-notice';
|
||||
el.style.cssText =
|
||||
'position:fixed;bottom:20px;left:50%;transform:translateX(-50%);' +
|
||||
'background:rgba(0,0,0,0.75);color:#fff;padding:8px 20px;border-radius:8px;' +
|
||||
'font-size:13px;z-index:99999;transition:opacity 0.3s;pointer-events:none;';
|
||||
document.body.appendChild(el);
|
||||
}
|
||||
|
||||
el.textContent = text;
|
||||
el.style.opacity = '1';
|
||||
|
||||
noticeTimer = setTimeout(function () {
|
||||
el.style.opacity = '0';
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* AKSRT Conversation — 私信会话交互
|
||||
*
|
||||
* 从 page-messages.php 内联脚本提取而来。
|
||||
* 处理会话列表点击、消息加载、发送、已读标记。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var wrap = document.getElementById('aksrt-pm-conversations');
|
||||
if (!wrap) return;
|
||||
|
||||
var ajaxUrl = wrap.getAttribute('data-ajax');
|
||||
var nonce = wrap.getAttribute('data-nonce');
|
||||
var listView = wrap;
|
||||
var threadView = document.getElementById('aksrt-pm-thread');
|
||||
var messagesEl = document.getElementById('aksrt-pm-messages');
|
||||
var threadName = document.getElementById('aksrt-pm-thread-name');
|
||||
var input = document.getElementById('aksrt-pm-input');
|
||||
var sendBtn = document.getElementById('aksrt-pm-send');
|
||||
var backBtn = document.getElementById('aksrt-pm-back');
|
||||
var currentConv = 0;
|
||||
var currentOther = 0;
|
||||
|
||||
function post(action, data) {
|
||||
var fd = new FormData();
|
||||
fd.append('action', action);
|
||||
fd.append('_nonce', nonce);
|
||||
if (data) {
|
||||
for (var key in data) {
|
||||
if (data.hasOwnProperty(key)) {
|
||||
fd.append(key, data[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return fetch(ajaxUrl, { method: 'POST', body: fd, credentials: 'same-origin' })
|
||||
.then(function (r) { return r.json(); });
|
||||
}
|
||||
|
||||
// Click conversation item → load thread
|
||||
document.addEventListener('click', function (e) {
|
||||
var item = e.target.closest('.aksrt-pm__item');
|
||||
if (!item) return;
|
||||
|
||||
currentConv = parseInt(item.getAttribute('data-conv-id'));
|
||||
currentOther = parseInt(item.getAttribute('data-other-id'));
|
||||
|
||||
var nm = item.querySelector('.aksrt-pm__name');
|
||||
if (nm) {
|
||||
threadName.textContent = nm.textContent.replace(/\d+$/, '').trim();
|
||||
}
|
||||
|
||||
loadThread(currentConv, 1);
|
||||
});
|
||||
|
||||
// Back button
|
||||
if (backBtn) {
|
||||
backBtn.addEventListener('click', function () {
|
||||
threadView.style.display = 'none';
|
||||
listView.style.display = '';
|
||||
});
|
||||
}
|
||||
|
||||
// Send message
|
||||
if (sendBtn) {
|
||||
sendBtn.addEventListener('click', function () {
|
||||
var content = input.value.trim();
|
||||
if (!content || !currentConv) return;
|
||||
|
||||
post('aksrt_pm_send', {
|
||||
conversation_id: currentConv,
|
||||
recipient_id: currentOther,
|
||||
content: content,
|
||||
}).then(function (d) {
|
||||
if (d.success) {
|
||||
input.value = '';
|
||||
loadThread(currentConv, 1);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Enter to send (Shift+Enter for newline)
|
||||
if (input) {
|
||||
input.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'Enter' && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
sendBtn.click();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function loadThread(convId, page) {
|
||||
post('aksrt_pm_thread', {
|
||||
conversation_id: convId,
|
||||
page: page,
|
||||
}).then(function (d) {
|
||||
if (d.success && d.data) {
|
||||
renderMessages(d.data.messages || []);
|
||||
listView.style.display = 'none';
|
||||
threadView.style.display = '';
|
||||
|
||||
// Mark as read
|
||||
post('aksrt_pm_mark_read', { conversation_id: convId });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function renderMessages(msgs) {
|
||||
messagesEl.innerHTML = '';
|
||||
msgs.forEach(function (m) {
|
||||
var div = document.createElement('div');
|
||||
div.className = 'aksrt-pm__msg' + (m.is_mine ? ' aksrt-pm__msg--mine' : '');
|
||||
div.innerHTML =
|
||||
'<div class="aksrt-pm__msg-bubble">' +
|
||||
'<div class="aksrt-pm__msg-content">' + (m.content || '').replace(/</g, '<') + '</div>' +
|
||||
'<div class="aksrt-pm__msg-time">' + (m.created_at || '') + '</div>' +
|
||||
'</div>';
|
||||
messagesEl.appendChild(div);
|
||||
});
|
||||
messagesEl.scrollTop = messagesEl.scrollHeight;
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,213 @@
|
||||
/**
|
||||
* AKSRT Archive AJAX Filter
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function initArchiveFilter() {
|
||||
var bar = document.querySelector(".archive-filter-bar--ajax[data-ajax-archive]");
|
||||
if (!bar) return;
|
||||
|
||||
var archiveType = bar.dataset.ajaxArchive || "category";
|
||||
var termId = parseInt(bar.dataset.termId, 10) || 0;
|
||||
var wrap = document.querySelector("[data-ajax-wrap]");
|
||||
if (!wrap) return;
|
||||
|
||||
var loading = wrap.querySelector(".archive__ajax-loading");
|
||||
var REST_BASE = "/wp-json/aksrt/v1/archive/posts";
|
||||
|
||||
var state = {
|
||||
filter_cat: "",
|
||||
filter_tag: "",
|
||||
sort: "latest",
|
||||
page: 1,
|
||||
cf: {}
|
||||
};
|
||||
|
||||
// Read initial state from active chips
|
||||
var activeCat = bar.querySelector("[data-filter-cat].is-active");
|
||||
if (activeCat) state.filter_cat = activeCat.dataset.filterCat || "";
|
||||
var activeTag = bar.querySelector("[data-filter-tag].is-active");
|
||||
if (activeTag) state.filter_tag = activeTag.dataset.filterTag || "";
|
||||
var activeSort = bar.querySelector("[data-filter-sort].is-active");
|
||||
if (activeSort) state.sort = activeSort.dataset.filterSort || "latest";
|
||||
// custom_filter: read initial cf state from active chips
|
||||
bar.querySelectorAll("[data-filter-cf].is-active").forEach(function (el) {
|
||||
var dimKey = el.dataset.filterCf || "";
|
||||
var dimVal = el.dataset.filterCfVal || "";
|
||||
if (dimKey) state.cf[dimKey] = dimVal;
|
||||
});
|
||||
|
||||
function buildUrl() {
|
||||
var params = new URLSearchParams();
|
||||
params.set("archive_type", archiveType);
|
||||
params.set("term_id", String(termId));
|
||||
if (state.filter_cat) params.set("filter_cat", state.filter_cat);
|
||||
if (state.filter_tag) params.set("filter_tag", state.filter_tag);
|
||||
|
||||
var sortMap = { oldest: { orderby: "date", order: "ASC" }, popular: { orderby: "comment_count", order: "DESC" } };
|
||||
var s = sortMap[state.sort];
|
||||
params.set("sort", s ? s.orderby : "date");
|
||||
params.set("order", s ? s.order : "DESC");
|
||||
params.set("page", String(state.page));
|
||||
// custom_filter: pass active dimensions as JSON
|
||||
var cfActive = {};
|
||||
var hasCf = false;
|
||||
for (var cfK in state.cf) {
|
||||
if (state.cf[cfK]) { cfActive[cfK] = state.cf[cfK]; hasCf = true; }
|
||||
}
|
||||
if (hasCf) params.set("custom_filters", JSON.stringify(cfActive));
|
||||
return REST_BASE + "?" + params.toString();
|
||||
}
|
||||
|
||||
function updateActiveChips() {
|
||||
bar.querySelectorAll("[data-filter-cat]").forEach(function (el) {
|
||||
el.classList.toggle("is-active", (el.dataset.filterCat || "") === state.filter_cat);
|
||||
});
|
||||
bar.querySelectorAll("[data-filter-tag]").forEach(function (el) {
|
||||
el.classList.toggle("is-active", (el.dataset.filterTag || "") === state.filter_tag);
|
||||
});
|
||||
bar.querySelectorAll("[data-filter-sort]").forEach(function (el) {
|
||||
el.classList.toggle("is-active", (el.dataset.filterSort || "latest") === state.sort);
|
||||
});
|
||||
// custom_filter: update cf chip active state
|
||||
bar.querySelectorAll("[data-filter-cf]").forEach(function (el) {
|
||||
var dimKey = el.dataset.filterCf || "";
|
||||
var dimVal = el.dataset.filterCfVal || "";
|
||||
var isActive = dimKey && (state.cf[dimKey] || "") === dimVal;
|
||||
el.classList.toggle("is-active", isActive);
|
||||
});
|
||||
}
|
||||
|
||||
function showLoading() {
|
||||
if (loading) loading.classList.add("is-loading");
|
||||
wrap.classList.add("is-loading");
|
||||
}
|
||||
|
||||
function hideLoading() {
|
||||
if (loading) loading.classList.remove("is-loading");
|
||||
wrap.classList.remove("is-loading");
|
||||
}
|
||||
|
||||
function fetchPosts(pushState) {
|
||||
showLoading();
|
||||
fetch(buildUrl(), {
|
||||
method: "GET",
|
||||
headers: { Accept: "application/json" },
|
||||
credentials: "same-origin"
|
||||
})
|
||||
.then(function (r) {
|
||||
if (!r.ok) throw new Error("HTTP " + r.status);
|
||||
return r.json();
|
||||
})
|
||||
.then(function (data) {
|
||||
hideLoading();
|
||||
if (data.html !== undefined) {
|
||||
// Keep the loading element, replace the rest
|
||||
var children = Array.from(wrap.children);
|
||||
children.forEach(function (child) {
|
||||
if (child !== loading) wrap.removeChild(child);
|
||||
});
|
||||
if (data.html) {
|
||||
var temp = document.createElement("div");
|
||||
temp.innerHTML = data.html;
|
||||
while (temp.firstChild) wrap.appendChild(temp.firstChild);
|
||||
} else {
|
||||
var noResults = document.createElement("div");
|
||||
noResults.className = "no-results";
|
||||
noResults.innerHTML = "<p>暂无文章</p>";
|
||||
wrap.appendChild(noResults);
|
||||
}
|
||||
// Re-init rehydratable modules for new content
|
||||
if (window.AksrtFrontend) AksrtFrontend.rehydrate(wrap, 'ajax');
|
||||
}
|
||||
if (pushState !== false) {
|
||||
var url = new URL(window.location.href);
|
||||
url.searchParams.delete("orderby");
|
||||
url.searchParams.delete("order");
|
||||
url.searchParams.delete("paged");
|
||||
url.searchParams.delete("aksrt_filter_cat");
|
||||
url.searchParams.delete("aksrt_filter_tag");
|
||||
// custom_filter: clean cf params
|
||||
url.searchParams.forEach(function (v, k) {
|
||||
if (k.indexOf("aksrt_cf_") === 0) url.searchParams.delete(k);
|
||||
});
|
||||
if (state.filter_cat) url.searchParams.set("aksrt_filter_cat", state.filter_cat);
|
||||
if (state.filter_tag) url.searchParams.set("aksrt_filter_tag", state.filter_tag);
|
||||
// custom_filter: set cf URL params
|
||||
for (var cfK2 in state.cf) {
|
||||
if (state.cf[cfK2]) url.searchParams.set("aksrt_cf_" + cfK2, state.cf[cfK2]);
|
||||
}
|
||||
if (state.sort === "oldest") { url.searchParams.set("orderby", "date"); url.searchParams.set("order", "asc"); }
|
||||
else if (state.sort === "popular") { url.searchParams.set("orderby", "comment_count"); url.searchParams.set("order", "desc"); }
|
||||
if (state.page > 1) url.searchParams.set("paged", String(state.page));
|
||||
history.pushState({ aksrtArchive: true, state: Object.assign({}, state) }, "", url.toString());
|
||||
}
|
||||
})
|
||||
.catch(function () {
|
||||
hideLoading();
|
||||
});
|
||||
}
|
||||
|
||||
bar.addEventListener("click", function (e) {
|
||||
var chip = e.target.closest("[data-filter-cat], [data-filter-tag], [data-filter-sort], [data-filter-cf]");
|
||||
if (!chip) return;
|
||||
e.preventDefault();
|
||||
|
||||
var changed = false;
|
||||
if (chip.dataset.filterCat !== undefined) {
|
||||
var newCat = chip.dataset.filterCat;
|
||||
if (newCat !== state.filter_cat) { state.filter_cat = newCat; changed = true; }
|
||||
}
|
||||
if (chip.dataset.filterTag !== undefined) {
|
||||
var newTag = chip.dataset.filterTag;
|
||||
if (newTag !== state.filter_tag) { state.filter_tag = newTag; changed = true; }
|
||||
}
|
||||
if (chip.dataset.filterSort !== undefined) {
|
||||
var newSort = chip.dataset.filterSort || "latest";
|
||||
if (newSort !== state.sort) { state.sort = newSort; changed = true; }
|
||||
}
|
||||
// custom_filter: handle cf chip clicks
|
||||
if (chip.dataset.filterCf !== undefined) {
|
||||
var cfKey = chip.dataset.filterCf;
|
||||
var cfVal = chip.dataset.filterCfVal || "";
|
||||
if ((state.cf[cfKey] || "") !== cfVal) {
|
||||
state.cf[cfKey] = cfVal;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
state.page = 1;
|
||||
updateActiveChips();
|
||||
fetchPosts(true);
|
||||
}
|
||||
});
|
||||
|
||||
// Pagination within AJAX wrap
|
||||
wrap.addEventListener("click", function (e) {
|
||||
var pageLink = e.target.closest(".pagination a, .nav-links a, a.page-numbers");
|
||||
if (!pageLink || !wrap.contains(pageLink)) return;
|
||||
var href = pageLink.getAttribute("href");
|
||||
if (!href) return;
|
||||
|
||||
var match = href.match(/[?&]paged=(\d+)/);
|
||||
if (match) {
|
||||
e.preventDefault();
|
||||
state.page = parseInt(match[1], 10) || 1;
|
||||
fetchPosts(true);
|
||||
}
|
||||
});
|
||||
|
||||
// Handle browser back/forward
|
||||
window.addEventListener("popstate", function (e) {
|
||||
if (e.state && e.state.aksrtArchive) {
|
||||
state = Object.assign(state, e.state.state);
|
||||
updateActiveChips();
|
||||
fetchPosts(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
window.AksrtFrontend.register("aksrt-archive-filter", function () { initArchiveFilter(); });
|
||||
})();
|
||||
@@ -0,0 +1,226 @@
|
||||
/**
|
||||
* AKSRT Article Tools — password toggles, search clear, article actions, interaction bar
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function initPasswordToggles(root) {
|
||||
(root || document).querySelectorAll(".toggle-pwd").forEach(function (btn) {
|
||||
if (btn.dataset.pwdToggleBound) return;
|
||||
btn.dataset.pwdToggleBound = "1";
|
||||
btn.addEventListener("click", function () {
|
||||
var id = btn.getAttribute("data-target");
|
||||
var input = id ? document.getElementById(id) : null;
|
||||
if (!input) return;
|
||||
var show = input.getAttribute("type") === "password";
|
||||
input.setAttribute("type", show ? "text" : "password");
|
||||
btn.setAttribute("aria-label", show ? "隐藏密码" : "显示密码");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function initSearchClear() {
|
||||
var btn = document.getElementById("search-clear-btn");
|
||||
var input = document.getElementById("search-page-input");
|
||||
|
||||
if (btn && input) {
|
||||
var syncClearButton = function () {
|
||||
var hasValue = input.value.trim().length > 0;
|
||||
btn.classList.toggle("is-visible", hasValue);
|
||||
btn.hidden = !hasValue;
|
||||
};
|
||||
|
||||
btn.addEventListener("click", function () {
|
||||
input.value = "";
|
||||
input.focus();
|
||||
syncClearButton();
|
||||
});
|
||||
|
||||
input.addEventListener("input", syncClearButton);
|
||||
syncClearButton();
|
||||
}
|
||||
|
||||
var categorySelect = document.getElementById("search-category-filter");
|
||||
if (categorySelect) {
|
||||
categorySelect.addEventListener("change", function () {
|
||||
var url = new URL(window.location.href);
|
||||
if (this.value) {
|
||||
url.searchParams.set("aksrt_category", this.value);
|
||||
} else {
|
||||
url.searchParams.delete("aksrt_category");
|
||||
}
|
||||
url.searchParams.delete("paged");
|
||||
window.location.href = url.toString();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function showToast(msg, type) {
|
||||
if (window.aksrt && aksrt.notyf) {
|
||||
aksrt.notyf(msg, { type: type || "info", duration: 2200 });
|
||||
} else {
|
||||
console.log("[AKSRT Toast]", type, msg);
|
||||
}
|
||||
}
|
||||
|
||||
function initArticleTools() {
|
||||
var buttons = document.querySelectorAll("[data-article-tool]");
|
||||
if (!buttons.length) return;
|
||||
|
||||
buttons.forEach(function (button) {
|
||||
button.addEventListener("click", function () {
|
||||
var tool = button.getAttribute("data-article-tool");
|
||||
if (tool === "print") {
|
||||
window.print();
|
||||
return;
|
||||
}
|
||||
|
||||
if (tool === "pdf") {
|
||||
window.print();
|
||||
if (typeof showToast === "function") {
|
||||
showToast("请在打印对话框中选择“另存为 PDF”", "info");
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getBaseStatCount(statName) {
|
||||
var statEl = document.querySelector('[data-stat-count="' + statName + '"][data-base-count]');
|
||||
return statEl ? (parseInt(statEl.dataset.baseCount, 10) || 0) : 0;
|
||||
}
|
||||
|
||||
function updateStatCounts(statName, count) {
|
||||
var safeCount = Math.max(0, count);
|
||||
document.querySelectorAll('[data-stat-count="' + statName + '"]').forEach(function (statEl) {
|
||||
statEl.textContent = String(safeCount);
|
||||
});
|
||||
}
|
||||
|
||||
function setBaseStatCount(statName, count) {
|
||||
var safeCount = Math.max(0, count);
|
||||
document.querySelectorAll('[data-stat-count="' + statName + '"][data-base-count]').forEach(function (statEl) {
|
||||
statEl.dataset.baseCount = String(safeCount);
|
||||
});
|
||||
updateStatCounts(statName, safeCount);
|
||||
}
|
||||
|
||||
function requestInteraction(actionName, postId, active) {
|
||||
if (!window.aksrtData || !aksrtData.ajaxUrl || !aksrtData.nonce) {
|
||||
return Promise.reject(new Error("互动服务未配置"));
|
||||
}
|
||||
|
||||
var body = new URLSearchParams();
|
||||
body.set("action", actionName);
|
||||
body.set("nonce", aksrtData.nonce);
|
||||
body.set("postId", String(postId));
|
||||
body.set("active", active ? "1" : "0");
|
||||
|
||||
return fetch(aksrtData.ajaxUrl, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8" },
|
||||
credentials: "same-origin",
|
||||
body: body.toString()
|
||||
}).then(function (response) {
|
||||
return response.json().catch(function () {
|
||||
throw new Error("服务器返回无效响应");
|
||||
});
|
||||
}).then(function (payload) {
|
||||
if (!payload || !payload.success) {
|
||||
var message = payload && payload.data && payload.data.message ? payload.data.message : "请求失败";
|
||||
throw new Error(message);
|
||||
}
|
||||
return payload.data || {};
|
||||
});
|
||||
}
|
||||
|
||||
function setButtonBusy(button, busy) {
|
||||
button.disabled = !!busy;
|
||||
button.classList.toggle("is-loading", !!busy);
|
||||
}
|
||||
|
||||
function initInteractionBar(root) {
|
||||
var scope = root || document;
|
||||
var likeBtn = scope.getElementById("action-like");
|
||||
var favBtn = scope.getElementById("action-favorite");
|
||||
|
||||
if (likeBtn && likeBtn.dataset.aksrtInteractionBound) return;
|
||||
if (favBtn && favBtn.dataset.aksrtInteractionBound) return;
|
||||
|
||||
if (likeBtn) {
|
||||
var likePostId = likeBtn.dataset.postId ? String(likeBtn.dataset.postId) : "";
|
||||
|
||||
function applyLikeState(isActive, count) {
|
||||
likeBtn.dataset.initialActive = isActive ? "1" : "0";
|
||||
likeBtn.classList.toggle("is-active", isActive);
|
||||
var likeIcon = likeBtn.querySelector("i");
|
||||
if (likeIcon) {
|
||||
likeIcon.className = isActive ? "fas fa-heart" : "far fa-heart";
|
||||
}
|
||||
if ("number" === typeof count && !isNaN(count)) {
|
||||
setBaseStatCount("likes", count);
|
||||
} else {
|
||||
updateStatCounts("likes", getBaseStatCount("likes"));
|
||||
}
|
||||
}
|
||||
|
||||
applyLikeState(likeBtn.dataset.initialActive === "1", getBaseStatCount("likes"));
|
||||
|
||||
likeBtn.addEventListener("click", function () {
|
||||
if (!likePostId || likeBtn.disabled) return;
|
||||
var nextState = likeBtn.dataset.initialActive !== "1";
|
||||
setButtonBusy(likeBtn, true);
|
||||
requestInteraction("aksrt_toggle_like", likePostId, nextState).then(function (data) {
|
||||
applyLikeState(!!data.active, parseInt(data.count, 10) || 0);
|
||||
showToast(data.active ? "感谢你的点赞" : "已取消点赞", "success");
|
||||
}).catch(function (error) {
|
||||
showToast(error && error.message ? error.message : "点赞失败", "error");
|
||||
}).finally(function () {
|
||||
setButtonBusy(likeBtn, false);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (favBtn) {
|
||||
var favoritePostId = favBtn.dataset.postId ? String(favBtn.dataset.postId) : "";
|
||||
|
||||
function applyFavoriteState(isActive, count) {
|
||||
favBtn.dataset.initialActive = isActive ? "1" : "0";
|
||||
favBtn.classList.toggle("is-active", isActive);
|
||||
var favoriteIcon = favBtn.querySelector("i");
|
||||
if (favoriteIcon) {
|
||||
favoriteIcon.className = isActive ? "fas fa-star" : "far fa-star";
|
||||
}
|
||||
if ("number" === typeof count && !isNaN(count)) {
|
||||
setBaseStatCount("favorites", count);
|
||||
} else {
|
||||
updateStatCounts("favorites", getBaseStatCount("favorites"));
|
||||
}
|
||||
}
|
||||
|
||||
applyFavoriteState(favBtn.dataset.initialActive === "1", getBaseStatCount("favorites"));
|
||||
|
||||
favBtn.addEventListener("click", function () {
|
||||
if (!favoritePostId || favBtn.disabled) return;
|
||||
var nextState = favBtn.dataset.initialActive !== "1";
|
||||
setButtonBusy(favBtn, true);
|
||||
requestInteraction("aksrt_toggle_favorite", favoritePostId, nextState).then(function (data) {
|
||||
applyFavoriteState(!!data.active, parseInt(data.count, 10) || 0);
|
||||
showToast(data.active ? "收藏成功" : "已取消收藏", "success");
|
||||
}).catch(function (error) {
|
||||
showToast(error && error.message ? error.message : "收藏失败", "error");
|
||||
}).finally(function () {
|
||||
setButtonBusy(favBtn, false);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (likeBtn) likeBtn.dataset.aksrtInteractionBound = "1";
|
||||
if (favBtn) favBtn.dataset.aksrtInteractionBound = "1";
|
||||
}
|
||||
|
||||
window.AksrtFrontend.register("aksrt-search-clear", function () { initSearchClear(); });
|
||||
window.AksrtFrontend.register("aksrt-article-tools", function () { initArticleTools(); });
|
||||
window.AksrtFrontend.register("aksrt-password-toggles", function (root) { initPasswordToggles(root); });
|
||||
window.AksrtFrontend.register("aksrt-interaction-bar", function (root) { initInteractionBar(root); });
|
||||
})();
|
||||
@@ -0,0 +1,622 @@
|
||||
/**
|
||||
* AKSRT Comment System — AJAX submit, captcha, ordering, author filter
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function showToast(msg, type) {
|
||||
if (window.aksrt && aksrt.notyf) {
|
||||
aksrt.notyf(msg, { type: type || "info", duration: 2200 });
|
||||
} else {
|
||||
console.log("[AKSRT Toast]", type, msg);
|
||||
}
|
||||
}
|
||||
|
||||
function initCommentSystem() {
|
||||
var form = document.querySelector("#commentform");
|
||||
if (!form) return;
|
||||
|
||||
// 修复:同时匹配 button 和 input 元素
|
||||
var submitBtn = form.querySelector('[type="submit"]');
|
||||
if (!submitBtn) return;
|
||||
var isInputSubmit = submitBtn.tagName === 'INPUT';
|
||||
|
||||
// 保存原始按钮内容(用于恢复)
|
||||
var originalBtnHTML = isInputSubmit ? submitBtn.value : submitBtn.innerHTML;
|
||||
|
||||
function setSubmitBtnContent(html, textFallback) {
|
||||
if (isInputSubmit) {
|
||||
submitBtn.value = textFallback;
|
||||
} else {
|
||||
submitBtn.innerHTML = html;
|
||||
}
|
||||
}
|
||||
|
||||
// 状态管理
|
||||
var isSubmitting = false;
|
||||
var countdownTimer = null;
|
||||
|
||||
// 显示/隐藏加载状态
|
||||
function setLoading(loading) {
|
||||
if (loading) {
|
||||
isSubmitting = true;
|
||||
submitBtn.classList.add("is-loading");
|
||||
submitBtn.disabled = true;
|
||||
var loadingText = (window.aksrtData && aksrtData.commentSubmittingText) || '发送中...';
|
||||
setSubmitBtnContent('<i class="fas fa-circle-notch fa-spin"></i> ' + loadingText, loadingText);
|
||||
} else {
|
||||
isSubmitting = false;
|
||||
submitBtn.classList.remove("is-loading");
|
||||
submitBtn.classList.remove('countdown-active');
|
||||
submitBtn.disabled = false;
|
||||
setSubmitBtnContent(originalBtnHTML, originalBtnHTML);
|
||||
}
|
||||
}
|
||||
|
||||
// 收集表单数据(包含验证码字段)
|
||||
function collectFormData() {
|
||||
var formData = new FormData(form);
|
||||
|
||||
// 确保包含必要的隐藏字段
|
||||
var postId = document.querySelector('input[name="comment_post_ID"]');
|
||||
if (postId && !formData.get('comment_post_ID')) {
|
||||
formData.append('comment_post_ID', postId.value);
|
||||
}
|
||||
|
||||
return formData;
|
||||
}
|
||||
|
||||
// 从 wp_die() HTML 中提取错误信息
|
||||
function extractErrorMessage(html) {
|
||||
// WordPress wp_die() 输出格式: <p>错误信息</p>
|
||||
var match = html.match(/<p[^>]*>([^<]+)<\/p>/i);
|
||||
return match ? match[1].trim() : '未知错误';
|
||||
}
|
||||
|
||||
// 从错误消息中提取等待时间(秒)
|
||||
function extractWaitTime(msg) {
|
||||
var match = msg.match(/(\d+)\s*秒/);
|
||||
return match ? parseInt(match[1]) : 0;
|
||||
}
|
||||
|
||||
// 启动倒计时(用于频率限制)
|
||||
function startCountdown(seconds) {
|
||||
if (countdownTimer) clearInterval(countdownTimer);
|
||||
|
||||
submitBtn.classList.add('countdown-active');
|
||||
submitBtn.disabled = true;
|
||||
var remaining = seconds;
|
||||
|
||||
countdownTimer = setInterval(function () {
|
||||
setSubmitBtnContent(
|
||||
'<i class="fas fa-clock"></i> 请等待 ' + remaining + 's',
|
||||
'请等待 ' + remaining + 's'
|
||||
);
|
||||
|
||||
if (--remaining <= 0) {
|
||||
clearInterval(countdownTimer);
|
||||
countdownTimer = null;
|
||||
submitBtn.classList.remove('countdown-active', 'is-loading');
|
||||
submitBtn.disabled = false;
|
||||
setSubmitBtnContent(originalBtnHTML, originalBtnHTML);
|
||||
isSubmitting = false;
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function updateCommentCount(delta) {
|
||||
var countEl = document.querySelector('.comments-count');
|
||||
if (!countEl) return;
|
||||
var text = countEl.textContent || '';
|
||||
var match = text.match(/(\d+)/);
|
||||
if (!match) return;
|
||||
var nextCount = Math.max(0, parseInt(match[1], 10) + delta);
|
||||
countEl.textContent = '共 ' + nextCount + ' 条';
|
||||
}
|
||||
function handleResponse(responseText, statusCode) {
|
||||
try {
|
||||
// 情况1: 成功提交 - 包含评论ID或成功标记
|
||||
if (statusCode === 200 || statusCode === 201) {
|
||||
if (responseText.includes('comment-submitted') ||
|
||||
responseText.indexOf('id="comment-') !== -1 ||
|
||||
responseText.indexOf('awaiting-moderation') !== -1) {
|
||||
|
||||
// 区分是否需要审核
|
||||
if (responseText.indexOf('审核') !== -1 ||
|
||||
responseText.indexOf('moderation') !== -1 ||
|
||||
responseText.includes('awaiting-moderation')) {
|
||||
showToast('评论已提交,等待管理员审核', 'info');
|
||||
} else {
|
||||
showToast('评论发布成功', 'success');
|
||||
}
|
||||
|
||||
// 清空文本框
|
||||
var textarea = form.querySelector('#comment');
|
||||
if (textarea) textarea.value = '';
|
||||
|
||||
// 重置回复状态
|
||||
var replyInfo = document.getElementById('comment-reply-info');
|
||||
if (replyInfo) replyInfo.style.display = 'none';
|
||||
|
||||
// 刷新评论列表(延迟执行,确保后端处理完成)
|
||||
setTimeout(function () {
|
||||
reloadCommentList();
|
||||
}, 500);
|
||||
setLoading(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 情况2: HTTP 429 频率限制
|
||||
if (statusCode === 429) {
|
||||
var errorMsg = extractErrorMessage(responseText);
|
||||
var waitSeconds = extractWaitTime(errorMsg);
|
||||
|
||||
showToast(errorMsg, 'warning');
|
||||
|
||||
if (waitSeconds > 0) {
|
||||
startCountdown(waitSeconds);
|
||||
} else {
|
||||
setLoading(false); // 无具体等待时间时恢复按钮
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// 情况3: HTTP 403 权限不足(地区/IP/关键词等)
|
||||
if (statusCode === 403) {
|
||||
var forbiddenMsg = extractErrorMessage(responseText);
|
||||
showToast(forbiddenMsg, 'error');
|
||||
setLoading(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 情况4: 包含WordPress错误信息
|
||||
var errorMatch = responseText.match(/<p[^>]*>([^<]*(?:错误|失败|error|Error)[^<]*)<\/p>/i);
|
||||
if (errorMatch) {
|
||||
showToast(errorMatch[1].trim(), 'error');
|
||||
setLoading(false);
|
||||
return false;
|
||||
}
|
||||
// 默认情况:可能是成功或其他
|
||||
showToast('评论已提交', 'success');
|
||||
var textarea2 = form.querySelector('#comment');
|
||||
if (textarea2) textarea2.value = '';
|
||||
|
||||
// 局部刷新评论列表(不再整页 reload)
|
||||
setTimeout(function () {
|
||||
reloadCommentList();
|
||||
}, 500);
|
||||
setLoading(false);
|
||||
|
||||
return true;
|
||||
|
||||
} catch (e) {
|
||||
console.error('[AKSRT Comment] 解析响应失败:', e);
|
||||
showToast('响应解析异常,请重试', 'error');
|
||||
setLoading(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 执行实际的 AJAX 请求 — local insert instead of full-page re-fetch
|
||||
function performSubmit() {
|
||||
setLoading(true);
|
||||
|
||||
var formData = collectFormData();
|
||||
var restBase = '/wp-json/aksrt/v1/comment/submit';
|
||||
|
||||
// Try REST endpoint for local-insert HTML response
|
||||
var restBody = {};
|
||||
formData.forEach(function (v, k) { restBody[k] = v; });
|
||||
|
||||
fetch(restBase, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-WP-Nonce': (window.aksrtData && aksrtData.restNonce) || ''
|
||||
},
|
||||
credentials: 'same-origin',
|
||||
body: JSON.stringify(restBody)
|
||||
})
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (json) {
|
||||
if (json && json.success && json.html) {
|
||||
// Local insert: prepend new comment HTML
|
||||
localInsertComment(json.html, json.is_reply, json.parent_id, json.needs_moderation);
|
||||
|
||||
var textarea = form.querySelector('#comment');
|
||||
if (textarea) textarea.value = '';
|
||||
|
||||
var replyInfo = document.getElementById('comment-reply-info');
|
||||
if (replyInfo) replyInfo.style.display = 'none';
|
||||
// Reset captcha
|
||||
var captchaImg = form.querySelector('.imagecaptcha img');
|
||||
if (captchaImg) captchaImg.click();
|
||||
|
||||
// Wait time countdown
|
||||
if (json.wait_time && json.wait_time > 0) {
|
||||
startCountdown(json.wait_time);
|
||||
} else {
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
// Move respond back to original position
|
||||
restoreRespondPosition();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (json && json.code) {
|
||||
showToast(json.message || '评论提交失败', 'error');
|
||||
if (json.wait_time) startCountdown(json.wait_time);
|
||||
else setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
showToast('评论已提交', 'success');
|
||||
setLoading(false);
|
||||
setTimeout(function () { reloadCommentList(); }, 500);
|
||||
})
|
||||
.catch(function () {
|
||||
// Fallback: submit to wp-comments-post.php directly
|
||||
performLegacySubmit();
|
||||
});
|
||||
}
|
||||
|
||||
function localInsertComment(html, isReply, parentId, needsModeration) {
|
||||
var temp = document.createElement('div');
|
||||
temp.innerHTML = html;
|
||||
var newComment = temp.firstElementChild;
|
||||
if (!newComment) { reloadCommentList(); return; }
|
||||
|
||||
newComment.style.overflow = 'hidden';
|
||||
newComment.style.maxHeight = '0';
|
||||
newComment.style.opacity = '0';
|
||||
newComment.style.transition = 'max-height 0.4s ease, opacity 0.3s ease';
|
||||
if (isReply && parentId) {
|
||||
var parentComment = document.querySelector('#comment-' + parentId + ', [data-comment-id="' + parentId + '"]');
|
||||
if (parentComment) {
|
||||
var children = parentComment.querySelector('.children');
|
||||
if (!children) {
|
||||
children = document.createElement('ol');
|
||||
children.className = 'children';
|
||||
parentComment.appendChild(children);
|
||||
}
|
||||
children.insertBefore(newComment, children.firstChild);
|
||||
} else {
|
||||
prependToCommentList(newComment);
|
||||
}
|
||||
} else {
|
||||
prependToCommentList(newComment);
|
||||
}
|
||||
|
||||
// slideDown animation
|
||||
requestAnimationFrame(function () {
|
||||
newComment.style.maxHeight = newComment.scrollHeight + 100 + 'px';
|
||||
newComment.style.opacity = '1';
|
||||
setTimeout(function () {
|
||||
newComment.style.maxHeight = '';
|
||||
newComment.style.overflow = '';
|
||||
newComment.style.transition = '';
|
||||
}, 500);
|
||||
});
|
||||
|
||||
if (needsModeration) {
|
||||
showToast('评论已提交,等待管理员审核', 'info');
|
||||
} else {
|
||||
showToast('评论发布成功', 'success');
|
||||
}
|
||||
|
||||
if (window.AksrtFrontend) AksrtFrontend.rehydrate(newComment, 'ajax');
|
||||
updateCommentCount(1);
|
||||
}
|
||||
|
||||
function prependToCommentList(el) {
|
||||
var list = document.querySelector('.commentlist, #comment-list > ol, #comment-list');
|
||||
if (list) list.insertBefore(el, list.firstChild);
|
||||
}
|
||||
|
||||
function restoreRespondPosition() {
|
||||
var respond = document.getElementById('respond');
|
||||
var placeholder = document.getElementById('wp-temp-form-div');
|
||||
if (respond && placeholder && placeholder.parentNode) {
|
||||
placeholder.parentNode.insertBefore(respond, placeholder);
|
||||
placeholder.remove();
|
||||
}
|
||||
}
|
||||
// Legacy fallback: POST to wp-comments-post.php
|
||||
function performLegacySubmit() {
|
||||
var formData = collectFormData();
|
||||
var actionUrl = form.getAttribute('action') || '/wp-comments-post.php';
|
||||
|
||||
fetch(actionUrl, {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
credentials: 'same-origin',
|
||||
headers: { 'X-Requested-With': 'XMLHttpRequest' }
|
||||
})
|
||||
.then(function (response) {
|
||||
return response.text().then(function (text) {
|
||||
return { status: response.status, text: text, ok: response.ok };
|
||||
});
|
||||
})
|
||||
.then(function (result) {
|
||||
handleResponse(result.text, result.status);
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.error('[AKSRT Comment] 提交失败:', error);
|
||||
|
||||
if (error.message === 'Failed to fetch' || error.name === 'TypeError') {
|
||||
showToast('网络连接失败,请检查网络后重试', 'error');
|
||||
} else {
|
||||
showToast(error.message || '评论提交失败,请重试', 'error');
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
})
|
||||
.finally(function () {
|
||||
// 兜底:避免异常分支漏掉状态恢复导致按钮卡在"发送中"
|
||||
if (!countdownTimer && isSubmitting) {
|
||||
setLoading(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 核心表单提交事件处理器
|
||||
function handleSubmit(e) {
|
||||
// 如果已经在提交中或倒计时中,防止重复提交
|
||||
if (isSubmitting || countdownTimer) {
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
return false;
|
||||
}
|
||||
|
||||
// 阻止默认表单提交
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
// 检查验证码状态(如果有验证码组件)
|
||||
var captchaScene = window.AKSRTCaptchaState &&
|
||||
window.AKSRTCaptchaState.scenes &&
|
||||
window.AKSRTCaptchaState.scenes.comment;
|
||||
|
||||
if (captchaScene && typeof captchaScene.verify === 'function') {
|
||||
// 有验证码:先触发验证流程
|
||||
setLoading(true);
|
||||
|
||||
captchaScene.verify(function (verified) {
|
||||
if (verified !== false) {
|
||||
// 验证通过,执行 AJAX 提交
|
||||
performSubmit();
|
||||
} else {
|
||||
// 验证失败
|
||||
showToast('人机验证未通过,请重试', 'warning');
|
||||
setLoading(false);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 无验证码或已经验证过:直接提交
|
||||
performSubmit();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// 绑定表单提交事件(使用捕获阶段,高优先级)
|
||||
form.addEventListener('submit', handleSubmit, true);
|
||||
}
|
||||
|
||||
/* ====== 评论列表动态刷新 ====== */
|
||||
function reloadCommentList() {
|
||||
var listContainer = document.getElementById('comment-list');
|
||||
if (!listContainer) {
|
||||
// 降级:整页刷新
|
||||
window.location.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
var postIdInput = document.querySelector('input[name="comment_post_ID"]');
|
||||
if (!postIdInput) return;
|
||||
|
||||
// 显示骨架屏加载效果
|
||||
listContainer.innerHTML = '<li class="comment-loading-skeleton">' +
|
||||
'<div class="aksrt-comment"><div class="aksrt-comment__body">' +
|
||||
'<div style="height:60px;background:#f0f0f0;border-radius:8px;margin-bottom:10px;animation:pulse 1.5s ease-in-out infinite;"></div>' +
|
||||
'<div style="height:20px;width:70%;background:#f0f0f0;border-radius:4px;animation:pulse 1.5s ease-in-out infinite;"></div>' +
|
||||
'</div></div></li>';
|
||||
// 获取当前页面 URL(带时间戳避免缓存)
|
||||
var currentUrl = window.location.href.split('#')[0];
|
||||
var bustUrl = currentUrl + (currentUrl.indexOf('?') === -1 ? '?' : '&') + '_cache_bust=' + Date.now();
|
||||
|
||||
fetch(bustUrl, {
|
||||
method: 'GET',
|
||||
credentials: 'same-origin'
|
||||
})
|
||||
.then(function (response) { return response.text(); })
|
||||
.then(function (html) {
|
||||
// 从新页面提取评论列表
|
||||
var parser = new DOMParser();
|
||||
var doc = parser.parseFromString(html, 'text/html');
|
||||
var newList = doc.getElementById('comment-list');
|
||||
|
||||
if (newList && newList.innerHTML.trim()) {
|
||||
listContainer.innerHTML = newList.innerHTML;
|
||||
|
||||
// 更新评论计数
|
||||
var countEl = document.querySelector('.comments-count');
|
||||
var newCountEl = doc.querySelector('.comments-count');
|
||||
if (countEl && newCountEl) {
|
||||
countEl.textContent = newCountEl.textContent;
|
||||
}
|
||||
} else {
|
||||
listContainer.innerHTML = '';
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.error('[AKSRT Comment] 刷新评论列表失败:', error);
|
||||
// 失败时降级为整页刷新
|
||||
window.location.reload();
|
||||
});
|
||||
}
|
||||
|
||||
/* ====== 评论排序(最新 / 最早) ====== */
|
||||
function initCommentOrder(root) {
|
||||
var scope = root || document;
|
||||
var commentsArea = scope.getElementById("comments");
|
||||
if (!commentsArea) return;
|
||||
if (commentsArea.dataset.orderInit === "1") return;
|
||||
commentsArea.dataset.orderInit = "1";
|
||||
|
||||
function getPaginationEl(root) {
|
||||
if (!root) return null;
|
||||
return root.querySelector(".aksrt-comment-pagination, .comment-navigation");
|
||||
}
|
||||
|
||||
function renderLoadingState() {
|
||||
var listContainer = commentsArea.querySelector("#comment-list");
|
||||
if (!listContainer) return;
|
||||
listContainer.innerHTML = '<li class="comment-loading-skeleton">' +
|
||||
'<div class="aksrt-comment"><div class="aksrt-comment__body">' +
|
||||
'<div style="height:60px;background:#f0f0f0;border-radius:8px;margin-bottom:10px;animation:pulse 1.5s ease-in-out infinite;"></div>' +
|
||||
'<div style="height:20px;width:70%;background:#f0f0f0;border-radius:4px;animation:pulse 1.5s ease-in-out infinite;"></div>' +
|
||||
'</div></div></li>';
|
||||
}
|
||||
function applyCommentOrder(order) {
|
||||
if (order !== "newest" && order !== "oldest" && order !== "hottest") {
|
||||
order = "newest";
|
||||
}
|
||||
|
||||
renderLoadingState();
|
||||
|
||||
var url = new URL(window.location.href);
|
||||
url.searchParams.set("aksrt_comment_order", order);
|
||||
url.searchParams.delete("cpage");
|
||||
var fetchUrl = new URL(url.toString());
|
||||
fetchUrl.searchParams.set("_cache_bust", Date.now().toString());
|
||||
|
||||
fetch(fetchUrl.toString(), {
|
||||
method: "GET",
|
||||
credentials: "same-origin"
|
||||
})
|
||||
.then(function (response) { return response.text(); })
|
||||
.then(function (html) {
|
||||
var parser = new DOMParser();
|
||||
var doc = parser.parseFromString(html, "text/html");
|
||||
var newComments = doc.getElementById("comments");
|
||||
if (!newComments) {
|
||||
throw new Error("new comments area not found");
|
||||
}
|
||||
|
||||
var currentFilter = commentsArea.querySelector(".comment-filter");
|
||||
var newFilter = newComments.querySelector(".comment-filter");
|
||||
if (currentFilter && newFilter) {
|
||||
currentFilter.replaceWith(newFilter.cloneNode(true));
|
||||
}
|
||||
|
||||
var currentList = commentsArea.querySelector("#comment-list");
|
||||
var newList = newComments.querySelector("#comment-list");
|
||||
if (currentList && newList) {
|
||||
currentList.replaceWith(newList.cloneNode(true));
|
||||
}
|
||||
|
||||
var currentPagination = getPaginationEl(commentsArea);
|
||||
var newPagination = getPaginationEl(newComments);
|
||||
if (currentPagination && newPagination) {
|
||||
currentPagination.replaceWith(newPagination.cloneNode(true));
|
||||
} else if (currentPagination && !newPagination) {
|
||||
currentPagination.remove();
|
||||
} else if (!currentPagination && newPagination) {
|
||||
var list = commentsArea.querySelector("#comment-list");
|
||||
if (list && list.parentNode) {
|
||||
list.parentNode.insertBefore(newPagination.cloneNode(true), list.nextSibling);
|
||||
}
|
||||
}
|
||||
var currentCount = commentsArea.querySelector(".comments-count");
|
||||
var newCount = newComments.querySelector(".comments-count");
|
||||
if (currentCount && newCount) {
|
||||
currentCount.textContent = newCount.textContent;
|
||||
}
|
||||
|
||||
if (window.history && typeof window.history.replaceState === "function") {
|
||||
window.history.replaceState(null, "", url.toString());
|
||||
}
|
||||
|
||||
if (window.AksrtFrontend) AksrtFrontend.rehydrate(commentsArea, 'ajax');
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.error("[AKSRT Comment] 排序刷新失败:", error);
|
||||
window.location.href = url.toString();
|
||||
});
|
||||
}
|
||||
|
||||
commentsArea.addEventListener("click", function (e) {
|
||||
var link = e.target.closest(".comment-orderby");
|
||||
if (link && commentsArea.contains(link)) {
|
||||
e.preventDefault();
|
||||
var order = (link.dataset && link.dataset.order) ? link.dataset.order : "newest";
|
||||
applyCommentOrder(order);
|
||||
return;
|
||||
}
|
||||
|
||||
var authorLink = e.target.closest(".comment-author-filter");
|
||||
if (authorLink && commentsArea.contains(authorLink)) {
|
||||
e.preventDefault();
|
||||
var authorOnly = (authorLink.dataset && authorLink.dataset.authorOnly) ? authorLink.dataset.authorOnly : "1";
|
||||
applyAuthorFilter(authorOnly);
|
||||
}
|
||||
});
|
||||
|
||||
function applyAuthorFilter(authorOnly) {
|
||||
renderLoadingState();
|
||||
|
||||
var url = new URL(window.location.href);
|
||||
if (authorOnly === "1") {
|
||||
url.searchParams.set("aksrt_author_only", "1");
|
||||
} else {
|
||||
url.searchParams.delete("aksrt_author_only");
|
||||
}
|
||||
url.searchParams.delete("cpage");
|
||||
var fetchUrl = new URL(url.toString());
|
||||
fetchUrl.searchParams.set("_cache_bust", Date.now().toString());
|
||||
fetch(fetchUrl.toString(), {
|
||||
method: "GET",
|
||||
credentials: "same-origin"
|
||||
})
|
||||
.then(function (response) { return response.text(); })
|
||||
.then(function (html) {
|
||||
var parser = new DOMParser();
|
||||
var doc = parser.parseFromString(html, "text/html");
|
||||
var newComments = doc.getElementById("comments");
|
||||
if (!newComments) {
|
||||
throw new Error("new comments area not found");
|
||||
}
|
||||
|
||||
var currentFilter = commentsArea.querySelector(".comment-filter");
|
||||
var newFilter = newComments.querySelector(".comment-filter");
|
||||
if (currentFilter && newFilter) {
|
||||
currentFilter.replaceWith(newFilter.cloneNode(true));
|
||||
}
|
||||
|
||||
var currentList = commentsArea.querySelector("#comment-list");
|
||||
var newList = newComments.querySelector("#comment-list");
|
||||
if (currentList && newList) {
|
||||
currentList.replaceWith(newList.cloneNode(true));
|
||||
}
|
||||
|
||||
if (window.history && typeof window.history.replaceState === "function") {
|
||||
window.history.replaceState(null, "", url.toString());
|
||||
}
|
||||
|
||||
if (window.AksrtFrontend) AksrtFrontend.rehydrate(commentsArea, 'ajax');
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.error("[AKSRT Comment] Author filter failed:", error);
|
||||
window.location.href = url.toString();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
window.AksrtFrontend.register("aksrt-comment-system", function () { initCommentSystem(); });
|
||||
window.AksrtFrontend.register("aksrt-comment-order", function (root) { initCommentOrder(root); });
|
||||
})();
|
||||
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* AKSRT Dropdown Menus — user, auth, post-meta
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function initUserDropdown() {
|
||||
var toggle = document.getElementById("user-menu-toggle");
|
||||
var menu = document.getElementById("user-dropdown");
|
||||
if (!toggle || !menu) return;
|
||||
|
||||
function close() {
|
||||
menu.classList.remove("is-open");
|
||||
toggle.setAttribute("aria-expanded", "false");
|
||||
}
|
||||
|
||||
toggle.addEventListener("click", function (e) {
|
||||
e.stopPropagation();
|
||||
var open = !menu.classList.contains("is-open");
|
||||
menu.classList.toggle("is-open", open);
|
||||
toggle.setAttribute("aria-expanded", open ? "true" : "false");
|
||||
});
|
||||
|
||||
document.addEventListener("click", function (e) {
|
||||
if (!menu.contains(e.target) && e.target !== toggle) close();
|
||||
});
|
||||
document.addEventListener("touchstart", function (e) {
|
||||
if (!menu.contains(e.target) && e.target !== toggle) close();
|
||||
}, { passive: true });
|
||||
document.addEventListener("keydown", function (e) {
|
||||
if (e.key === "Escape") close();
|
||||
});
|
||||
}
|
||||
|
||||
function initAuthDropdown() {
|
||||
var trigger = document.getElementById("nav-auth-trigger");
|
||||
var container = document.getElementById("nav-auth-dropdown");
|
||||
if (!trigger || !container) return;
|
||||
|
||||
function close() {
|
||||
container.classList.remove("is-open");
|
||||
trigger.setAttribute("aria-expanded", "false");
|
||||
}
|
||||
|
||||
trigger.addEventListener("click", function (e) {
|
||||
e.stopPropagation();
|
||||
var open = !container.classList.contains("is-open");
|
||||
container.classList.toggle("is-open", open);
|
||||
trigger.setAttribute("aria-expanded", open ? "true" : "false");
|
||||
});
|
||||
|
||||
document.addEventListener("click", function (e) {
|
||||
if (!container.contains(e.target) && e.target !== trigger) close();
|
||||
});
|
||||
document.addEventListener("touchstart", function (e) {
|
||||
if (!container.contains(e.target) && e.target !== trigger) close();
|
||||
}, { passive: true });
|
||||
document.addEventListener("keydown", function (e) {
|
||||
if (e.key === "Escape") close();
|
||||
});
|
||||
}
|
||||
|
||||
function initPostDropMeta() {
|
||||
document.querySelectorAll('.post-drop-meta').forEach(function (wrap) {
|
||||
if (!wrap || wrap.dataset.aksrtDropMetaBound === '1') return;
|
||||
var trigger = wrap.querySelector('.post-drop-meta__toggle');
|
||||
var menu = wrap.querySelector('.post-drop-meta__menu');
|
||||
if (!trigger || !menu) return;
|
||||
wrap.dataset.aksrtDropMetaBound = '1';
|
||||
|
||||
function close() {
|
||||
wrap.classList.remove('is-open');
|
||||
trigger.setAttribute('aria-expanded', 'false');
|
||||
menu.setAttribute('aria-hidden', 'true');
|
||||
}
|
||||
|
||||
trigger.addEventListener('click', function (e) {
|
||||
e.stopPropagation();
|
||||
var open = !wrap.classList.contains('is-open');
|
||||
document.querySelectorAll('.post-drop-meta.is-open').forEach(function (other) {
|
||||
if (other !== wrap) {
|
||||
other.classList.remove('is-open');
|
||||
var otherTrigger = other.querySelector('.post-drop-meta__toggle');
|
||||
var otherMenu = other.querySelector('.post-drop-meta__menu');
|
||||
if (otherTrigger) otherTrigger.setAttribute('aria-expanded', 'false');
|
||||
if (otherMenu) otherMenu.setAttribute('aria-hidden', 'true');
|
||||
}
|
||||
});
|
||||
wrap.classList.toggle('is-open', open);
|
||||
trigger.setAttribute('aria-expanded', open ? 'true' : 'false');
|
||||
menu.setAttribute('aria-hidden', open ? 'false' : 'true');
|
||||
});
|
||||
|
||||
document.addEventListener('click', function (e) {
|
||||
if (!wrap.contains(e.target)) close();
|
||||
});
|
||||
document.addEventListener('touchstart', function (e) {
|
||||
if (!wrap.contains(e.target)) close();
|
||||
}, { passive: true });
|
||||
document.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'Escape') close();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
window.AksrtFrontend.register("aksrt-user-dropdown", function () { initUserDropdown(); });
|
||||
window.AksrtFrontend.register("aksrt-auth-dropdown", function () { initAuthDropdown(); });
|
||||
window.AksrtFrontend.register("aksrt-post-drop-meta", function () { initPostDropMeta(); });
|
||||
})();
|
||||
@@ -0,0 +1,140 @@
|
||||
/**
|
||||
* AKSRT Footer Tabbar
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function initFooterTabbar() {
|
||||
var tabbar = document.getElementById("footer-tabbar");
|
||||
if (!tabbar) return;
|
||||
var addBackdrop = document.getElementById("tabbar-add-backdrop");
|
||||
|
||||
var ticking = false;
|
||||
var scrollThreshold = 100;
|
||||
var isHidden = false;
|
||||
|
||||
// Use body scroll bus classes from aksrt-runtime.js
|
||||
function handleScrollDownHide() {
|
||||
var body = document.body;
|
||||
var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
||||
|
||||
if (scrollTop > scrollThreshold) {
|
||||
if (body.classList.contains("scroll-down") && !isHidden) {
|
||||
// 向下滚动 - 隐藏
|
||||
tabbar.classList.add("is-hidden");
|
||||
isHidden = true;
|
||||
} else if (body.classList.contains("scroll-up") && isHidden) {
|
||||
tabbar.classList.remove("is-hidden");
|
||||
isHidden = false;
|
||||
}
|
||||
} else {
|
||||
tabbar.classList.remove("is-hidden");
|
||||
isHidden = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 返回顶部按钮切换
|
||||
function handleOntopWrap() {
|
||||
var ontopWraps = tabbar.querySelectorAll(".tabbar-ontop-wrap");
|
||||
var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
||||
|
||||
ontopWraps.forEach(function (wrap) {
|
||||
if (scrollTop > scrollThreshold) {
|
||||
wrap.classList.add("is-scrolled");
|
||||
} else {
|
||||
wrap.classList.remove("is-scrolled");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 滚动事件处理
|
||||
function onScroll() {
|
||||
if (!ticking) {
|
||||
requestAnimationFrame(function () {
|
||||
if (tabbar.classList.contains("scroll-down-hide")) {
|
||||
handleScrollDownHide();
|
||||
}
|
||||
handleOntopWrap();
|
||||
ticking = false;
|
||||
});
|
||||
ticking = true;
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("scroll", onScroll, { passive: true });
|
||||
|
||||
function closeAddPanels() {
|
||||
document.querySelectorAll(".tabbar-add-panel").forEach(function (panel) {
|
||||
panel.setAttribute("hidden", "");
|
||||
});
|
||||
if (addBackdrop) addBackdrop.setAttribute("hidden", "");
|
||||
document.body.classList.remove("tabbar-add-open");
|
||||
}
|
||||
|
||||
function openAddPanel(panelId) {
|
||||
closeAddPanels();
|
||||
var panel = document.getElementById(panelId);
|
||||
if (!panel) return;
|
||||
panel.removeAttribute("hidden");
|
||||
if (addBackdrop) addBackdrop.removeAttribute("hidden");
|
||||
document.body.classList.add("tabbar-add-open");
|
||||
}
|
||||
|
||||
if (addBackdrop) {
|
||||
addBackdrop.addEventListener("click", closeAddPanels);
|
||||
}
|
||||
|
||||
document.addEventListener("keydown", function (e) {
|
||||
if (e.key === "Escape") closeAddPanels();
|
||||
});
|
||||
|
||||
// 返回顶部点击事件 + 双击首页刷新
|
||||
var homeClickTimer = null;
|
||||
tabbar.addEventListener("click", function (e) {
|
||||
var addBtn = e.target.closest('.tabbar-item[data-type="add"]');
|
||||
if (addBtn) {
|
||||
e.preventDefault();
|
||||
openAddPanel(addBtn.getAttribute("data-panel-id"));
|
||||
return;
|
||||
}
|
||||
|
||||
var searchBtn = e.target.closest('.tabbar-item[data-type="search"]');
|
||||
if (searchBtn) {
|
||||
e.preventDefault();
|
||||
if (typeof window.__aksrtOpenSearchPanel === "function") {
|
||||
window.__aksrtOpenSearchPanel();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var ontopBtn = e.target.closest(".tabbar-ontop-btn");
|
||||
if (ontopBtn) {
|
||||
e.preventDefault();
|
||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||
return;
|
||||
}
|
||||
|
||||
// 双击首页Tab刷新页面
|
||||
var homeBtn = e.target.closest('.tabbar-item[data-type="home"]');
|
||||
if (homeBtn && tabbar.classList.contains("has-animation")) {
|
||||
if (homeClickTimer) {
|
||||
clearTimeout(homeClickTimer);
|
||||
homeClickTimer = null;
|
||||
window.location.reload();
|
||||
return;
|
||||
}
|
||||
homeClickTimer = setTimeout(function () {
|
||||
homeClickTimer = null;
|
||||
}, 350);
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener("click", function (e) {
|
||||
if (e.target.closest("[data-close-tabbar-add-panel]")) {
|
||||
closeAddPanels();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
window.AksrtFrontend.register("aksrt-footer-tabbar", function () { initFooterTabbar(); });
|
||||
})();
|
||||
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* AKSRT Misc — related swiper, slide covers, hidden content
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function initRelatedSwiper() {
|
||||
var el = document.querySelector(".related-swiper[data-swiper-config]");
|
||||
if (!el || typeof Swiper === "undefined") return;
|
||||
|
||||
var config = {};
|
||||
try { config = JSON.parse(el.dataset.swiperConfig || "{}"); } catch (e) {}
|
||||
new Swiper(el, Object.assign({
|
||||
slidesPerView: "auto",
|
||||
spaceBetween: 12,
|
||||
freeMode: true,
|
||||
navigation: {
|
||||
nextEl: ".related-swiper-next",
|
||||
prevEl: ".related-swiper-prev",
|
||||
},
|
||||
}, config));
|
||||
}
|
||||
|
||||
window.AksrtFrontend.register("aksrt-related-swiper", function () { initRelatedSwiper(); });
|
||||
})();
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function initSlideCovers() {
|
||||
var covers = document.querySelectorAll(".single-cover--slide");
|
||||
covers.forEach(function (cover) {
|
||||
var slides = cover.querySelectorAll(".single-cover__slide");
|
||||
var dots = cover.querySelectorAll(".single-cover__dot");
|
||||
if (slides.length < 2) return;
|
||||
|
||||
var current = 0;
|
||||
var interval = 5000;
|
||||
|
||||
function goTo(idx) {
|
||||
slides[current].classList.remove("is-active");
|
||||
if (dots[current]) dots[current].classList.remove("is-active");
|
||||
current = idx;
|
||||
slides[current].classList.add("is-active");
|
||||
if (dots[current]) dots[current].classList.add("is-active");
|
||||
}
|
||||
|
||||
var timer = setInterval(function () {
|
||||
goTo((current + 1) % slides.length);
|
||||
}, interval);
|
||||
|
||||
dots.forEach(function (dot, i) {
|
||||
dot.addEventListener("click", function () {
|
||||
clearInterval(timer);
|
||||
goTo(i);
|
||||
timer = setInterval(function () {
|
||||
goTo((current + 1) % slides.length);
|
||||
}, interval);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", initSlideCovers);
|
||||
} else {
|
||||
initSlideCovers();
|
||||
}
|
||||
})();
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function initHiddenContent() {
|
||||
document.addEventListener("click", function (e) {
|
||||
var btn = e.target.closest(".aksrt-hidden-content__submit-btn");
|
||||
if (!btn) return;
|
||||
|
||||
e.preventDefault();
|
||||
var wrapper = btn.closest(".aksrt-hidden-content--locked");
|
||||
if (!wrapper) return;
|
||||
|
||||
var mode = wrapper.getAttribute("data-aksrt-visibility-mode");
|
||||
var pid = wrapper.getAttribute("data-aksrt-visibility-pid");
|
||||
var input = wrapper.querySelector(".aksrt-hidden-content__password-input");
|
||||
var password = input ? input.value.trim() : "";
|
||||
|
||||
if (mode === "password" && !password) {
|
||||
if (input) input.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
var formData = new FormData();
|
||||
formData.append("action", "aksrt_check_visibility");
|
||||
formData.append("_nonce", (window.aksrtData && aksrtData.visibilityNonce) || "");
|
||||
formData.append("mode", mode);
|
||||
formData.append("pid", pid);
|
||||
if (password) formData.append("password", password);
|
||||
|
||||
btn.disabled = true;
|
||||
btn.textContent = "...";
|
||||
|
||||
fetch((window.aksrtData && aksrtData.ajaxUrl) || "/wp-admin/admin-ajax.php", {
|
||||
method: "POST",
|
||||
body: formData,
|
||||
credentials: "same-origin",
|
||||
})
|
||||
.then(function (res) { return res.json(); })
|
||||
.then(function (data) {
|
||||
if (data.success) {
|
||||
window.location.reload();
|
||||
} else {
|
||||
var msg = (data.data && data.data.message) ? data.data.message : "验证失败";
|
||||
alert(msg);
|
||||
btn.disabled = false;
|
||||
btn.textContent = "验证";
|
||||
}
|
||||
})
|
||||
.catch(function () {
|
||||
alert("网络错误,请重试");
|
||||
btn.disabled = false;
|
||||
btn.textContent = "验证";
|
||||
});
|
||||
});
|
||||
|
||||
// Handle Enter key on password input
|
||||
document.addEventListener("keydown", function (e) {
|
||||
if (e.key === "Enter" && e.target.classList.contains("aksrt-hidden-content__password-input")) {
|
||||
e.preventDefault();
|
||||
var wrapper = e.target.closest(".aksrt-hidden-content--locked");
|
||||
if (wrapper) {
|
||||
var btn = wrapper.querySelector(".aksrt-hidden-content__submit-btn");
|
||||
if (btn) btn.click();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", initHiddenContent);
|
||||
} else {
|
||||
initHiddenContent();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* AKSRT Navigation Drawer
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function initNavDrawer() {
|
||||
var toggle = document.getElementById("nav-toggle");
|
||||
var drawer = document.getElementById("nav-drawer");
|
||||
var backdrop = document.getElementById("nav-drawer-backdrop");
|
||||
var closeBtn = document.getElementById("nav-drawer-close");
|
||||
if (!toggle || !drawer || !backdrop) return;
|
||||
|
||||
var openIcon = toggle.querySelector(".nav-toggle-open");
|
||||
var closeIcon = toggle.querySelector(".nav-toggle-close");
|
||||
|
||||
function setOpen(open) {
|
||||
toggle.setAttribute("aria-expanded", open ? "true" : "false");
|
||||
drawer.classList.toggle("is-open", open);
|
||||
backdrop.classList.toggle("is-open", open);
|
||||
drawer.setAttribute("aria-hidden", open ? "false" : "true");
|
||||
backdrop.setAttribute("aria-hidden", open ? "false" : "true");
|
||||
document.body.style.overflow = open ? "hidden" : "";
|
||||
if (openIcon && closeIcon) {
|
||||
openIcon.style.display = open ? "none" : "";
|
||||
closeIcon.style.display = open ? "" : "none";
|
||||
}
|
||||
if (open && typeof window.__aksrtCloseSearchPanel === "function") {
|
||||
window.__aksrtCloseSearchPanel();
|
||||
}
|
||||
}
|
||||
|
||||
setOpen(false);
|
||||
|
||||
toggle.addEventListener("click", function () {
|
||||
setOpen(!drawer.classList.contains("is-open"));
|
||||
});
|
||||
backdrop.addEventListener("click", function () {
|
||||
setOpen(false);
|
||||
});
|
||||
if (closeBtn) closeBtn.addEventListener("click", function () {
|
||||
setOpen(false);
|
||||
});
|
||||
|
||||
document.addEventListener("keydown", function (e) {
|
||||
if (e.key === "Escape" && drawer.classList.contains("is-open")) {
|
||||
setOpen(false);
|
||||
toggle.focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
window.AksrtFrontend.register("aksrt-nav-drawer", function () { initNavDrawer(); });
|
||||
})();
|
||||
@@ -0,0 +1,270 @@
|
||||
/**
|
||||
* AKSRT AJAX Pagination & Lazy Load
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function initAjaxPagination(root) {
|
||||
var containers = (root || document).querySelectorAll(".aksrt-pagination-ajax, .ajax-pagination");
|
||||
if (!containers.length) return;
|
||||
|
||||
var triggerText = (window.aksrtData && aksrtData.ajaxTrigger) || "加载更多";
|
||||
var nomoreText = (window.aksrtData && aksrtData.ajaxNomore) || "没有更多了";
|
||||
var loadingText = (window.aksrtData && aksrtData.ajaxLoading) || "正在加载...";
|
||||
|
||||
containers.forEach(function (container) {
|
||||
if (container.dataset.aksrtPaginationBound === "1") return;
|
||||
container.dataset.aksrtPaginationBound = "1";
|
||||
|
||||
var mode = container.dataset.mode || "load_more";
|
||||
var nextPage = parseInt(container.dataset.nextPage, 10) || 2;
|
||||
var maxPages = parseInt(container.dataset.maxPages, 10) || 1;
|
||||
var isComment = container.classList.contains("aksrt-comment-pagination");
|
||||
var postId = container.dataset.postId || "";
|
||||
var commentOrder = container.dataset.commentOrder || "newest";
|
||||
var loading = false;
|
||||
var loadMoreBtn = container.querySelector(".aksrt-load-more-btn, .ajax-next");
|
||||
var indicator = container.querySelector(".aksrt-loading-indicator");
|
||||
// 目标容器:文章列表取 .post-grid,评论取 .comment-list
|
||||
var target = container.previousElementSibling;
|
||||
|
||||
function showSkeleton() {
|
||||
if (!target) return;
|
||||
var loader = target.querySelector(".post-ajax-loader");
|
||||
if (loader) {
|
||||
loader.classList.add("is-loading");
|
||||
}
|
||||
}
|
||||
|
||||
function hideSkeleton() {
|
||||
if (!target) return;
|
||||
var loader = target.querySelector(".post-ajax-loader");
|
||||
if (loader) {
|
||||
loader.classList.remove("is-loading");
|
||||
}
|
||||
}
|
||||
|
||||
function loadNextPage() {
|
||||
if (loading || nextPage > maxPages || !target) return;
|
||||
loading = true;
|
||||
if (indicator) indicator.style.display = "flex";
|
||||
if (loadMoreBtn) {
|
||||
loadMoreBtn.classList.add("is-loading");
|
||||
loadMoreBtn.textContent = loadingText;
|
||||
}
|
||||
showSkeleton();
|
||||
|
||||
var action = isComment ? "aksrt_load_more_comments" : "aksrt_load_more_posts";
|
||||
var queryContext = container.dataset.queryContext || "";
|
||||
var queryVars = container.dataset.queryVars || "";
|
||||
var renderConfig = container.dataset.renderConfig || "";
|
||||
var body = new URLSearchParams();
|
||||
body.set("action", action);
|
||||
body.set("nonce", aksrtData.nonce);
|
||||
body.set("page", String(nextPage));
|
||||
if (queryContext) {
|
||||
body.set("query_context", queryContext);
|
||||
}
|
||||
if (!isComment && queryVars) {
|
||||
body.set("query_vars", queryVars);
|
||||
}
|
||||
if (!isComment && renderConfig) {
|
||||
body.set("render_config", renderConfig);
|
||||
}
|
||||
if (isComment && postId) {
|
||||
body.set("post_id", postId);
|
||||
body.set("comment_order", commentOrder);
|
||||
}
|
||||
|
||||
fetch(aksrtData.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.success && res.data && res.data.html) {
|
||||
var temp = document.createElement("div");
|
||||
temp.innerHTML = res.data.html;
|
||||
var newItems = temp.children;
|
||||
while (newItems.length > 0) {
|
||||
target.appendChild(newItems[0]);
|
||||
}
|
||||
nextPage++;
|
||||
container.dataset.nextPage = String(nextPage);
|
||||
|
||||
// 重新初始化懒加载(新加载的图片)
|
||||
if (typeof initLazyLoad === "function") initLazyLoad();
|
||||
|
||||
// 如果没有更多页
|
||||
if (nextPage > maxPages || !res.data.has_more) {
|
||||
if (loadMoreBtn) {
|
||||
loadMoreBtn.textContent = nomoreText;
|
||||
loadMoreBtn.classList.remove("is-loading");
|
||||
loadMoreBtn.classList.add("ajax-nomore");
|
||||
loadMoreBtn.style.pointerEvents = "none";
|
||||
} else {
|
||||
container.innerHTML = '<span class="ajax-nomore">' + nomoreText + '</span>';
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(function () {})
|
||||
.finally(function () {
|
||||
loading = false;
|
||||
hideSkeleton();
|
||||
if (indicator) indicator.style.display = "none";
|
||||
if (loadMoreBtn && !loadMoreBtn.classList.contains("ajax-nomore")) {
|
||||
loadMoreBtn.classList.remove("is-loading");
|
||||
loadMoreBtn.textContent = triggerText;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 加载更多按钮点击
|
||||
if (loadMoreBtn) {
|
||||
loadMoreBtn.addEventListener("click", function(e) {
|
||||
e.preventDefault();
|
||||
if (loadMoreBtn.dataset.jumpComments === "1") {
|
||||
var jumpInput = container.querySelector(".jump-input");
|
||||
if (!jumpInput) return;
|
||||
var targetPage = parseInt(jumpInput.value, 10) || 1;
|
||||
var max = parseInt(jumpInput.dataset.maxPages || String(maxPages), 10) || maxPages;
|
||||
targetPage = Math.max(1, Math.min(max, targetPage));
|
||||
var url = new URL(window.location.href);
|
||||
url.searchParams.set("cpage", String(targetPage));
|
||||
window.location.href = url.toString();
|
||||
return;
|
||||
}
|
||||
if (loadMoreBtn.dataset.jumpArchive === "1") {
|
||||
var archiveJumpInput = container.querySelector(".jump-input");
|
||||
if (!archiveJumpInput) return;
|
||||
var archiveTargetPage = parseInt(archiveJumpInput.value, 10) || 1;
|
||||
var archiveMax = parseInt(archiveJumpInput.dataset.maxPages || String(maxPages), 10) || maxPages;
|
||||
archiveTargetPage = Math.max(1, Math.min(archiveMax, archiveTargetPage));
|
||||
var archiveUrl = new URL(window.location.href);
|
||||
archiveUrl.searchParams.set("paged", String(archiveTargetPage));
|
||||
window.location.href = archiveUrl.toString();
|
||||
return;
|
||||
}
|
||||
loadNextPage();
|
||||
});
|
||||
}
|
||||
|
||||
// 无限滚动:IntersectionObserver
|
||||
if (mode === "infinite" && "IntersectionObserver" in window) {
|
||||
// Comment containers respect commentIasAuto; if disabled, fall back to click-to-load
|
||||
if (isComment && window.aksrtData && aksrtData.commentIasAuto === false) {
|
||||
// Skip IntersectionObserver — load_more button already present
|
||||
} else {
|
||||
var sentinel = document.createElement("div");
|
||||
sentinel.className = "aksrt-scroll-sentinel";
|
||||
container.appendChild(sentinel);
|
||||
var lazyloadAction = container.dataset.lazyloadAction || "";
|
||||
var iasMax = isComment
|
||||
? ((window.aksrtData && typeof aksrtData.commentIasMax !== "undefined") ? parseInt(aksrtData.commentIasMax, 10) : 0)
|
||||
: ((window.aksrtData && typeof aksrtData.iasMax !== "undefined") ? parseInt(aksrtData.iasMax, 10) : 0);
|
||||
var initialPage = nextPage - 1; // page at init time
|
||||
var observer = new IntersectionObserver(
|
||||
function (entries) {
|
||||
if (entries[0].isIntersecting && !loading) {
|
||||
// iasMax = 0 means unlimited, otherwise limit additional pages
|
||||
if (iasMax > 0 && (nextPage - initialPage) >= iasMax) {
|
||||
// Reached ias max, show nomore and disconnect
|
||||
observer.disconnect();
|
||||
if (loadMoreBtn) {
|
||||
loadMoreBtn.textContent = nomoreText;
|
||||
loadMoreBtn.classList.add("ajax-nomore");
|
||||
loadMoreBtn.style.pointerEvents = "none";
|
||||
}
|
||||
return;
|
||||
}
|
||||
loadNextPage();
|
||||
}
|
||||
},
|
||||
{ rootMargin: "400px" }
|
||||
);
|
||||
if (lazyloadAction === "ias") {
|
||||
container.classList.add("ias-pending");
|
||||
}
|
||||
observer.observe(sentinel);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* ====== 图片懒加载 ====== */
|
||||
function initLazyLoad(root) {
|
||||
var scope = root || document;
|
||||
var lazyImages = scope.querySelectorAll("img.aksrt-lazy");
|
||||
if (!lazyImages.length) return;
|
||||
|
||||
// 不支持 IntersectionObserver 时直接加载所有图片
|
||||
if (!("IntersectionObserver" in window)) {
|
||||
lazyImages.forEach(function (img) {
|
||||
var src = img.dataset.src;
|
||||
if (src) {
|
||||
img.src = src;
|
||||
img.classList.remove("aksrt-lazy");
|
||||
img.classList.add("aksrt-loaded");
|
||||
}
|
||||
var skeleton = img.previousElementSibling;
|
||||
if (skeleton && skeleton.classList.contains("aksrt-skeleton")) {
|
||||
skeleton.remove();
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var observer = new IntersectionObserver(function (entries) {
|
||||
entries.forEach(function (entry) {
|
||||
if (!entry.isIntersecting) return;
|
||||
|
||||
var img = entry.target;
|
||||
var src = img.dataset.src;
|
||||
if (!src) {
|
||||
observer.unobserve(img);
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建新图片预加载
|
||||
var tempImg = new Image();
|
||||
tempImg.onload = function () {
|
||||
img.src = src;
|
||||
img.classList.remove("aksrt-lazy");
|
||||
img.classList.add("aksrt-loaded");
|
||||
// 移除骨架
|
||||
var skeleton = img.previousElementSibling;
|
||||
if (skeleton && skeleton.classList.contains("aksrt-skeleton")) {
|
||||
skeleton.remove();
|
||||
}
|
||||
};
|
||||
tempImg.onerror = function () {
|
||||
img.classList.remove("aksrt-lazy");
|
||||
img.classList.add("aksrt-error");
|
||||
// 移除骨架
|
||||
var skeleton = img.previousElementSibling;
|
||||
if (skeleton && skeleton.classList.contains("aksrt-skeleton")) {
|
||||
skeleton.remove();
|
||||
}
|
||||
};
|
||||
tempImg.src = src;
|
||||
|
||||
observer.unobserve(img);
|
||||
});
|
||||
}, {
|
||||
rootMargin: "200px 0px",
|
||||
threshold: 0.01
|
||||
});
|
||||
|
||||
lazyImages.forEach(function (img) {
|
||||
observer.observe(img);
|
||||
});
|
||||
}
|
||||
|
||||
window.AksrtFrontend.register("aksrt-ajax-pagination", function (root) { initAjaxPagination(root); });
|
||||
window.AksrtFrontend.register("aksrt-lazy-load", function (root) { initLazyLoad(root); });
|
||||
})();
|
||||
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* AKSRT Scroll Behaviors — back-to-top, floating buttons, reading progress, nav scroll
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function initBackToTop() {
|
||||
var el = document.getElementById("float-back-to-top") || document.getElementById("back-to-top");
|
||||
if (!el) return;
|
||||
|
||||
function onScroll() {
|
||||
if (window.scrollY > 400) {
|
||||
el.classList.add("is-visible");
|
||||
} else {
|
||||
el.classList.remove("is-visible");
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("scroll", onScroll, { passive: true });
|
||||
onScroll();
|
||||
|
||||
el.addEventListener("click", function (e) {
|
||||
e.preventDefault();
|
||||
if (window.aksrt && aksrt.scrollTopTo) {
|
||||
aksrt.scrollTopTo(0);
|
||||
} else {
|
||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function initFloatingButtons() {
|
||||
var wrap = document.getElementById("float-right-btns");
|
||||
if (!wrap) return;
|
||||
|
||||
function debugEnabled() {
|
||||
return !!(window.aksrtData && aksrtData.debug);
|
||||
}
|
||||
|
||||
function debugLog(message, context, level) {
|
||||
if (!debugEnabled()) return;
|
||||
var method = level === "error" ? "error" : (level === "warn" ? "warn" : "log");
|
||||
console[method]("[AKSRT FloatingButtons] " + message, context || {});
|
||||
}
|
||||
|
||||
function reportDebug(eventName, payload) {
|
||||
if (!(window.aksrtData && aksrtData.debugLog && aksrtData.ajaxUrl && aksrtData.nonce)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var body = new URLSearchParams();
|
||||
body.set("action", "aksrt_frontend_debug");
|
||||
body.set("nonce", aksrtData.nonce);
|
||||
body.set("source", "floating_buttons");
|
||||
body.set("event", eventName);
|
||||
body.set("page", window.location.href);
|
||||
if (payload && payload.text) body.set("text", String(payload.text));
|
||||
if (payload && payload.size) body.set("size", String(payload.size));
|
||||
if (payload && payload.error) body.set("error", String(payload.error));
|
||||
|
||||
fetch(aksrtData.ajaxUrl, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8" },
|
||||
credentials: "same-origin",
|
||||
body: body.toString()
|
||||
}).catch(function () {});
|
||||
}
|
||||
|
||||
var scrollTimer = null;
|
||||
|
||||
function setHidden(hidden) {
|
||||
wrap.classList.toggle("is-hidden", !!hidden);
|
||||
}
|
||||
|
||||
function syncFromScrollBus() {
|
||||
var body = document.body;
|
||||
if (wrap.classList.contains("scroll-down-hide")) {
|
||||
setHidden(body.classList.contains("scroll-down"));
|
||||
}
|
||||
if (wrap.classList.contains("scrolling-hide")) {
|
||||
setHidden(true);
|
||||
window.clearTimeout(scrollTimer);
|
||||
scrollTimer = window.setTimeout(function () {
|
||||
if (!body.classList.contains("scroll-down")) setHidden(false);
|
||||
}, 160);
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("scroll", function () {
|
||||
requestAnimationFrame(syncFromScrollBus);
|
||||
}, { passive: true });
|
||||
|
||||
wrap.addEventListener("click", function (event) {
|
||||
var btn = event.target.closest(".float-btn");
|
||||
if (!btn) return;
|
||||
|
||||
if (btn.getAttribute("href") === "#") {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
if (btn.hasAttribute("data-action") && btn.getAttribute("data-action") === "toggle-theme") {
|
||||
event.preventDefault();
|
||||
if (window.aksrt && typeof aksrt.toggleTheme === "function") {
|
||||
aksrt.toggleTheme();
|
||||
} else {
|
||||
document.documentElement.classList.toggle("dark");
|
||||
document.body.classList.toggle("dark-theme");
|
||||
}
|
||||
}
|
||||
|
||||
btn.classList.remove("is-rippling");
|
||||
window.requestAnimationFrame(function () {
|
||||
btn.classList.add("is-rippling");
|
||||
window.setTimeout(function () {
|
||||
btn.classList.remove("is-rippling");
|
||||
}, 600);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function initReadingProgress() {
|
||||
var bar = document.getElementById("reading-progress-global");
|
||||
if (!bar) return;
|
||||
|
||||
function update() {
|
||||
var doc = document.documentElement;
|
||||
var scrollable = doc.scrollHeight - window.innerHeight;
|
||||
var pct = scrollable <= 0 ? 100 : Math.min(100, Math.max(0, (window.scrollY / scrollable) * 100));
|
||||
bar.style.width = pct + "%";
|
||||
bar.setAttribute("aria-valuenow", String(Math.round(pct)));
|
||||
}
|
||||
|
||||
window.addEventListener("scroll", update, { passive: true });
|
||||
window.addEventListener("resize", update, { passive: true });
|
||||
update();
|
||||
}
|
||||
|
||||
function initNavScrollState() {
|
||||
var nav = document.querySelector(".site-nav");
|
||||
|
||||
var sliderContainer = document.querySelector(".header-components-container");
|
||||
if (nav && sliderContainer) {
|
||||
nav.classList.add("nav-transparent");
|
||||
}
|
||||
|
||||
var scrollDownHide = document.body.classList.contains("scroll-down-hide");
|
||||
var ticking = false;
|
||||
|
||||
function update() {
|
||||
ticking = false;
|
||||
var body = document.body;
|
||||
if (nav) {
|
||||
nav.classList.toggle("is-scrolled", body.classList.contains("body-scroll"));
|
||||
}
|
||||
if (nav && scrollDownHide) {
|
||||
if (body.classList.contains("scroll-down")) {
|
||||
nav.classList.add("is-hidden");
|
||||
} else {
|
||||
nav.classList.remove("is-hidden");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onScroll() {
|
||||
if (!ticking) {
|
||||
window.requestAnimationFrame(update);
|
||||
ticking = true;
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("scroll", onScroll, { passive: true });
|
||||
window.addEventListener("resize", onScroll, { passive: true });
|
||||
update();
|
||||
}
|
||||
|
||||
window.AksrtFrontend.register("aksrt-floating-buttons", function () { initFloatingButtons(); });
|
||||
window.AksrtFrontend.register("aksrt-back-to-top", function () { initBackToTop(); });
|
||||
window.AksrtFrontend.register("aksrt-reading-progress", function () { initReadingProgress(); });
|
||||
window.AksrtFrontend.register("aksrt-nav-scroll-state", function () { initNavScrollState(); });
|
||||
})();
|
||||
@@ -0,0 +1,340 @@
|
||||
/**
|
||||
* AKSRT Search Panel — desktop panel, mobile overlay, history, suggestions
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function initSearchPanel() {
|
||||
var btn = document.getElementById("search-toggle");
|
||||
var panel = document.getElementById("nav-search-panel");
|
||||
var mobileOverlay = document.getElementById("tabbar-search-overlay");
|
||||
var mobileInput = document.getElementById("tabbar-search-input");
|
||||
var mobileClose = document.getElementById("tabbar-search-close");
|
||||
var mobileForm = mobileOverlay ? mobileOverlay.querySelector("form") : null;
|
||||
var mobileTypeInput = document.getElementById("tabbar-search-type");
|
||||
var mobileTypeButtons = document.querySelectorAll("#tabbar-search-types [data-search-type]");
|
||||
var historyWrap = document.getElementById("tabbar-search-history");
|
||||
var historySection = document.getElementById("tabbar-search-history-section");
|
||||
var historyClear = document.getElementById("tabbar-search-history-clear");
|
||||
var suggestionsWrap = document.getElementById("tabbar-search-suggestions");
|
||||
var suggestionsSection = document.getElementById("tabbar-search-suggestions-section");
|
||||
if (!btn || !panel) return;
|
||||
var HISTORY_KEY = "aksrt-mobile-search-history";
|
||||
var suggestTimer = null;
|
||||
var searchConfig = (window.aksrtData && aksrtData.search) || {};
|
||||
var historyEnabled = searchConfig.historyEnabled !== false;
|
||||
var suggestionsEnabled = !!searchConfig.suggestionsEnabled;
|
||||
|
||||
if (historySection && !historyEnabled) {
|
||||
historySection.hidden = true;
|
||||
}
|
||||
if (suggestionsSection && !suggestionsEnabled) {
|
||||
suggestionsSection.hidden = true;
|
||||
}
|
||||
|
||||
function getSearchType() {
|
||||
return mobileTypeInput ? (mobileTypeInput.value || "post") : "post";
|
||||
}
|
||||
|
||||
function setSearchType(type) {
|
||||
if (!mobileTypeInput) return;
|
||||
mobileTypeInput.value = type;
|
||||
mobileTypeButtons.forEach(function (button) {
|
||||
button.classList.toggle("is-active", button.getAttribute("data-search-type") === type);
|
||||
});
|
||||
requestSuggestions();
|
||||
}
|
||||
|
||||
function readHistory() {
|
||||
if (!historyEnabled) return [];
|
||||
if (aksrtData.isLoggedIn) return [];
|
||||
try {
|
||||
var raw = localStorage.getItem(HISTORY_KEY);
|
||||
var list = raw ? JSON.parse(raw) : [];
|
||||
return Array.isArray(list) ? list : [];
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function writeHistory(items) {
|
||||
if (!historyEnabled) return;
|
||||
if (aksrtData.isLoggedIn) return;
|
||||
try {
|
||||
localStorage.setItem(HISTORY_KEY, JSON.stringify(items.slice(0, 8)));
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
function requestHistorySync(mode, items, callback) {
|
||||
if (!historyEnabled) {
|
||||
if (historySection) historySection.hidden = true;
|
||||
if (typeof callback === "function") callback([]);
|
||||
return;
|
||||
}
|
||||
if (!aksrtData.isLoggedIn) {
|
||||
if (typeof callback === "function") callback(mode === "save" ? (items || []) : readHistory());
|
||||
return;
|
||||
}
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", aksrtData.ajaxUrl, true);
|
||||
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
|
||||
xhr.onload = function () {
|
||||
if (typeof callback !== "function") return;
|
||||
if (xhr.status < 200 || xhr.status >= 300) {
|
||||
callback([]);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
var json = JSON.parse(xhr.responseText);
|
||||
callback(json.success && json.data && Array.isArray(json.data.items) ? json.data.items : []);
|
||||
} catch (e) {
|
||||
callback([]);
|
||||
}
|
||||
};
|
||||
var body = "action=aksrt_search_history&nonce=" + encodeURIComponent(aksrtData.nonce) + "&mode=" + encodeURIComponent(mode);
|
||||
if (mode === "save") {
|
||||
body += "&items=" + encodeURIComponent(JSON.stringify(items || []));
|
||||
}
|
||||
xhr.send(body);
|
||||
}
|
||||
|
||||
function pushHistory(keyword, type) {
|
||||
if (!historyEnabled) return;
|
||||
if (!keyword) return;
|
||||
if (aksrtData.isLoggedIn) {
|
||||
requestHistorySync("get", null, function (remoteItems) {
|
||||
var nextRemote = (remoteItems || []).filter(function (item) {
|
||||
return !(item && item.keyword === keyword && item.type === type);
|
||||
});
|
||||
nextRemote.unshift({ keyword: keyword, type: type });
|
||||
requestHistorySync("save", nextRemote.slice(0, 8), function (savedItems) {
|
||||
renderHistory(savedItems);
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
var next = readHistory().filter(function (item) {
|
||||
return !(item && item.keyword === keyword && item.type === type);
|
||||
});
|
||||
next.unshift({ keyword: keyword, type: type });
|
||||
writeHistory(next);
|
||||
renderHistory();
|
||||
}
|
||||
|
||||
function renderHistory(providedItems) {
|
||||
if (!historyWrap) return;
|
||||
if (!historyEnabled) {
|
||||
if (historySection) historySection.hidden = true;
|
||||
historyWrap.innerHTML = "";
|
||||
return;
|
||||
}
|
||||
|
||||
if (historySection) {
|
||||
historySection.hidden = false;
|
||||
}
|
||||
var items = Array.isArray(providedItems) ? providedItems : readHistory();
|
||||
if (!items.length) {
|
||||
historyWrap.innerHTML = '<div class="tabbar-search-overlay__empty">暂无搜索历史</div>';
|
||||
if (historyClear) historyClear.style.display = "none";
|
||||
return;
|
||||
}
|
||||
if (historyClear) historyClear.style.display = "inline-flex";
|
||||
historyWrap.innerHTML = items.map(function (item) {
|
||||
return '<button type="button" class="tabbar-search-overlay__history-item" data-history-keyword="' + encodeURIComponent(item.keyword) + '" data-history-type="' + encodeURIComponent(item.type || 'post') + '">' +
|
||||
'<i class="fas fa-history"></i><span>' + item.keyword + '</span>' +
|
||||
'</button>';
|
||||
}).join("");
|
||||
}
|
||||
|
||||
function renderSuggestions(items) {
|
||||
if (!suggestionsWrap || !suggestionsSection) return;
|
||||
if (!suggestionsEnabled) {
|
||||
suggestionsSection.hidden = true;
|
||||
suggestionsWrap.innerHTML = "";
|
||||
return;
|
||||
}
|
||||
if (!items || !items.length) {
|
||||
suggestionsWrap.innerHTML = '<div class="tabbar-search-overlay__empty">暂无匹配结果</div>';
|
||||
suggestionsSection.hidden = false;
|
||||
return;
|
||||
}
|
||||
suggestionsWrap.innerHTML = items.map(function (item) {
|
||||
var meta = item.meta ? '<small>' + item.meta + '</small>' : '';
|
||||
return '<a href="' + item.url + '" class="tabbar-search-overlay__suggestion-item">' +
|
||||
'<span>' + item.title + '</span>' + meta +
|
||||
'</a>';
|
||||
}).join("");
|
||||
suggestionsSection.hidden = false;
|
||||
}
|
||||
|
||||
function requestSuggestions() {
|
||||
if (!mobileInput || !suggestionsWrap || !suggestionsSection) return;
|
||||
if (!suggestionsEnabled) {
|
||||
suggestionsSection.hidden = true;
|
||||
return;
|
||||
}
|
||||
var keyword = (mobileInput.value || "").trim();
|
||||
if (suggestTimer) clearTimeout(suggestTimer);
|
||||
if (keyword.length < 2) {
|
||||
suggestionsSection.hidden = true;
|
||||
return;
|
||||
}
|
||||
suggestTimer = setTimeout(function () {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", aksrtData.ajaxUrl, true);
|
||||
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
|
||||
xhr.onload = function () {
|
||||
if (xhr.status < 200 || xhr.status >= 300) return;
|
||||
try {
|
||||
var json = JSON.parse(xhr.responseText);
|
||||
if (json.success && json.data && json.data.items) {
|
||||
renderSuggestions(json.data.items);
|
||||
}
|
||||
} catch (e) {}
|
||||
};
|
||||
xhr.send(
|
||||
"action=aksrt_search_suggestions&nonce=" + encodeURIComponent(aksrtData.nonce) +
|
||||
"&q=" + encodeURIComponent(keyword) +
|
||||
"&type=" + encodeURIComponent(getSearchType())
|
||||
);
|
||||
}, 180);
|
||||
}
|
||||
|
||||
function isMobileSearchMode() {
|
||||
return window.innerWidth < 768 && !!mobileOverlay;
|
||||
}
|
||||
|
||||
function setOpen(open) {
|
||||
if (isMobileSearchMode()) {
|
||||
if (open) {
|
||||
mobileOverlay.removeAttribute("hidden");
|
||||
document.body.classList.add("tabbar-search-open");
|
||||
if (mobileInput) mobileInput.focus();
|
||||
if (historyEnabled) renderHistory();
|
||||
if (suggestionsEnabled) requestSuggestions();
|
||||
} else {
|
||||
mobileOverlay.setAttribute("hidden", "");
|
||||
document.body.classList.remove("tabbar-search-open");
|
||||
if (suggestionsSection) suggestionsSection.hidden = true;
|
||||
}
|
||||
btn.setAttribute("aria-expanded", open ? "true" : "false");
|
||||
return;
|
||||
}
|
||||
|
||||
panel.classList.toggle("is-open", open);
|
||||
btn.setAttribute("aria-expanded", open ? "true" : "false");
|
||||
if (open) {
|
||||
var input = panel.querySelector('input[type="search"]');
|
||||
if (input) input.focus();
|
||||
}
|
||||
}
|
||||
|
||||
btn.addEventListener("click", function (e) {
|
||||
e.stopPropagation();
|
||||
if (isMobileSearchMode()) {
|
||||
setOpen(!mobileOverlay || mobileOverlay.hasAttribute("hidden"));
|
||||
return;
|
||||
}
|
||||
setOpen(!panel.classList.contains("is-open"));
|
||||
});
|
||||
|
||||
document.addEventListener("click", function (e) {
|
||||
if (isMobileSearchMode()) return;
|
||||
if (!panel.classList.contains("is-open")) return;
|
||||
if (panel.contains(e.target) || btn.contains(e.target)) return;
|
||||
setOpen(false);
|
||||
});
|
||||
|
||||
if (mobileOverlay) {
|
||||
mobileOverlay.addEventListener("click", function (e) {
|
||||
if (e.target === mobileOverlay) setOpen(false);
|
||||
});
|
||||
}
|
||||
if (mobileClose) {
|
||||
mobileClose.addEventListener("click", function () {
|
||||
setOpen(false);
|
||||
});
|
||||
}
|
||||
|
||||
if (historyClear) {
|
||||
historyClear.addEventListener("click", function () {
|
||||
if (aksrtData.isLoggedIn) {
|
||||
requestHistorySync("save", [], function (savedItems) {
|
||||
renderHistory(savedItems);
|
||||
});
|
||||
return;
|
||||
}
|
||||
writeHistory([]);
|
||||
renderHistory();
|
||||
});
|
||||
}
|
||||
|
||||
if (historyWrap) {
|
||||
historyWrap.addEventListener("click", function (e) {
|
||||
var item = e.target.closest("[data-history-keyword]");
|
||||
if (!item || !mobileInput) return;
|
||||
mobileInput.value = decodeURIComponent(item.getAttribute("data-history-keyword") || "");
|
||||
setSearchType(decodeURIComponent(item.getAttribute("data-history-type") || "post"));
|
||||
requestSuggestions();
|
||||
});
|
||||
}
|
||||
|
||||
mobileTypeButtons.forEach(function (button) {
|
||||
button.addEventListener("click", function () {
|
||||
setSearchType(button.getAttribute("data-search-type") || "post");
|
||||
});
|
||||
});
|
||||
|
||||
if (mobileInput) {
|
||||
mobileInput.addEventListener("input", requestSuggestions);
|
||||
}
|
||||
|
||||
if (mobileForm) {
|
||||
mobileForm.addEventListener("submit", function () {
|
||||
if (mobileInput) {
|
||||
pushHistory((mobileInput.value || "").trim(), getSearchType());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.querySelectorAll("[data-aksrt-search-form]").forEach(function (form) {
|
||||
if (form === mobileForm) return;
|
||||
form.addEventListener("submit", function () {
|
||||
if (!historyEnabled) return;
|
||||
var input = form.querySelector('input[name="s"]');
|
||||
var typeInput = form.querySelector('input[name="aksrt_search_type"]');
|
||||
var keyword = input ? (input.value || "").trim() : "";
|
||||
var type = typeInput ? (typeInput.value || "post") : "post";
|
||||
pushHistory(keyword, type);
|
||||
});
|
||||
});
|
||||
|
||||
setSearchType(getSearchType());
|
||||
if (historyEnabled && aksrtData.isLoggedIn) {
|
||||
requestHistorySync("get", null, function (items) {
|
||||
renderHistory(items);
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener("keydown", function (e) {
|
||||
if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") {
|
||||
e.preventDefault();
|
||||
setOpen(true);
|
||||
}
|
||||
if (e.key === "Escape" && panel.classList.contains("is-open")) {
|
||||
setOpen(false);
|
||||
btn.focus();
|
||||
}
|
||||
if (e.key === "Escape" && isMobileSearchMode() && mobileOverlay && !mobileOverlay.hasAttribute("hidden")) {
|
||||
setOpen(false);
|
||||
btn.focus();
|
||||
}
|
||||
});
|
||||
|
||||
window.__aksrtOpenSearchPanel = function () { setOpen(true); };
|
||||
window.__aksrtCloseSearchPanel = function () { setOpen(false); };
|
||||
}
|
||||
|
||||
window.AksrtFrontend.register("aksrt-search-panel", function () { initSearchPanel(); });
|
||||
})();
|
||||
@@ -0,0 +1,295 @@
|
||||
/**
|
||||
* AKSRT Hero & Swiper Initialization
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
window.AksrtSwipers = { new: [], scroll: [], tab: [] };
|
||||
|
||||
function initHeroSlider() {
|
||||
if (typeof Swiper === "undefined") return;
|
||||
|
||||
// ===== Type A: .swiper-scroll =====
|
||||
document.querySelectorAll(".swiper-scroll:not(.swiper-initialized)").forEach(function (el, index) {
|
||||
var c_w = el.offsetWidth;
|
||||
var firstSlide = el.querySelector(".swiper-wrapper > *");
|
||||
var i_w = firstSlide ? firstSlide.offsetWidth : 200;
|
||||
var slidesPerGroup = Math.max(1, Math.floor(c_w / i_w));
|
||||
|
||||
var option = {
|
||||
slidesPerView: "auto",
|
||||
freeMode: true,
|
||||
freeModeSticky: true,
|
||||
mousewheel: { forceToAxis: true },
|
||||
slidesPerGroup: slidesPerGroup,
|
||||
autoplay: el.dataset.autoplay ? {
|
||||
delay: parseInt(el.dataset.interval || "4000", 10),
|
||||
disableOnInteraction: false,
|
||||
} : false,
|
||||
loop: !!el.dataset.loop,
|
||||
navigation: {
|
||||
nextEl: el.querySelector(".swiper-button-next"),
|
||||
prevEl: el.querySelector(".swiper-button-prev"),
|
||||
},
|
||||
};
|
||||
|
||||
el.classList.add("swiper-scroll-eq-" + index);
|
||||
el.setAttribute("swiper-scroll-index", String(index));
|
||||
window.AksrtSwipers.scroll[index] = new Swiper(el, option);
|
||||
});
|
||||
|
||||
// ===== Type B: .swiper-tab =====
|
||||
document.querySelectorAll(".swiper-tab:not(.swiper-initialized)").forEach(function (el, index) {
|
||||
var speed = parseInt(el.dataset.speed || "0", 10) || Math.floor((el.offsetWidth + 1200) / 170) * 50;
|
||||
speed = Math.max(300, speed);
|
||||
|
||||
var initialSlide = parseInt(el.getAttribute("active-index") || "0", 10);
|
||||
|
||||
var option = {
|
||||
loop: false,
|
||||
initialSlide: initialSlide,
|
||||
autoHeight: true,
|
||||
spaceBetween: 20,
|
||||
autoplay: false,
|
||||
speed: speed,
|
||||
pagination: {
|
||||
el: el.querySelector(".swiper-pagination"),
|
||||
clickable: true,
|
||||
},
|
||||
};
|
||||
|
||||
var tabId = el.getAttribute("swiper-tab");
|
||||
if (tabId) {
|
||||
var tabNav = document.querySelector('[swiper-tab-nav="' + tabId + '"]');
|
||||
if (tabNav && tabNav.swiper) {
|
||||
option.thumbs = {
|
||||
swiper: tabNav.swiper,
|
||||
autoScrollOffset: 2,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
el.classList.add("swiper-tab-eq-" + index);
|
||||
el.setAttribute("swiper-tab-index", String(index));
|
||||
window.AksrtSwipers.tab[index] = new Swiper(el, option);
|
||||
});
|
||||
|
||||
// ===== Type C: .new-swiper =====
|
||||
document.querySelectorAll(".new-swiper:not(.swiper-initialized)").forEach(function (el, index) {
|
||||
var delay = parseInt(el.dataset.interval || "6000", 10);
|
||||
var autoplay = el.dataset.autoplay !== undefined ? {
|
||||
delay: delay,
|
||||
disableOnInteraction: false,
|
||||
} : false;
|
||||
|
||||
var speed = parseInt(el.dataset.speed || "0", 10) || Math.floor((el.offsetWidth + 1000) / 22) * 10;
|
||||
speed = Math.max(400, speed);
|
||||
if (!autoplay) speed = Math.floor(speed / 1.6);
|
||||
|
||||
var loop = !!el.dataset.loop;
|
||||
var parallax = !!el.querySelector("[data-swiper-parallax],[data-swiper-parallax-scale]");
|
||||
var effect = el.dataset.effect || "slide";
|
||||
var direction = el.dataset.direction || "horizontal";
|
||||
var spaceBetween = parseInt(el.dataset.spaceBetween || "0", 10);
|
||||
var paginationType = el.dataset.paginationType || "bullets";
|
||||
var autoHeight = el.hasAttribute("auto-height");
|
||||
|
||||
el.classList.add("swiper-new-eq-" + index);
|
||||
el.setAttribute("swiper-new-index", String(index));
|
||||
|
||||
var swiperArgs = {
|
||||
loop: loop,
|
||||
autoHeight: autoHeight,
|
||||
direction: direction,
|
||||
spaceBetween: spaceBetween,
|
||||
parallax: parallax,
|
||||
effect: effect,
|
||||
lazy: { loadPrevNext: true },
|
||||
autoplay: autoplay,
|
||||
speed: speed,
|
||||
pagination: {
|
||||
el: el.querySelector(".swiper-pagination"),
|
||||
type: paginationType,
|
||||
clickable: true,
|
||||
},
|
||||
navigation: {
|
||||
nextEl: el.querySelector(".swiper-button-next"),
|
||||
prevEl: el.querySelector(".swiper-button-prev"),
|
||||
},
|
||||
keyboard: { enabled: true },
|
||||
a11y: { prevSlideMessage: "上一张", nextSlideMessage: "下一张" },
|
||||
on: {
|
||||
lazyImageReady: function (slideEl, imageEl) {
|
||||
if (imageEl) imageEl.classList.add("lazyloaded");
|
||||
},
|
||||
slideChange: function () {
|
||||
el.querySelectorAll(".aksrt-dplayer, video").forEach(function (media) {
|
||||
if (media.pause) media.pause();
|
||||
var dp = media.closest("[data-dplayer]");
|
||||
if (dp && dp._dplayer) dp._dplayer.pause();
|
||||
});
|
||||
},
|
||||
init: function () {
|
||||
if (loop) {
|
||||
el.querySelectorAll(".swiper-slide-duplicate img").forEach(function (img) {
|
||||
img.classList.add("no-imgbox");
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
if (paginationType === "thumbnail") {
|
||||
swiperArgs.pagination.type = "bullets";
|
||||
swiperArgs.pagination.bulletClass = "pagination-thumbnail-item";
|
||||
swiperArgs.pagination.bulletActiveClass = "pagination-thumbnail-item-active";
|
||||
swiperArgs.pagination.renderBullet = function (idx, className) {
|
||||
var slide = this.slides[idx];
|
||||
if (!slide) return "";
|
||||
var img = slide.querySelector("img");
|
||||
var src = img ? (img.dataset.src || img.src) : "";
|
||||
if (src) {
|
||||
return '<div class="' + className + '"><img class="aksrt-tilt-thumb" src="' + src + '"></div>';
|
||||
}
|
||||
return "";
|
||||
};
|
||||
}
|
||||
|
||||
var swiperInstance = new Swiper(el, swiperArgs);
|
||||
window.AksrtSwipers.new[index] = swiperInstance;
|
||||
|
||||
if (el.classList.contains("banner-module__swiper")) {
|
||||
var prevBtn = el.querySelector(".swiper-button-prev");
|
||||
var nextBtn = el.querySelector(".swiper-button-next");
|
||||
if (prevBtn) {
|
||||
prevBtn.addEventListener("click", function (e) {
|
||||
e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation();
|
||||
if (swiperInstance && !swiperInstance.destroyed) swiperInstance.slidePrev();
|
||||
}, true);
|
||||
}
|
||||
if (nextBtn) {
|
||||
nextBtn.addEventListener("click", function (e) {
|
||||
e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation();
|
||||
if (swiperInstance && !swiperInstance.destroyed) swiperInstance.slideNext();
|
||||
}, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// ===== Compat: data-swiper-config JSON =====
|
||||
document.querySelectorAll("[data-swiper-config]:not(.swiper-initialized):not(.new-swiper):not(.swiper-scroll):not(.swiper-tab)").forEach(function (el) {
|
||||
var config = {};
|
||||
try { config = JSON.parse(el.dataset.swiperConfig || "{}"); } catch (e) {}
|
||||
|
||||
var paginationEl = el.querySelector(".swiper-pagination, .header-components__pagination");
|
||||
var prevBtn = el.querySelector(".swiper-button-prev");
|
||||
var nextBtn = el.querySelector(".swiper-button-next");
|
||||
|
||||
var defaults = {
|
||||
effect: "fade",
|
||||
fadeEffect: { crossFade: true },
|
||||
loop: true,
|
||||
speed: 600,
|
||||
autoplay: { delay: 5000, disableOnInteraction: false },
|
||||
pagination: paginationEl ? { el: paginationEl, type: "progressbar" } : false,
|
||||
navigation: (prevBtn && nextBtn) ? { prevEl: prevBtn, nextEl: nextBtn } : false,
|
||||
keyboard: { enabled: true },
|
||||
a11y: { prevSlideMessage: "上一张", nextSlideMessage: "下一张" },
|
||||
};
|
||||
|
||||
var finalConfig = Object.assign({}, defaults, config);
|
||||
if (config.pagination && typeof config.pagination === "object") {
|
||||
if (!config.pagination.el && paginationEl) config.pagination.el = paginationEl;
|
||||
finalConfig.pagination = Object.assign({}, defaults.pagination || {}, config.pagination);
|
||||
} else if (config.pagination === false) {
|
||||
finalConfig.pagination = false;
|
||||
}
|
||||
if (config.navigation === true && prevBtn && nextBtn) {
|
||||
finalConfig.navigation = { prevEl: prevBtn, nextEl: nextBtn };
|
||||
}
|
||||
|
||||
new Swiper(el, finalConfig);
|
||||
});
|
||||
|
||||
// Clickable slides
|
||||
document.querySelectorAll(".swiper-slide[data-link]").forEach(function (slide) {
|
||||
var link = slide.dataset.link;
|
||||
if (link && link !== "#") {
|
||||
slide.style.cursor = "pointer";
|
||||
slide.addEventListener("click", function (e) {
|
||||
if (e.target.closest(".header-components-search, .header-components-card, .hero__btn, .swiper-button-prev, .swiper-button-next, .swiper-pagination, .hero-search, a, button, input")) return;
|
||||
window.location.href = link;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Legacy hero__slides fallback
|
||||
document.querySelectorAll(".hero__slides:not(.swiper-wrapper)").forEach(function (slider) {
|
||||
var slides = slider.querySelectorAll(".hero__slide");
|
||||
var dots = slider.querySelectorAll(".hero__dot");
|
||||
var prevBtn = slider.closest("section")?.querySelector(".hero__btn--prev");
|
||||
var nextBtn = slider.closest("section")?.querySelector(".hero__btn--next");
|
||||
if (!slides.length || slides.length <= 1) return;
|
||||
|
||||
var autoplayInterval = parseInt(slider.dataset.autoplay || "5000", 10) || 5000;
|
||||
var pauseOnHover = slider.dataset.pauseOnHover === "true";
|
||||
var current = 0;
|
||||
var timer = null;
|
||||
var paused = false;
|
||||
|
||||
function show(index) {
|
||||
index = ((index % slides.length) + slides.length) % slides.length;
|
||||
slides[current].classList.remove("active");
|
||||
if (dots[current]) dots[current].setAttribute("aria-selected", "false");
|
||||
current = index;
|
||||
slides[current].classList.add("active");
|
||||
if (dots[current]) dots[current].setAttribute("aria-selected", "true");
|
||||
}
|
||||
function next() { show(current + 1); }
|
||||
function prev() { show(current - 1); }
|
||||
function startAutoplay() { stopAutoplay(); timer = setInterval(next, autoplayInterval); }
|
||||
function stopAutoplay() { if (timer) clearInterval(timer); timer = null; }
|
||||
function restart() { if (!paused) { stopAutoplay(); startAutoplay(); } }
|
||||
|
||||
show(0);
|
||||
if (nextBtn) nextBtn.addEventListener("click", function () { next(); restart(); });
|
||||
if (prevBtn) prevBtn.addEventListener("click", function () { prev(); restart(); });
|
||||
dots.forEach(function (dot, i) { dot.addEventListener("click", function () { show(i); restart(); }); });
|
||||
|
||||
slider.setAttribute("tabindex", "-1");
|
||||
slider.addEventListener("keydown", function (e) {
|
||||
if (e.key === "ArrowRight") { next(); restart(); }
|
||||
else if (e.key === "ArrowLeft") { prev(); restart(); }
|
||||
});
|
||||
|
||||
if (pauseOnHover) {
|
||||
slider.addEventListener("mouseenter", function () { paused = true; stopAutoplay(); });
|
||||
slider.addEventListener("mouseleave", function () { paused = false; startAutoplay(); });
|
||||
}
|
||||
|
||||
slides.forEach(function (slide) {
|
||||
var link = slide.dataset.link;
|
||||
if (link && link !== "#") {
|
||||
slide.style.cursor = "pointer";
|
||||
slide.addEventListener("click", function () { window.location.href = link; });
|
||||
}
|
||||
});
|
||||
|
||||
var touchStartX = 0;
|
||||
slider.addEventListener("touchstart", function (e) { touchStartX = e.changedTouches[0].screenX; stopAutoplay(); }, { passive: true });
|
||||
slider.addEventListener("touchend", function (e) {
|
||||
var diff = touchStartX - e.changedTouches[0].screenX;
|
||||
if (Math.abs(diff) > 50) { if (diff > 0) next(); else prev(); }
|
||||
startAutoplay();
|
||||
}, { passive: true });
|
||||
|
||||
startAutoplay();
|
||||
document.addEventListener("visibilitychange", function () {
|
||||
if (document.hidden) stopAutoplay();
|
||||
else if (!paused) startAutoplay();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
window.AksrtFrontend.register("aksrt-hero-slider", function () { initHeroSlider(); });
|
||||
})();
|
||||
@@ -0,0 +1,269 @@
|
||||
/**
|
||||
* AKSRT Theme Toggle — dark/light mode switching with transitions
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
var THEME_KEY = "aksrt-theme";
|
||||
var THEME_COOKIE_KEY = "theme_mode";
|
||||
|
||||
function normalizeStoredTheme(value) {
|
||||
if (value === "dark" || value === "dark-theme") return "dark";
|
||||
if (value === "light" || value === "white-theme") return "light";
|
||||
return null;
|
||||
}
|
||||
|
||||
function toCookieTheme(value) {
|
||||
return value === "dark" ? "dark-theme" : "white-theme";
|
||||
}
|
||||
|
||||
function getCookie(name) {
|
||||
var parts = document.cookie ? document.cookie.split("; ") : [];
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
var pair = parts[i].split("=");
|
||||
if (decodeURIComponent(pair[0]) === name) {
|
||||
return decodeURIComponent(pair.slice(1).join("="));
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
function setCookie(name, value, days) {
|
||||
var maxAge = days ? "; max-age=" + (days * 24 * 60 * 60) : "";
|
||||
var secure = window.location && window.location.protocol === "https:" ? "; Secure" : "";
|
||||
document.cookie = encodeURIComponent(name) + "=" + encodeURIComponent(value) + maxAge + "; path=/; SameSite=Lax" + secure;
|
||||
}
|
||||
|
||||
function getStoredTheme() {
|
||||
var localTheme = null;
|
||||
try {
|
||||
localTheme = normalizeStoredTheme(localStorage.getItem(THEME_KEY));
|
||||
} catch (e) {
|
||||
localTheme = null;
|
||||
}
|
||||
|
||||
var theme = normalizeStoredTheme(getCookie(THEME_COOKIE_KEY)) || localTheme;
|
||||
if (theme) {
|
||||
setStoredTheme(theme);
|
||||
}
|
||||
return theme;
|
||||
}
|
||||
|
||||
function setStoredTheme(value) {
|
||||
var theme = normalizeStoredTheme(value);
|
||||
if (!theme) return;
|
||||
try {
|
||||
localStorage.setItem(THEME_KEY, theme);
|
||||
} catch (e) {}
|
||||
setCookie(THEME_COOKIE_KEY, toCookieTheme(theme), 365);
|
||||
}
|
||||
|
||||
function getTimeAutoTheme() {
|
||||
var hour = (new Date()).getHours();
|
||||
return hour >= 20 || hour < 8 ? "dark" : "light";
|
||||
}
|
||||
|
||||
function resolveConfiguredTheme(mode) {
|
||||
var normalized = normalizeStoredTheme(mode);
|
||||
if (normalized) return normalized;
|
||||
if (mode === "time-auto" || mode === "auto") {
|
||||
return getTimeAutoTheme();
|
||||
}
|
||||
return "light";
|
||||
}
|
||||
|
||||
function syncBrandLogos(isDark) {
|
||||
document.querySelectorAll("[data-logo-light]").forEach(function (img) {
|
||||
var lightSrc = img.getAttribute("data-logo-light") || "";
|
||||
var darkSrc = img.getAttribute("data-logo-dark") || "";
|
||||
if (!lightSrc) return;
|
||||
img.setAttribute("src", isDark && darkSrc ? darkSrc : lightSrc);
|
||||
});
|
||||
}
|
||||
|
||||
function syncThemeColorMeta(isDark) {
|
||||
var meta = document.querySelector('meta[name="theme-color"]');
|
||||
if (!meta) {
|
||||
meta = document.createElement("meta");
|
||||
meta.setAttribute("name", "theme-color");
|
||||
document.head.appendChild(meta);
|
||||
}
|
||||
meta.setAttribute("content", isDark ? "#2F3135" : "#FDFCFE");
|
||||
}
|
||||
|
||||
function getThemeImageAttr(img, name) {
|
||||
return img.getAttribute(name) || img.getAttribute("data-" + name) || "";
|
||||
}
|
||||
|
||||
function setThemeImageSource(img, src) {
|
||||
if (!src || img.getAttribute("src") === src) return;
|
||||
img.setAttribute("src", src);
|
||||
}
|
||||
|
||||
function syncThemeImages(isDark) {
|
||||
document.querySelectorAll("img[switch-src], img[data-switch-src]").forEach(function (img) {
|
||||
var darkSrc = getThemeImageAttr(img, "switch-src");
|
||||
if (!img.dataset.aksrtThemeLightSrc) {
|
||||
img.dataset.aksrtThemeLightSrc = img.getAttribute("src") || "";
|
||||
}
|
||||
setThemeImageSource(img, isDark && darkSrc ? darkSrc : img.dataset.aksrtThemeLightSrc);
|
||||
});
|
||||
|
||||
document.querySelectorAll("img[white-src], img[dark-src], img[data-white-src], img[data-dark-src]").forEach(function (img) {
|
||||
var lightSrc = getThemeImageAttr(img, "white-src") || img.dataset.aksrtThemeLightSrc || img.getAttribute("src") || "";
|
||||
var darkSrc = getThemeImageAttr(img, "dark-src");
|
||||
if (!img.dataset.aksrtThemeLightSrc && lightSrc) {
|
||||
img.dataset.aksrtThemeLightSrc = lightSrc;
|
||||
}
|
||||
setThemeImageSource(img, isDark && darkSrc ? darkSrc : lightSrc);
|
||||
});
|
||||
}
|
||||
|
||||
function syncCodeHighlightTheme(isDark) {
|
||||
if (typeof window.AksrtPrecodeApplyTheme === "function") {
|
||||
window.AksrtPrecodeApplyTheme(isDark);
|
||||
return;
|
||||
}
|
||||
|
||||
var settings = (window.aksrtData && window.aksrtData.codeHighlight) || {};
|
||||
var theme = isDark ? (settings.darkTheme || "monokai") : (settings.lightTheme || "enlighter");
|
||||
document.querySelectorAll(".enlighter-default").forEach(function (el) {
|
||||
el.className = el.className.replace(/\benlighter-t-[\w-]+\b/g, "").replace(/\s+/g, " ").trim();
|
||||
el.classList.add("enlighter-t-" + theme);
|
||||
});
|
||||
}
|
||||
|
||||
function dispatchThemeChange(isDark) {
|
||||
try {
|
||||
document.dispatchEvent(new CustomEvent("aksrt:theme-change", {
|
||||
detail: {
|
||||
theme: isDark ? "dark" : "light",
|
||||
isDark: isDark
|
||||
}
|
||||
}));
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
function applyTheme(mode) {
|
||||
var isDark = mode === "dark";
|
||||
document.documentElement.classList.toggle("dark", isDark);
|
||||
document.documentElement.setAttribute("data-theme", isDark ? "dark" : "light");
|
||||
document.body.classList.toggle("theme-dark", isDark);
|
||||
document.body.classList.toggle("dark-theme", isDark);
|
||||
document.body.classList.toggle("white-theme", !isDark);
|
||||
document.body.setAttribute("data-theme", isDark ? "dark" : "light");
|
||||
syncBrandLogos(isDark);
|
||||
syncThemeColorMeta(isDark);
|
||||
syncThemeImages(isDark);
|
||||
syncCodeHighlightTheme(isDark);
|
||||
dispatchThemeChange(isDark);
|
||||
var btn = document.getElementById("theme-toggle");
|
||||
if (btn) {
|
||||
btn.setAttribute("aria-pressed", isDark ? "true" : "false");
|
||||
btn.classList.toggle("is-dark", isDark);
|
||||
var moon = btn.querySelector(".theme-icon-moon");
|
||||
var sun = btn.querySelector(".theme-icon-sun");
|
||||
if (moon && sun) {
|
||||
moon.style.display = isDark ? "none" : "";
|
||||
sun.style.display = isDark ? "" : "none";
|
||||
}
|
||||
}
|
||||
var floatBtn = document.getElementById("float-theme-toggle");
|
||||
if (floatBtn) {
|
||||
floatBtn.setAttribute("aria-pressed", isDark ? "true" : "false");
|
||||
var moonIcon = floatBtn.querySelector(".float-btn__icon-moon");
|
||||
var sunIcon = floatBtn.querySelector(".float-btn__icon-sun");
|
||||
if (moonIcon && sunIcon) {
|
||||
moonIcon.style.display = isDark ? "" : "none";
|
||||
sunIcon.style.display = isDark ? "none" : "";
|
||||
}
|
||||
}
|
||||
var ddBtn = document.getElementById("dropdown-theme-toggle");
|
||||
if (ddBtn) ddBtn.setAttribute("aria-pressed", isDark ? "true" : "false");
|
||||
}
|
||||
|
||||
function initTheme() {
|
||||
var stored = getStoredTheme();
|
||||
var configuredMode = (window.aksrtData && aksrtData.themeMode) || "light";
|
||||
if (stored === "dark" || stored === "light") {
|
||||
applyTheme(stored);
|
||||
} else {
|
||||
applyTheme(resolveConfiguredTheme(configuredMode));
|
||||
}
|
||||
|
||||
function prefersReducedMotion() {
|
||||
return window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
||||
}
|
||||
|
||||
function getThemeTransitionPoint(event) {
|
||||
if (event && typeof event.clientX === "number" && typeof event.clientY === "number") {
|
||||
return { x: event.clientX, y: event.clientY };
|
||||
}
|
||||
return { x: window.innerWidth / 2, y: window.innerHeight / 2 };
|
||||
}
|
||||
|
||||
function runThemeTransition(next, event) {
|
||||
if (!document.startViewTransition || prefersReducedMotion()) {
|
||||
applyTheme(next);
|
||||
return;
|
||||
}
|
||||
|
||||
var point = getThemeTransitionPoint(event);
|
||||
var endRadius = Math.hypot(
|
||||
Math.max(point.x, window.innerWidth - point.x),
|
||||
Math.max(point.y, window.innerHeight - point.y)
|
||||
);
|
||||
var clipPath = [
|
||||
"circle(0px at " + point.x + "px " + point.y + "px)",
|
||||
"circle(" + endRadius + "px at " + point.x + "px " + point.y + "px)"
|
||||
];
|
||||
var enteringDark = next === "dark";
|
||||
|
||||
try {
|
||||
var transition = document.startViewTransition(function () {
|
||||
applyTheme(next);
|
||||
});
|
||||
|
||||
transition.ready.then(function () {
|
||||
try {
|
||||
document.documentElement.animate(
|
||||
{ clipPath: enteringDark ? clipPath : clipPath.slice().reverse() },
|
||||
{
|
||||
duration: 500,
|
||||
easing: enteringDark ? "ease-in" : "ease-out",
|
||||
fill: "both",
|
||||
pseudoElement: enteringDark ? "::view-transition-new(root)" : "::view-transition-old(root)"
|
||||
}
|
||||
);
|
||||
} catch (e) {}
|
||||
}).catch(function () {});
|
||||
} catch (e) {
|
||||
applyTheme(next);
|
||||
}
|
||||
}
|
||||
|
||||
function bindToggle(id) {
|
||||
var el = document.getElementById(id);
|
||||
if (!el) return;
|
||||
el.addEventListener("click", function (event) {
|
||||
var next = document.body.classList.contains("theme-dark") ? "light" : "dark";
|
||||
setStoredTheme(next);
|
||||
runThemeTransition(next, event);
|
||||
});
|
||||
}
|
||||
|
||||
bindToggle("theme-toggle");
|
||||
bindToggle("theme-toggle-desktop");
|
||||
bindToggle("dropdown-theme-toggle");
|
||||
bindToggle("float-theme-toggle");
|
||||
bindToggle("theme-toggle-mobile");
|
||||
|
||||
aksrt.toggleTheme = function (event) {
|
||||
var next = document.body.classList.contains("theme-dark") ? "light" : "dark";
|
||||
setStoredTheme(next);
|
||||
runThemeTransition(next, event);
|
||||
};
|
||||
}
|
||||
|
||||
window.AksrtFrontend.register("aksrt-theme", function () { initTheme(); });
|
||||
})();
|
||||
@@ -0,0 +1,329 @@
|
||||
/**
|
||||
* AKSRT Credits Frontend
|
||||
*
|
||||
* 功能:
|
||||
* - 签到 panel:拉取 /signin/today,按钮触发 POST /signin
|
||||
* - 邀请 panel:拉取 /invite/me,复制邀请链接
|
||||
*
|
||||
* 仅在 page-profile 页面 + 启用积分时加载。
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var aksrt = window.aksrtData;
|
||||
if (!aksrt || !aksrt.siteUrl) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 协议修正:页面是 HTTPS 但 siteUrl 是 HTTP 时,强制使用 HTTPS(避免混合内容拦截)
|
||||
var siteUrl = aksrt.siteUrl;
|
||||
if (window.location.protocol === 'https:' && siteUrl.substring(0, 5) === 'http:') {
|
||||
siteUrl = 'https:' + siteUrl.substring(5);
|
||||
}
|
||||
|
||||
var REST = siteUrl.replace(/\/$/, '') + '/wp-json/aksrt/v1';
|
||||
var NONCE_HEADER = aksrt.restNonce ? { 'X-WP-Nonce': aksrt.restNonce } : (aksrt.nonce ? { 'X-WP-Nonce': aksrt.nonce } : {});
|
||||
|
||||
function api(path, options) {
|
||||
var merged = Object.assign({
|
||||
credentials: 'same-origin',
|
||||
headers: Object.assign({ 'Content-Type': 'application/json' }, NONCE_HEADER),
|
||||
}, options || {});
|
||||
return fetch(REST + path, merged).then(function (r) {
|
||||
// 401 时去掉 nonce 重试(页面缓存可能导致 nonce 过期,GET 请求可用 cookie 认证)
|
||||
if (r.status === 401 && (!options || !options.method || options.method === 'GET')) {
|
||||
var retry = Object.assign({}, merged, {
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
return fetch(REST + path, retry).then(function (r2) {
|
||||
return r2.json().catch(function () {
|
||||
return { message: '服务器返回了非 JSON 响应 (HTTP ' + r2.status + ')' };
|
||||
}).then(function (j) { return { ok: r2.ok, status: r2.status, json: j }; });
|
||||
});
|
||||
}
|
||||
return r.json().catch(function () {
|
||||
return { message: '服务器返回了非 JSON 响应 (HTTP ' + r.status + ')' };
|
||||
}).then(function (j) { return { ok: r.ok, status: r.status, json: j }; });
|
||||
});
|
||||
}
|
||||
|
||||
// ===== 签到 =====
|
||||
function initSignin() {
|
||||
var root = document.querySelector('[data-aksrt-signin]');
|
||||
if (!root) return;
|
||||
var status = root.querySelector('[data-signin-status]');
|
||||
var btn = root.querySelector('[data-signin-btn]');
|
||||
var tip = root.querySelector('[data-signin-tip]');
|
||||
if (!btn) return;
|
||||
|
||||
function setStatus(text) { if (status) status.textContent = text; }
|
||||
function setStatusHtml(html) { if (status) status.innerHTML = html; }
|
||||
function setTip(text) { if (tip) tip.textContent = text; }
|
||||
|
||||
function refresh() {
|
||||
api('/signin/today').then(function (r) {
|
||||
if (!r.ok) {
|
||||
setStatus((r.json && r.json.message) || '加载失败 (HTTP ' + r.status + ')');
|
||||
return;
|
||||
}
|
||||
var j = r.json;
|
||||
if (!j.enabled) {
|
||||
setStatus('签到功能未启用');
|
||||
btn.disabled = true;
|
||||
setTip('');
|
||||
return;
|
||||
}
|
||||
if (j.signed) {
|
||||
setStatusHtml('已签到 <strong>' + j.streak + '</strong> 天 +' + j.reward_today);
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = '已签到';
|
||||
setTip('');
|
||||
} else {
|
||||
setStatusHtml('连续 <strong>' + j.streak + '</strong> 天,+' + j.reward_if_signin);
|
||||
btn.disabled = false;
|
||||
setTip('');
|
||||
}
|
||||
}).catch(function (err) {
|
||||
if (window.console) console.error('[AKSRT Credits] /signin/today 请求失败:', err);
|
||||
setStatus('加载失败,请刷新重试');
|
||||
});
|
||||
}
|
||||
|
||||
function collectCaptcha() {
|
||||
var el = document.querySelector('[data-signin-captcha]');
|
||||
if (!el) return {};
|
||||
var out = {};
|
||||
var keys = [
|
||||
'captcha_verified', 'cf_turnstile_response',
|
||||
'tencent_ticket', 'tencent_randstr', 'tencent_sid',
|
||||
'geetest_lot_number', 'geetest_captcha_output', 'geetest_pass_token', 'geetest_gen_time',
|
||||
'aliyun_captcha_verify_param',
|
||||
];
|
||||
keys.forEach(function (k) {
|
||||
var inp = el.querySelector('input[name="' + k + '"]');
|
||||
if (inp && inp.value !== '') out[k] = inp.value;
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
function resetCaptcha() {
|
||||
try {
|
||||
var state = window.AKSRTCaptchaState;
|
||||
var scene = state && state.scenes && state.scenes.signin;
|
||||
if (scene && typeof scene.reset === 'function') scene.reset();
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
function triggerCaptcha(callback) {
|
||||
var state = window.AKSRTCaptchaState;
|
||||
var scene = state && state.scenes && state.scenes.signin;
|
||||
if (scene && typeof scene.verify === 'function') {
|
||||
scene.verify(callback);
|
||||
return;
|
||||
}
|
||||
callback();
|
||||
}
|
||||
|
||||
btn.addEventListener('click', function () {
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = '…';
|
||||
setTip('');
|
||||
|
||||
var captchaDone = false;
|
||||
var timeoutId = setTimeout(function () {
|
||||
if (!captchaDone) {
|
||||
captchaDone = true;
|
||||
doSignin();
|
||||
}
|
||||
}, 30000);
|
||||
|
||||
triggerCaptcha(function () {
|
||||
clearTimeout(timeoutId);
|
||||
if (captchaDone) return;
|
||||
captchaDone = true;
|
||||
doSignin();
|
||||
});
|
||||
|
||||
function doSignin() {
|
||||
api('/signin', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ captcha: collectCaptcha() })
|
||||
}).then(function (r) {
|
||||
if (!r.ok) {
|
||||
resetCaptcha();
|
||||
setTip((r.json && r.json.message) || '签到失败');
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = '签到';
|
||||
return;
|
||||
}
|
||||
setTip('签到成功,获得 ' + r.json.reward + ' 积分(连续 ' + r.json.streak + ' 天)');
|
||||
var balanceEls = document.querySelectorAll('[data-credits-value]');
|
||||
balanceEls.forEach(function (el) { el.textContent = r.json.balance.toLocaleString(); });
|
||||
refresh();
|
||||
}).catch(function () {
|
||||
resetCaptcha();
|
||||
setTip('网络错误,请重试');
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = '签到';
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
// ===== 邀请 =====
|
||||
function initInvite() {
|
||||
var root = document.querySelector('[data-aksrt-invite]');
|
||||
if (!root) return;
|
||||
var linkInput = root.querySelector('[data-invite-link]');
|
||||
var copyBtn = root.querySelector('[data-invite-copy]');
|
||||
var stats = root.querySelector('[data-invite-stats]');
|
||||
var codeEl = root.querySelector('[data-invite-code]');
|
||||
var listEl = root.querySelector('[data-invite-list]');
|
||||
var totalEl = root.querySelector('[data-invite-total]');
|
||||
|
||||
function escapeHtml(value) {
|
||||
return String(value == null ? '' : value)
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
function formatDate(value) {
|
||||
if (!value || value === '0000-00-00 00:00:00') return '';
|
||||
var date = new Date(String(value).replace(' ', 'T') + 'Z');
|
||||
if (isNaN(date.getTime())) return String(value).slice(0, 16);
|
||||
function pad(n) { return n < 10 ? '0' + n : String(n); }
|
||||
return date.getFullYear() + '-' + pad(date.getMonth() + 1) + '-' + pad(date.getDate()) + ' ' + pad(date.getHours()) + ':' + pad(date.getMinutes());
|
||||
}
|
||||
|
||||
function statusMeta(status) {
|
||||
if (status === 'rewarded') {
|
||||
return { label: '已奖励', text: '奖励已发放', className: 'is-rewarded' };
|
||||
}
|
||||
if (status === 'verified') {
|
||||
return { label: '已验证', text: '等待奖励发放', className: 'is-verified' };
|
||||
}
|
||||
return { label: '已注册', text: '等待完成验证', className: 'is-registered' };
|
||||
}
|
||||
|
||||
function setCopyText(text) {
|
||||
if (!copyBtn) return;
|
||||
var label = copyBtn.querySelector('span');
|
||||
if (label) label.textContent = text;
|
||||
else copyBtn.textContent = text;
|
||||
}
|
||||
|
||||
function renderInviteList(items, total) {
|
||||
if (!listEl) return;
|
||||
listEl.classList.remove('is-loading');
|
||||
if (totalEl) {
|
||||
if (total > items.length) totalEl.textContent = '最近 ' + items.length + ' 条 / 共 ' + total + ' 条';
|
||||
else totalEl.textContent = total ? '共 ' + total + ' 条' : '暂无记录';
|
||||
}
|
||||
if (!items.length) {
|
||||
listEl.innerHTML = '<div class="aksrt-invite-record-empty">分享链接后,好友注册记录会显示在这里。</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
listEl.innerHTML = items.map(function (item) {
|
||||
var name = item.invitee_name || (item.invitee_id ? '用户 #' + item.invitee_id : '受邀用户');
|
||||
var first = name ? name.charAt(0).toUpperCase() : '?';
|
||||
var meta = statusMeta(item.status);
|
||||
var createdAt = formatDate(item.created_at);
|
||||
var rewardedAt = formatDate(item.rewarded_at);
|
||||
var statusText = meta.text;
|
||||
if (item.status === 'rewarded' && rewardedAt) statusText = '奖励于 ' + rewardedAt;
|
||||
var avatar = item.invitee_avatar
|
||||
? '<img src="' + escapeHtml(item.invitee_avatar) + '" alt="">'
|
||||
: '<span>' + escapeHtml(first) + '</span>';
|
||||
|
||||
return '<div class="aksrt-invite-record ' + meta.className + '">' +
|
||||
'<div class="aksrt-invite-record__avatar">' + avatar + '</div>' +
|
||||
'<div class="aksrt-invite-record__main">' +
|
||||
'<strong>' + escapeHtml(name) + '</strong>' +
|
||||
'<span>' + (createdAt ? '注册于 ' + escapeHtml(createdAt) : '注册时间未知') + '</span>' +
|
||||
'</div>' +
|
||||
'<div class="aksrt-invite-record__status">' +
|
||||
'<span class="aksrt-invite-badge ' + meta.className + '">' + meta.label + '</span>' +
|
||||
'<small>' + escapeHtml(statusText) + '</small>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
}).join('');
|
||||
}
|
||||
|
||||
api('/invite/me').then(function (r) {
|
||||
if (!r.ok) {
|
||||
if (linkInput) linkInput.value = '';
|
||||
if (copyBtn) copyBtn.disabled = true;
|
||||
if (codeEl) codeEl.textContent = '--';
|
||||
if (stats) {
|
||||
stats.querySelectorAll('[data-stat]').forEach(function (el) {
|
||||
el.textContent = '—';
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
var j = r.json;
|
||||
if (linkInput) linkInput.value = j.invite_url || '';
|
||||
if (codeEl) codeEl.textContent = j.code || '--';
|
||||
if (stats && j.stats) {
|
||||
stats.querySelectorAll('[data-stat]').forEach(function (el) {
|
||||
var k = el.getAttribute('data-stat');
|
||||
el.textContent = (j.stats[k] || 0).toString();
|
||||
});
|
||||
}
|
||||
}).catch(function () {
|
||||
if (copyBtn) copyBtn.disabled = true;
|
||||
if (codeEl) codeEl.textContent = '--';
|
||||
});
|
||||
|
||||
if (listEl) {
|
||||
api('/invite/list?per_page=8').then(function (r) {
|
||||
if (!r.ok) {
|
||||
listEl.classList.remove('is-loading');
|
||||
listEl.innerHTML = '<div class="aksrt-invite-record-empty">邀请记录加载失败,请稍后刷新。</div>';
|
||||
if (totalEl) totalEl.textContent = '加载失败';
|
||||
return;
|
||||
}
|
||||
var j = r.json || {};
|
||||
renderInviteList(j.items || [], Number(j.total || 0));
|
||||
}).catch(function () {
|
||||
listEl.classList.remove('is-loading');
|
||||
listEl.innerHTML = '<div class="aksrt-invite-record-empty">邀请记录加载失败,请稍后刷新。</div>';
|
||||
if (totalEl) totalEl.textContent = '加载失败';
|
||||
});
|
||||
}
|
||||
|
||||
if (!copyBtn) return;
|
||||
var copying = false;
|
||||
copyBtn.addEventListener('click', function () {
|
||||
if (copying || !linkInput || !linkInput.value) return;
|
||||
copying = true;
|
||||
if (navigator.clipboard) {
|
||||
navigator.clipboard.writeText(linkInput.value).then(function () {
|
||||
setCopyText('已复制');
|
||||
setTimeout(function () { setCopyText('复制链接'); copying = false; }, 2000);
|
||||
}).catch(function () { copying = false; });
|
||||
} else {
|
||||
linkInput.select();
|
||||
document.execCommand('copy');
|
||||
setCopyText('已复制');
|
||||
setTimeout(function () { setCopyText('复制链接'); copying = false; }, 2000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
initSignin();
|
||||
initInvite();
|
||||
});
|
||||
} else {
|
||||
initSignin();
|
||||
initInvite();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* AKSRT Docs Navigation
|
||||
*
|
||||
* Enhanced document sidebar navigation:
|
||||
* - Collapsible section toggles
|
||||
* - Keyboard navigation
|
||||
* - Current section auto-expand
|
||||
* - Sidebar search with live filtering
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var DocsNav = {
|
||||
sidebar: null,
|
||||
searchInput: null,
|
||||
items: [],
|
||||
|
||||
init: function () {
|
||||
this.sidebar = document.querySelector('.aksrt-doc-sidebar');
|
||||
if (!this.sidebar) return;
|
||||
|
||||
this.items = Array.from(this.sidebar.querySelectorAll('.aksrt-doc-sidebar__item'));
|
||||
this.searchInput = this.sidebar.querySelector('.aksrt-doc-sidebar__search-input');
|
||||
|
||||
this.initToggle();
|
||||
this.initSearch();
|
||||
this.initKeyboard();
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggle collapsible sections
|
||||
*/
|
||||
initToggle: function () {
|
||||
var self = this;
|
||||
this.sidebar.addEventListener('click', function (e) {
|
||||
var toggle = e.target.closest('.aksrt-doc-sidebar__toggle');
|
||||
if (!toggle) return;
|
||||
|
||||
e.preventDefault();
|
||||
var link = toggle.closest('.aksrt-doc-sidebar__link');
|
||||
if (!link) return;
|
||||
|
||||
var li = link.closest('.aksrt-doc-sidebar__item');
|
||||
if (!li) return;
|
||||
|
||||
var sub = li.querySelector('.aksrt-doc-sidebar__sub, ul');
|
||||
if (!sub) return;
|
||||
|
||||
var isOpen = li.classList.contains('is-open');
|
||||
li.classList.toggle('is-open');
|
||||
|
||||
// Update icon
|
||||
toggle.classList.remove('fa-chevron-down', 'fa-chevron-right');
|
||||
toggle.classList.add(isOpen ? 'fa-chevron-right' : 'fa-chevron-down');
|
||||
|
||||
// Toggle sub-visibility
|
||||
sub.style.display = isOpen ? 'none' : '';
|
||||
});
|
||||
|
||||
// Auto-expand current path
|
||||
var currentItems = this.sidebar.querySelectorAll('.aksrt-doc-sidebar__item.is-current, .aksrt-doc-sidebar__item.is-ancestor');
|
||||
currentItems.forEach(function (item) {
|
||||
item.classList.add('is-open');
|
||||
var toggle = item.querySelector('.aksrt-doc-sidebar__toggle');
|
||||
if (toggle) {
|
||||
toggle.classList.remove('fa-chevron-right');
|
||||
toggle.classList.add('fa-chevron-down');
|
||||
}
|
||||
var sub = item.querySelector('.aksrt-doc-sidebar__sub, ul');
|
||||
if (sub) sub.style.display = '';
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Live search filtering
|
||||
*/
|
||||
initSearch: function () {
|
||||
if (!this.searchInput) return;
|
||||
|
||||
var debounceTimer = null;
|
||||
var self = this;
|
||||
this.searchInput.addEventListener('input', function () {
|
||||
clearTimeout(debounceTimer);
|
||||
debounceTimer = setTimeout(function () {
|
||||
self.filterItems(self.searchInput.value.trim().toLowerCase());
|
||||
}, 150);
|
||||
});
|
||||
},
|
||||
|
||||
filterItems: function (query) {
|
||||
this.items.forEach(function (item) {
|
||||
var link = item.querySelector('.aksrt-doc-sidebar__link');
|
||||
var text = link ? link.textContent.toLowerCase() : '';
|
||||
if (query === '' || text.indexOf(query) >= 0) {
|
||||
item.style.display = '';
|
||||
} else {
|
||||
item.style.display = 'none';
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Keyboard navigation (arrow keys)
|
||||
*/
|
||||
initKeyboard: function () {
|
||||
this.sidebar.addEventListener('keydown', function (e) {
|
||||
if (!['ArrowUp', 'ArrowDown', 'Enter', ' '].includes(e.key)) return;
|
||||
|
||||
var focused = document.activeElement;
|
||||
if (!focused || !focused.closest('.aksrt-doc-sidebar')) return;
|
||||
|
||||
var links = Array.from(document.querySelectorAll('.aksrt-doc-sidebar__link'));
|
||||
var idx = links.indexOf(focused);
|
||||
|
||||
if (e.key === 'ArrowDown') {
|
||||
e.preventDefault();
|
||||
if (idx < links.length - 1) links[idx + 1].focus();
|
||||
} else if (e.key === 'ArrowUp') {
|
||||
e.preventDefault();
|
||||
if (idx > 0) links[idx - 1].focus();
|
||||
} else if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
focused.click();
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', function () { DocsNav.init(); });
|
||||
} else {
|
||||
DocsNav.init();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* AKSRT Download Status
|
||||
*
|
||||
* Handles download center page interactions:
|
||||
* - Resource type filter animation
|
||||
* - Price badge hover effects
|
||||
* - Status bar refresh on download completion
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var DownloadStatus = {
|
||||
init: function () {
|
||||
this.initFilterHighlight();
|
||||
this.initCardHover();
|
||||
},
|
||||
|
||||
/**
|
||||
* Animate filter button active state
|
||||
*/
|
||||
initFilterHighlight: function () {
|
||||
var filters = document.querySelectorAll('.aksrt-download-hero__filter');
|
||||
if (filters.length === 0) return;
|
||||
|
||||
filters.forEach(function (btn) {
|
||||
btn.addEventListener('mouseenter', function () {
|
||||
btn.style.transform = 'translateY(-1px)';
|
||||
});
|
||||
btn.addEventListener('mouseleave', function () {
|
||||
btn.style.transform = '';
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Card hover depth effect
|
||||
*/
|
||||
initCardHover: function () {
|
||||
var cards = document.querySelectorAll('.aksrt-download-card');
|
||||
if (cards.length === 0) return;
|
||||
|
||||
cards.forEach(function (card) {
|
||||
card.addEventListener('mouseenter', function () {
|
||||
card.style.transform = 'translateY(-2px)';
|
||||
});
|
||||
card.addEventListener('mouseleave', function () {
|
||||
card.style.transform = '';
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', function () { DownloadStatus.init(); });
|
||||
} else {
|
||||
DownloadStatus.init();
|
||||
}
|
||||
})();
|
||||
Vendored
+214
@@ -0,0 +1,214 @@
|
||||
/**
|
||||
* AKSRT Effects — count-up / countdown / marquee / 3D tilt / FPS detection
|
||||
*
|
||||
* 全部渐进增强,尊重 prefers-reduced-motion。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var reducedMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||
|
||||
/* ============================================================
|
||||
* 1. 数字递增 (count-up) — IntersectionObserver 触发
|
||||
* 用法:<span data-aksrt-countup data-target="1234" data-duration="2000">0</span>
|
||||
* ============================================================ */
|
||||
function initCountUp() {
|
||||
if (reducedMotion) return;
|
||||
if (!('IntersectionObserver' in window)) return;
|
||||
|
||||
var els = document.querySelectorAll('[data-aksrt-countup]');
|
||||
if (!els.length) return;
|
||||
|
||||
var observer = new IntersectionObserver(function (entries) {
|
||||
entries.forEach(function (entry) {
|
||||
if (!entry.isIntersecting) return;
|
||||
var el = entry.target;
|
||||
observer.unobserve(el);
|
||||
|
||||
var target = parseFloat(el.dataset.target || '0');
|
||||
var duration = parseInt(el.dataset.duration || '2000', 10);
|
||||
var decimals = (el.dataset.decimals || '0|').split('|');
|
||||
var prefix = decimals[1] || '';
|
||||
var dec = parseInt(decimals[0], 10) || 0;
|
||||
var start = 0;
|
||||
var startTime = null;
|
||||
|
||||
function step(timestamp) {
|
||||
if (!startTime) startTime = timestamp;
|
||||
var progress = Math.min((timestamp - startTime) / duration, 1);
|
||||
// ease-out cubic
|
||||
var eased = 1 - Math.pow(1 - progress, 3);
|
||||
var current = start + (target - start) * eased;
|
||||
el.textContent = prefix + current.toFixed(dec).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||
if (progress < 1) {
|
||||
requestAnimationFrame(step);
|
||||
} else {
|
||||
el.textContent = prefix + target.toFixed(dec).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||
}
|
||||
}
|
||||
|
||||
requestAnimationFrame(step);
|
||||
});
|
||||
}, { threshold: 0.3 });
|
||||
|
||||
els.forEach(function (el) { observer.observe(el); });
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 2. 倒计时组件
|
||||
* 用法:<span data-aksrt-countdown data-end="2026-12-31T23:59:59">--:--:--</span>
|
||||
* ============================================================ */
|
||||
function initCountdown() {
|
||||
var els = document.querySelectorAll('[data-aksrt-countdown]');
|
||||
if (!els.length) return;
|
||||
|
||||
function pad(n) { return n < 10 ? '0' + n : '' + n; }
|
||||
|
||||
function update() {
|
||||
var now = Date.now();
|
||||
els.forEach(function (el) {
|
||||
var end = new Date(el.dataset.end).getTime();
|
||||
var diff = end - now;
|
||||
if (diff <= 0) {
|
||||
el.textContent = el.dataset.expired || '已结束';
|
||||
return;
|
||||
}
|
||||
var d = Math.floor(diff / 86400000);
|
||||
var h = Math.floor((diff % 86400000) / 3600000);
|
||||
var m = Math.floor((diff % 3600000) / 60000);
|
||||
var s = Math.floor((diff % 60000) / 1000);
|
||||
var format = el.dataset.format || 'dhms';
|
||||
if (format === 'dhms') {
|
||||
el.textContent = (d > 0 ? d + '天 ' : '') + pad(h) + ':' + pad(m) + ':' + pad(s);
|
||||
} else if (format === 'hms') {
|
||||
el.textContent = pad(h + d * 24) + ':' + pad(m) + ':' + pad(s);
|
||||
} else {
|
||||
el.textContent = (d > 0 ? d + '天 ' : '') + pad(h) + '时' + pad(m) + '分' + pad(s) + '秒';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
update();
|
||||
setInterval(update, 1000);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 3. 合作伙伴无缝滚动 (marquee)
|
||||
* 用法:<div class="aksrt-marquee" data-speed="1">...内容...</div>
|
||||
* ============================================================ */
|
||||
function initMarquee() {
|
||||
document.querySelectorAll('.aksrt-marquee').forEach(function (el) {
|
||||
if (el.dataset.marqueeBound) return;
|
||||
el.dataset.marqueeBound = '1';
|
||||
|
||||
var speed = parseFloat(el.dataset.speed || '1');
|
||||
var inner = el.querySelector('.aksrt-marquee__inner') || el.children[0];
|
||||
if (!inner) return;
|
||||
|
||||
// 克隆内容实现无缝
|
||||
var clone = inner.cloneNode(true);
|
||||
el.appendChild(clone);
|
||||
|
||||
var pos = 0;
|
||||
var width = inner.scrollWidth;
|
||||
|
||||
function animate() {
|
||||
pos -= speed;
|
||||
if (Math.abs(pos) >= width) pos = 0;
|
||||
inner.style.transform = 'translateX(' + pos + 'px)';
|
||||
clone.style.transform = 'translateX(' + (pos + width) + 'px)';
|
||||
if (!reducedMotion) requestAnimationFrame(animate);
|
||||
}
|
||||
|
||||
if (!reducedMotion) {
|
||||
requestAnimationFrame(animate);
|
||||
}
|
||||
|
||||
// 暂停/恢复
|
||||
el.addEventListener('mouseenter', function () { el.dataset.paused = '1'; });
|
||||
el.addEventListener('mouseleave', function () { delete el.dataset.paused; });
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 4. 3D 悬停倾斜 (vanilla tilt)
|
||||
* 用法:<div data-aksrt-tilt data-tilt-max="15">...</div>
|
||||
* ============================================================ */
|
||||
function initTilt() {
|
||||
if (reducedMotion) return;
|
||||
|
||||
document.querySelectorAll('[data-aksrt-tilt]').forEach(function (el) {
|
||||
if (el.dataset.tiltBound) return;
|
||||
el.dataset.tiltBound = '1';
|
||||
|
||||
var maxDeg = parseFloat(el.dataset.tiltMax || '10');
|
||||
var perspective = parseFloat(el.dataset.tiltPerspective || '800');
|
||||
var scale = parseFloat(el.dataset.tiltScale || '1.03');
|
||||
var glare = el.dataset.tiltGlare === '1';
|
||||
var glareEl = null;
|
||||
|
||||
if (glare) {
|
||||
glareEl = document.createElement('div');
|
||||
glareEl.style.cssText = 'position:absolute;inset:0;border-radius:inherit;pointer-events:none;background:linear-gradient(135deg,rgba(255,255,255,0) 0%,rgba(255,255,255,0.25) 100%);opacity:0;transition:opacity 0.2s;';
|
||||
el.style.position = el.style.position || 'relative';
|
||||
el.style.overflow = 'hidden';
|
||||
el.appendChild(glareEl);
|
||||
}
|
||||
|
||||
el.addEventListener('mousemove', function (e) {
|
||||
var rect = el.getBoundingClientRect();
|
||||
var x = (e.clientX - rect.left) / rect.width;
|
||||
var y = (e.clientY - rect.top) / rect.height;
|
||||
var rotateX = (0.5 - y) * maxDeg;
|
||||
var rotateY = (x - 0.5) * maxDeg;
|
||||
el.style.transform = 'perspective(' + perspective + 'px) rotateX(' + rotateX + 'deg) rotateY(' + rotateY + 'deg) scale3d(' + scale + ',' + scale + ',' + scale + ')';
|
||||
if (glareEl) glareEl.style.opacity = '1';
|
||||
});
|
||||
|
||||
el.addEventListener('mouseleave', function () {
|
||||
el.style.transform = 'perspective(' + perspective + 'px) rotateX(0deg) rotateY(0deg) scale3d(1,1,1)';
|
||||
if (glareEl) glareEl.style.opacity = '0';
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 5. FPS 检测 + 低端设备降级
|
||||
* ============================================================ */
|
||||
function initFpsDetection() {
|
||||
if (!('requestAnimationFrame' in window)) return;
|
||||
|
||||
var frames = 0;
|
||||
var startTime = performance.now();
|
||||
|
||||
function countFrames() {
|
||||
frames++;
|
||||
var elapsed = performance.now() - startTime;
|
||||
if (elapsed >= 1000) {
|
||||
var fps = Math.round(frames * 1000 / elapsed);
|
||||
if (fps < 24) {
|
||||
document.body.classList.add('fps-accelerat');
|
||||
}
|
||||
return; // 只检测一次
|
||||
}
|
||||
requestAnimationFrame(countFrames);
|
||||
}
|
||||
|
||||
requestAnimationFrame(countFrames);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 初始化入口
|
||||
* ============================================================ */
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
initCountUp();
|
||||
initCountdown();
|
||||
initMarquee();
|
||||
initTilt();
|
||||
initFpsDetection();
|
||||
});
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,588 @@
|
||||
/**
|
||||
* AKSRT Enhancements — 全局 UI 增强
|
||||
*
|
||||
* 包含:Toast 通知、图片灯箱、滚动方向感知
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/* ============================================================
|
||||
* 1. Toast 通知系统
|
||||
* ============================================================ */
|
||||
var toastContainer = null;
|
||||
|
||||
function ensureToastContainer() {
|
||||
if (!toastContainer || !document.body.contains(toastContainer)) {
|
||||
toastContainer = document.createElement('div');
|
||||
toastContainer.className = 'aksrt-toast-container';
|
||||
document.body.appendChild(toastContainer);
|
||||
}
|
||||
return toastContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示 Toast 通知
|
||||
*
|
||||
* @param {string} message 消息文本
|
||||
* @param {string} type 类型: success, info, warning, danger/error, loading
|
||||
* @param {number} duration 显示时长(ms),0 表示不自动关闭
|
||||
* @returns {Object} { dismiss: Function, update: Function }
|
||||
*/
|
||||
function showToast(message, type, duration) {
|
||||
type = type || 'success';
|
||||
if (type === 'error') type = 'danger';
|
||||
duration = duration !== undefined ? duration : 3500;
|
||||
if (duration > 0 && duration < 100) duration = duration * 1000;
|
||||
|
||||
var container = ensureToastContainer();
|
||||
|
||||
var icons = {
|
||||
success: 'fas fa-check-circle',
|
||||
info: 'fas fa-bell',
|
||||
warning: 'fas fa-exclamation-circle',
|
||||
danger: 'fas fa-times-circle',
|
||||
loading: 'fas fa-spinner',
|
||||
};
|
||||
|
||||
var el = document.createElement('div');
|
||||
el.className = 'aksrt-toast aksrt-toast--' + type;
|
||||
el.innerHTML =
|
||||
'<span class="aksrt-toast__icon"><i class="' + (icons[type] || icons.info) + '"></i></span>' +
|
||||
'<span class="aksrt-toast__text">' + message + '</span>';
|
||||
|
||||
container.appendChild(el);
|
||||
|
||||
var timer = null;
|
||||
|
||||
function dismiss() {
|
||||
if (timer) clearTimeout(timer);
|
||||
el.classList.add('is-dismissing');
|
||||
setTimeout(function () {
|
||||
if (el.parentNode) el.remove();
|
||||
}, 300);
|
||||
}
|
||||
|
||||
function update(newMessage, newType) {
|
||||
if (newType) {
|
||||
el.className = 'aksrt-toast aksrt-toast--' + newType;
|
||||
var iconEl = el.querySelector('.aksrt-toast__icon i');
|
||||
if (iconEl) iconEl.className = icons[newType] || icons.info;
|
||||
}
|
||||
var textEl = el.querySelector('.aksrt-toast__text');
|
||||
if (textEl) textEl.textContent = newMessage;
|
||||
|
||||
if (newType !== 'loading' && duration > 0) {
|
||||
if (timer) clearTimeout(timer);
|
||||
timer = setTimeout(dismiss, duration);
|
||||
}
|
||||
}
|
||||
|
||||
el.addEventListener('click', dismiss);
|
||||
|
||||
if (type !== 'loading' && duration > 0) {
|
||||
timer = setTimeout(dismiss, duration);
|
||||
}
|
||||
|
||||
return { dismiss: dismiss, update: update };
|
||||
}
|
||||
|
||||
// 暴露到全局
|
||||
window.AksrtToast = showToast;
|
||||
|
||||
/* ============================================================
|
||||
* 2. 图片灯箱 — zoom / thumbnails / slideshow / fullscreen /
|
||||
* mousewheel / origin animation / smart download
|
||||
* ============================================================ */
|
||||
var lightboxEl = null;
|
||||
var lightboxImg = null;
|
||||
var lightboxCaption = null;
|
||||
var lightboxCounter = null;
|
||||
var lightboxThumbsWrap = null;
|
||||
var currentGallery = [];
|
||||
var currentIndex = 0;
|
||||
var currentZoom = 1;
|
||||
var autoplayTimer = null;
|
||||
var isAutoplay = false;
|
||||
var EXCLUDE_SEL = '.no-imgbox,.no-lightbox,.avatar,.img-icon,.avatar-badge,.smilie-icon,.aksrt-avatar,.aksrt-lazy-skeleton';
|
||||
var TRIGGER_SEL = '.entry-content img, .wp-posts-content img, .aksrt-lightbox-trigger img, [data-aksrt-lightbox] img, .imgbox-container img, .comment-content .box-img img, a[data-imgbox] img';
|
||||
var CONTAINER_SEL = '.entry-content, .wp-posts-content, .aksrt-lightbox-trigger, [data-aksrt-lightbox], .imgbox-container, .comment-content';
|
||||
var MAX_ZOOM_DESKTOP = 2;
|
||||
var MAX_ZOOM_MOBILE = 3;
|
||||
|
||||
function resolveFullUrl(img) {
|
||||
var full = img.getAttribute('data-full-url') || img.getAttribute('data-src') || '';
|
||||
if (full) return full;
|
||||
var src = img.src || '';
|
||||
// thumbnail → original: strip -NNNxNNN suffix
|
||||
return src.replace(/-\d+x\d+(\.[a-z]+)$/i, '$1');
|
||||
}
|
||||
|
||||
function isNoLightbox(img) {
|
||||
if (img.closest(EXCLUDE_SEL)) return true;
|
||||
// parent anchor that does NOT point to an image
|
||||
var parentA = img.closest('a');
|
||||
if (parentA) {
|
||||
var href = parentA.getAttribute('href') || '';
|
||||
if (href && !/\.(jpe?g|png|gif|webp|avif|svg|bmp)(\?|$)/i.test(href) && !parentA.hasAttribute('data-imgbox')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function createLightbox() {
|
||||
if (lightboxEl) return;
|
||||
|
||||
lightboxEl = document.createElement('div');
|
||||
lightboxEl.className = 'aksrt-lightbox';
|
||||
lightboxEl.innerHTML =
|
||||
'<div class="aksrt-lightbox__toolbar">' +
|
||||
'<span class="aksrt-lightbox__counter"></span>' +
|
||||
'<button type="button" class="aksrt-lightbox__tool toggle-zoom" title="缩放"><i class="fas fa-search-plus"></i></button>' +
|
||||
'<button type="button" class="aksrt-lightbox__tool toggle-thumbs" title="缩略图"><i class="fas fa-th"></i></button>' +
|
||||
'<button type="button" class="aksrt-lightbox__tool toggle-play" title="幻灯片"><i class="fas fa-play"></i></button>' +
|
||||
'<button type="button" class="aksrt-lightbox__tool toggle-full" title="全屏"><i class="fas fa-expand"></i></button>' +
|
||||
'<button type="button" class="aksrt-lightbox__tool aksrt-lightbox__download" title="下载"><i class="fas fa-download"></i></button>' +
|
||||
'<button type="button" class="aksrt-lightbox__tool aksrt-lightbox__close" title="关闭"><i class="fas fa-times"></i></button>' +
|
||||
'</div>' +
|
||||
'<button type="button" class="aksrt-lightbox__nav aksrt-lightbox__nav--prev" aria-label="上一张"><i class="fas fa-chevron-left"></i></button>' +
|
||||
'<div class="aksrt-lightbox__stage"><img class="aksrt-lightbox__img" src="" alt=""></div>' +
|
||||
'<button type="button" class="aksrt-lightbox__nav aksrt-lightbox__nav--next" aria-label="下一张"><i class="fas fa-chevron-right"></i></button>' +
|
||||
'<div class="aksrt-lightbox__caption"></div>' +
|
||||
'<div class="aksrt-lightbox__thumbs" hidden></div>';
|
||||
|
||||
document.body.appendChild(lightboxEl);
|
||||
|
||||
lightboxImg = lightboxEl.querySelector('.aksrt-lightbox__img');
|
||||
lightboxCaption = lightboxEl.querySelector('.aksrt-lightbox__caption');
|
||||
lightboxCounter = lightboxEl.querySelector('.aksrt-lightbox__counter');
|
||||
lightboxThumbsWrap = lightboxEl.querySelector('.aksrt-lightbox__thumbs');
|
||||
|
||||
// Close
|
||||
lightboxEl.querySelector('.aksrt-lightbox__close').addEventListener('click', function (e) { e.stopPropagation(); closeLightbox(); });
|
||||
lightboxEl.addEventListener('click', function (e) { if (e.target === lightboxEl || e.target.classList.contains('aksrt-lightbox__stage')) closeLightbox(); });
|
||||
|
||||
// Nav
|
||||
lightboxEl.querySelector('.aksrt-lightbox__nav--prev').addEventListener('click', function (e) { e.stopPropagation(); navigateLightbox(-1); });
|
||||
lightboxEl.querySelector('.aksrt-lightbox__nav--next').addEventListener('click', function (e) { e.stopPropagation(); navigateLightbox(1); });
|
||||
|
||||
// Keyboard
|
||||
document.addEventListener('keydown', function (e) {
|
||||
if (!lightboxEl.classList.contains('is-open')) return;
|
||||
if (e.key === 'Escape') closeLightbox();
|
||||
if (e.key === 'ArrowLeft') navigateLightbox(-1);
|
||||
if (e.key === 'ArrowRight') navigateLightbox(1);
|
||||
});
|
||||
|
||||
// Mousewheel nav
|
||||
lightboxEl.addEventListener('wheel', function (e) {
|
||||
if (!lightboxEl.classList.contains('is-open')) return;
|
||||
if (currentZoom > 1) return; // don't nav when zoomed
|
||||
e.preventDefault();
|
||||
if (e.deltaY > 0) navigateLightbox(1);
|
||||
else navigateLightbox(-1);
|
||||
}, { passive: false });
|
||||
|
||||
// Image click → toggle zoom
|
||||
lightboxImg.addEventListener('click', function (e) { e.stopPropagation(); toggleZoom(); });
|
||||
|
||||
// Double-click → zoom in
|
||||
lightboxImg.addEventListener('dblclick', function (e) {
|
||||
e.stopPropagation();
|
||||
var maxZoom = window.innerWidth < 768 ? MAX_ZOOM_MOBILE : MAX_ZOOM_DESKTOP;
|
||||
if (currentZoom < maxZoom) setZoom(maxZoom);
|
||||
else setZoom(1);
|
||||
});
|
||||
|
||||
// Pinch zoom (mobile)
|
||||
var pinchStart = 0;
|
||||
lightboxEl.addEventListener('touchstart', function (e) {
|
||||
if (e.touches.length === 2) {
|
||||
pinchStart = Math.hypot(
|
||||
e.touches[1].clientX - e.touches[0].clientX,
|
||||
e.touches[1].clientY - e.touches[0].clientY
|
||||
);
|
||||
}
|
||||
}, { passive: true });
|
||||
|
||||
lightboxEl.addEventListener('touchmove', function (e) {
|
||||
if (e.touches.length === 2 && pinchStart > 0) {
|
||||
var dist = Math.hypot(
|
||||
e.touches[1].clientX - e.touches[0].clientX,
|
||||
e.touches[1].clientY - e.touches[0].clientY
|
||||
);
|
||||
var maxZoom = window.innerWidth < 768 ? MAX_ZOOM_MOBILE : MAX_ZOOM_DESKTOP;
|
||||
var newZoom = Math.min(maxZoom, Math.max(1, currentZoom * (dist / pinchStart)));
|
||||
setZoom(newZoom);
|
||||
pinchStart = dist;
|
||||
}
|
||||
}, { passive: true });
|
||||
|
||||
lightboxEl.addEventListener('touchend', function () { pinchStart = 0; }, { passive: true });
|
||||
|
||||
// Touch swipe/pull-dismiss (skip when zoomed)
|
||||
var touchStartY = 0, touchStartX = 0, isSwiping = false;
|
||||
lightboxEl.addEventListener('touchstart', function (e) {
|
||||
if (e.touches.length !== 1 || currentZoom > 1.05) return;
|
||||
touchStartY = e.touches[0].clientY;
|
||||
touchStartX = e.touches[0].clientX;
|
||||
isSwiping = false;
|
||||
}, { passive: true });
|
||||
|
||||
lightboxEl.addEventListener('touchmove', function (e) {
|
||||
if (e.touches.length !== 1 || currentZoom > 1.05) return;
|
||||
var dy = e.touches[0].clientY - touchStartY;
|
||||
var dx = e.touches[0].clientX - touchStartX;
|
||||
if (Math.abs(dy) > Math.abs(dx) && dy > 30) {
|
||||
isSwiping = true;
|
||||
var opacity = Math.max(0.2, (150 - dy) / 80);
|
||||
lightboxImg.style.transform = 'translate3d(0, ' + dy + 'px, 0) scale(' + currentZoom + ')';
|
||||
lightboxImg.style.opacity = String(Math.min(1, opacity));
|
||||
}
|
||||
}, { passive: true });
|
||||
|
||||
lightboxEl.addEventListener('touchend', function () {
|
||||
if (isSwiping) {
|
||||
closeLightbox();
|
||||
lightboxImg.style.transform = '';
|
||||
lightboxImg.style.opacity = '';
|
||||
}
|
||||
isSwiping = false;
|
||||
}, { passive: true });
|
||||
|
||||
// Download
|
||||
lightboxEl.querySelector('.aksrt-lightbox__download').addEventListener('click', function (e) {
|
||||
e.stopPropagation();
|
||||
var item = currentGallery[currentIndex];
|
||||
if (!item || !item.src) return;
|
||||
var a = document.createElement('a');
|
||||
var fullSrc = item.fullSrc || item.src;
|
||||
a.href = fullSrc;
|
||||
a.download = fullSrc.substring(fullSrc.lastIndexOf('/') + 1) || 'image';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
a.remove();
|
||||
});
|
||||
|
||||
// Zoom button
|
||||
lightboxEl.querySelector('.toggle-zoom').addEventListener('click', function (e) { e.stopPropagation(); toggleZoom(); });
|
||||
|
||||
// Thumbnails toggle
|
||||
lightboxEl.querySelector('.toggle-thumbs').addEventListener('click', function (e) {
|
||||
e.stopPropagation();
|
||||
lightboxThumbsWrap.hidden = !lightboxThumbsWrap.hidden;
|
||||
});
|
||||
|
||||
// Slideshow toggle
|
||||
lightboxEl.querySelector('.toggle-play').addEventListener('click', function (e) {
|
||||
e.stopPropagation();
|
||||
toggleAutoplay();
|
||||
});
|
||||
|
||||
// Fullscreen
|
||||
lightboxEl.querySelector('.toggle-full').addEventListener('click', function (e) {
|
||||
e.stopPropagation();
|
||||
toggleFullscreen();
|
||||
});
|
||||
|
||||
document.addEventListener('fullscreenchange', function () {
|
||||
var icon = lightboxEl.querySelector('.toggle-full i');
|
||||
if (document.fullscreenElement) {
|
||||
lightboxEl.classList.add('full-screen');
|
||||
icon.className = 'fas fa-compress';
|
||||
} else {
|
||||
lightboxEl.classList.remove('full-screen');
|
||||
icon.className = 'fas fa-expand';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function setZoom(z) {
|
||||
currentZoom = z;
|
||||
lightboxImg.style.transform = 'scale(' + z + ')';
|
||||
lightboxEl.classList.toggle('is-zoomed', z > 1);
|
||||
}
|
||||
|
||||
function toggleZoom() {
|
||||
var maxZoom = window.innerWidth < 768 ? MAX_ZOOM_MOBILE : MAX_ZOOM_DESKTOP;
|
||||
setZoom(currentZoom > 1 ? 1 : maxZoom);
|
||||
}
|
||||
|
||||
function toggleAutoplay() {
|
||||
var icon = lightboxEl.querySelector('.toggle-play i');
|
||||
if (isAutoplay) {
|
||||
clearInterval(autoplayTimer);
|
||||
isAutoplay = false;
|
||||
icon.className = 'fas fa-play';
|
||||
} else {
|
||||
if (currentGallery.length < 2) return;
|
||||
isAutoplay = true;
|
||||
icon.className = 'fas fa-pause';
|
||||
autoplayTimer = setInterval(function () { navigateLightbox(1); }, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
function toggleFullscreen() {
|
||||
var rfs = lightboxEl.requestFullscreen || lightboxEl.webkitRequestFullscreen || lightboxEl.msRequestFullscreen;
|
||||
if (document.fullscreenElement || document.webkitFullscreenElement) {
|
||||
(document.exitFullscreen || document.webkitExitFullscreen || document.msExitFullscreen).call(document);
|
||||
} else if (rfs) {
|
||||
rfs.call(lightboxEl);
|
||||
}
|
||||
}
|
||||
|
||||
function buildThumbnails() {
|
||||
if (!lightboxThumbsWrap) return;
|
||||
lightboxThumbsWrap.innerHTML = '';
|
||||
currentGallery.forEach(function (item, i) {
|
||||
var thumb = document.createElement('img');
|
||||
thumb.src = item.src;
|
||||
thumb.className = 'aksrt-lightbox__thumb' + (i === currentIndex ? ' is-active' : '');
|
||||
thumb.addEventListener('click', function (e) {
|
||||
e.stopPropagation();
|
||||
showLightboxImage(i);
|
||||
});
|
||||
lightboxThumbsWrap.appendChild(thumb);
|
||||
});
|
||||
}
|
||||
|
||||
function syncThumbActive() {
|
||||
if (!lightboxThumbsWrap) return;
|
||||
var thumbs = lightboxThumbsWrap.querySelectorAll('.aksrt-lightbox__thumb');
|
||||
thumbs.forEach(function (t, i) { t.classList.toggle('is-active', i === currentIndex); });
|
||||
var active = thumbs[currentIndex];
|
||||
if (active) active.scrollIntoView({ inline: 'center', block: 'nearest', behavior: 'smooth' });
|
||||
}
|
||||
|
||||
function openLightbox(src, caption, gallery, index, originEl) {
|
||||
createLightbox();
|
||||
|
||||
currentGallery = gallery || [{ src: src, caption: caption || '' }];
|
||||
currentIndex = index || 0;
|
||||
currentZoom = 1;
|
||||
|
||||
// Origin animation
|
||||
if (originEl) {
|
||||
var rect = originEl.getBoundingClientRect();
|
||||
lightboxEl.style.setProperty('--imgbox-origin-top', (rect.top + rect.height / 2) + 'px');
|
||||
lightboxEl.style.setProperty('--imgbox-origin-left', (rect.left + rect.width / 2) + 'px');
|
||||
lightboxEl.classList.add('from-origin');
|
||||
} else {
|
||||
lightboxEl.classList.remove('from-origin');
|
||||
}
|
||||
|
||||
showLightboxImage(currentIndex);
|
||||
buildThumbnails();
|
||||
|
||||
lightboxEl.classList.add('is-open');
|
||||
document.body.style.overflow = 'hidden';
|
||||
|
||||
lightboxEl.dispatchEvent(new CustomEvent('aksrt:lightbox-open', { bubbles: true }));
|
||||
}
|
||||
|
||||
function showLightboxImage(index) {
|
||||
if (index < 0) index = currentGallery.length - 1;
|
||||
if (index >= currentGallery.length) index = 0;
|
||||
currentIndex = index;
|
||||
setZoom(1);
|
||||
|
||||
var item = currentGallery[currentIndex];
|
||||
lightboxImg.src = item.fullSrc || item.src;
|
||||
lightboxImg.alt = item.caption || '';
|
||||
lightboxCaption.textContent = item.caption || '';
|
||||
lightboxCaption.style.display = item.caption ? '' : 'none';
|
||||
|
||||
if (currentGallery.length > 1) {
|
||||
lightboxCounter.textContent = (currentIndex + 1) + ' / ' + currentGallery.length;
|
||||
lightboxCounter.style.display = '';
|
||||
} else {
|
||||
lightboxCounter.style.display = 'none';
|
||||
}
|
||||
|
||||
syncThumbActive();
|
||||
}
|
||||
|
||||
function navigateLightbox(dir) {
|
||||
showLightboxImage(currentIndex + dir);
|
||||
}
|
||||
|
||||
function closeLightbox() {
|
||||
if (!lightboxEl) return;
|
||||
if (isAutoplay) toggleAutoplay();
|
||||
lightboxEl.classList.remove('is-open', 'is-zoomed', 'from-origin');
|
||||
document.body.style.overflow = '';
|
||||
lightboxThumbsWrap.hidden = true;
|
||||
if (document.fullscreenElement) {
|
||||
(document.exitFullscreen || document.webkitExitFullscreen || document.msExitFullscreen).call(document);
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-bind: expanded trigger scope + exclusion rules
|
||||
function initLightbox() {
|
||||
document.addEventListener('click', function (e) {
|
||||
// Also support a[data-imgbox]
|
||||
var anchor = e.target.closest('a[data-imgbox]');
|
||||
if (anchor) {
|
||||
e.preventDefault();
|
||||
var href = anchor.getAttribute('href') || anchor.getAttribute('data-imgbox');
|
||||
openLightbox(href, '', [{ src: href, fullSrc: href, caption: '' }], 0, anchor);
|
||||
return;
|
||||
}
|
||||
|
||||
var img = e.target.closest(TRIGGER_SEL);
|
||||
if (!img) return;
|
||||
if (img.width < 100 || img.height < 100) return;
|
||||
if (isNoLightbox(img)) return;
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
var container = img.closest(CONTAINER_SEL);
|
||||
if (!container) return;
|
||||
|
||||
var allImages = container.querySelectorAll('img');
|
||||
var gallery = [];
|
||||
var foundIndex = 0;
|
||||
|
||||
allImages.forEach(function (el) {
|
||||
if (el.width < 100 || el.height < 100) return;
|
||||
if (isNoLightbox(el)) return;
|
||||
var full = resolveFullUrl(el);
|
||||
var caption = el.alt || '';
|
||||
var figcaption = el.closest('figure') ? el.closest('figure').querySelector('figcaption') : null;
|
||||
if (figcaption) caption = figcaption.textContent;
|
||||
gallery.push({ src: el.dataset.src || el.src, fullSrc: full, caption: caption });
|
||||
if (el === img) foundIndex = gallery.length - 1;
|
||||
});
|
||||
|
||||
if (gallery.length > 0) {
|
||||
openLightbox(img.dataset.src || img.src, img.alt, gallery, foundIndex, img);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 暴露到全局
|
||||
window.AksrtLightbox = {
|
||||
open: openLightbox,
|
||||
close: closeLightbox,
|
||||
};
|
||||
|
||||
/* ============================================================
|
||||
* 3. 滚动方向感知
|
||||
* ============================================================ */
|
||||
// Scroll direction is now handled by aksrt-runtime.js body scroll bus
|
||||
// (body.scroll-down / body.scroll-up / body.body-scroll).
|
||||
// This stub syncs the legacy aksrt-* prefixed classes for backward compat.
|
||||
function initScrollDirection() {
|
||||
var body = document.body;
|
||||
|
||||
function sync() {
|
||||
body.classList.toggle('aksrt-body-scroll', body.classList.contains('body-scroll'));
|
||||
body.classList.toggle('aksrt-scroll-down', body.classList.contains('scroll-down'));
|
||||
body.classList.toggle('aksrt-scroll-up', body.classList.contains('scroll-up'));
|
||||
|
||||
body.classList.add('aksrt-scrolling');
|
||||
clearTimeout(body._aksrtScrollTimer);
|
||||
body._aksrtScrollTimer = setTimeout(function () {
|
||||
body.classList.remove('aksrt-scrolling');
|
||||
}, 300);
|
||||
}
|
||||
|
||||
function onScroll() {
|
||||
requestAnimationFrame(sync);
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', onScroll, { passive: true });
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 4. 导航溢出自动折叠
|
||||
* 菜单项超出容器宽度时折叠进「更多」下拉
|
||||
* ============================================================ */
|
||||
function initNavOverflow() {
|
||||
var nav = document.querySelector('.site-nav .nav-menu, .site-nav .primary-nav, .header-nav__menu');
|
||||
if (!nav) return;
|
||||
|
||||
// 创建「更多」按钮
|
||||
var moreLi = document.createElement('li');
|
||||
moreLi.className = 'nav-item aksrt-nav-more';
|
||||
moreLi.style.display = 'none';
|
||||
moreLi.innerHTML =
|
||||
'<button type="button" class="aksrt-nav-more__btn" aria-haspopup="true" aria-expanded="false">更多 <i class="fas fa-caret-down"></i></button>' +
|
||||
'<ul class="aksrt-nav-more__dropdown"></ul>';
|
||||
nav.appendChild(moreLi);
|
||||
|
||||
var moreBtn = moreLi.querySelector('.aksrt-nav-more__btn');
|
||||
var dropdown = moreLi.querySelector('.aksrt-nav-more__dropdown');
|
||||
|
||||
moreBtn.addEventListener('click', function (e) {
|
||||
e.stopPropagation();
|
||||
var open = dropdown.classList.toggle('is-open');
|
||||
moreBtn.setAttribute('aria-expanded', open ? 'true' : 'false');
|
||||
});
|
||||
|
||||
document.addEventListener('click', function () {
|
||||
dropdown.classList.remove('is-open');
|
||||
moreBtn.setAttribute('aria-expanded', 'false');
|
||||
});
|
||||
|
||||
function checkOverflow() {
|
||||
var items = Array.from(nav.children).filter(function (el) {
|
||||
return !el.classList.contains('aksrt-nav-more');
|
||||
});
|
||||
|
||||
// 重置:把所有项移回原位
|
||||
while (dropdown.firstChild) {
|
||||
var li = dropdown.firstChild;
|
||||
nav.insertBefore(li, moreLi);
|
||||
}
|
||||
moreLi.style.display = 'none';
|
||||
|
||||
var navWidth = nav.clientWidth;
|
||||
var moreWidth = 80; // 预留「更多」按钮宽度
|
||||
var usedWidth = 0;
|
||||
var overflowItems = [];
|
||||
|
||||
items.forEach(function (item) {
|
||||
usedWidth += item.offsetWidth;
|
||||
if (usedWidth + moreWidth > navWidth) {
|
||||
overflowItems.push(item);
|
||||
}
|
||||
});
|
||||
|
||||
if (overflowItems.length > 0) {
|
||||
moreLi.style.display = '';
|
||||
overflowItems.forEach(function (item) {
|
||||
dropdown.appendChild(item);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// ResizeObserver 监听(避免 resize 抖动)
|
||||
if ('ResizeObserver' in window) {
|
||||
var timer = null;
|
||||
var ro = new ResizeObserver(function () {
|
||||
if (timer) clearTimeout(timer);
|
||||
timer = setTimeout(checkOverflow, 100);
|
||||
});
|
||||
ro.observe(nav);
|
||||
} else {
|
||||
window.addEventListener('resize', checkOverflow, { passive: true });
|
||||
}
|
||||
|
||||
// 初始检测
|
||||
checkOverflow();
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 初始化入口
|
||||
* ============================================================ */
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
initLightbox();
|
||||
initScrollDirection();
|
||||
initNavOverflow();
|
||||
});
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,314 @@
|
||||
/**
|
||||
* AKSRT Enhancements Part 2 — 高级交互组件
|
||||
*
|
||||
* 包含:3D 悬停倾斜、滚动触发动画、封面轮播、打赏按钮
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/* ============================================================
|
||||
* 1. 3D 悬停倾斜效果 (vanilla-tilt 轻量版)
|
||||
* ============================================================ */
|
||||
function initTilt() {
|
||||
document.querySelectorAll('[data-aksrt-tilt]').forEach(function (el) {
|
||||
if (el.dataset.tiltInit) return;
|
||||
el.dataset.tiltInit = '1';
|
||||
|
||||
var maxTilt = parseInt(el.dataset.aksrtTiltMax || '15', 10);
|
||||
var perspective = parseInt(el.dataset.aksrtTiltPerspective || '1000', 10);
|
||||
var scale = parseFloat(el.dataset.aksrtTiltScale || '1.03');
|
||||
var speed = parseInt(el.dataset.aksrtTiltSpeed || '400', 10);
|
||||
var glare = el.dataset.aksrtTiltGlare === '1';
|
||||
|
||||
el.style.transformStyle = 'preserve-3d';
|
||||
el.style.transition = 'transform ' + speed + 'ms ease';
|
||||
|
||||
var glareEl = null;
|
||||
if (glare) {
|
||||
glareEl = document.createElement('div');
|
||||
glareEl.style.cssText = 'position:absolute;inset:0;border-radius:inherit;pointer-events:none;opacity:0;transition:opacity ' + speed + 'ms;';
|
||||
el.style.position = el.style.position || 'relative';
|
||||
el.style.overflow = 'hidden';
|
||||
el.appendChild(glareEl);
|
||||
}
|
||||
|
||||
el.addEventListener('mousemove', function (e) {
|
||||
var rect = el.getBoundingClientRect();
|
||||
var x = (e.clientX - rect.left) / rect.width;
|
||||
var y = (e.clientY - rect.top) / rect.height;
|
||||
var tiltX = (0.5 - y) * maxTilt;
|
||||
var tiltY = (x - 0.5) * maxTilt;
|
||||
|
||||
el.style.transform = 'perspective(' + perspective + 'px) rotateX(' + tiltX + 'deg) rotateY(' + tiltY + 'deg) scale3d(' + scale + ',' + scale + ',' + scale + ')';
|
||||
|
||||
if (glareEl) {
|
||||
glareEl.style.opacity = '1';
|
||||
glareEl.style.background = 'linear-gradient(135deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0.2) 50%, rgba(255,255,255,0) 100%)';
|
||||
glareEl.style.transform = 'translate(' + ((x - 0.5) * 100) + '%, ' + ((y - 0.5) * 100) + '%)';
|
||||
}
|
||||
});
|
||||
|
||||
el.addEventListener('mouseleave', function () {
|
||||
el.style.transform = 'perspective(' + perspective + 'px) rotateX(0deg) rotateY(0deg) scale3d(1,1,1)';
|
||||
if (glareEl) glareEl.style.opacity = '0';
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 2. 滚动触发动画 (IntersectionObserver)
|
||||
* ============================================================ */
|
||||
function initScrollAnimations() {
|
||||
if (!('IntersectionObserver' in window)) {
|
||||
// 不支持时直接显示所有元素
|
||||
document.querySelectorAll('[data-aksrt-animate]').forEach(function (el) {
|
||||
el.style.opacity = '1';
|
||||
el.style.transform = 'none';
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var observer = new IntersectionObserver(function (entries) {
|
||||
entries.forEach(function (entry) {
|
||||
if (!entry.isIntersecting) return;
|
||||
|
||||
var el = entry.target;
|
||||
var animation = el.dataset.aksrtAnimate || 'fadeInUp';
|
||||
var delay = parseInt(el.dataset.aksrtAnimateDelay || '0', 10);
|
||||
var duration = parseInt(el.dataset.aksrtAnimateDuration || '600', 10);
|
||||
|
||||
setTimeout(function () {
|
||||
el.style.transition = 'opacity ' + duration + 'ms ease, transform ' + duration + 'ms ease';
|
||||
el.style.opacity = '1';
|
||||
el.style.transform = 'translateY(0) translateX(0) scale(1)';
|
||||
el.classList.add('aksrt-animated');
|
||||
}, delay);
|
||||
|
||||
observer.unobserve(el);
|
||||
});
|
||||
}, {
|
||||
threshold: 0.1,
|
||||
rootMargin: '0px 0px -50px 0px',
|
||||
});
|
||||
|
||||
document.querySelectorAll('[data-aksrt-animate]').forEach(function (el) {
|
||||
var animation = el.dataset.aksrtAnimate || 'fadeInUp';
|
||||
|
||||
// 设置初始状态
|
||||
el.style.opacity = '0';
|
||||
switch (animation) {
|
||||
case 'fadeIn':
|
||||
el.style.transform = 'none';
|
||||
break;
|
||||
case 'fadeInUp':
|
||||
el.style.transform = 'translateY(30px)';
|
||||
break;
|
||||
case 'fadeInDown':
|
||||
el.style.transform = 'translateY(-30px)';
|
||||
break;
|
||||
case 'fadeInLeft':
|
||||
el.style.transform = 'translateX(-30px)';
|
||||
break;
|
||||
case 'fadeInRight':
|
||||
el.style.transform = 'translateX(30px)';
|
||||
break;
|
||||
case 'zoomIn':
|
||||
el.style.transform = 'scale(0.9)';
|
||||
break;
|
||||
default:
|
||||
el.style.transform = 'translateY(30px)';
|
||||
}
|
||||
|
||||
observer.observe(el);
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 3. 文章封面轮播
|
||||
* ============================================================ */
|
||||
function initCoverSlider() {
|
||||
var container = document.querySelector('.single-cover-slider[data-swiper-config]');
|
||||
if (!container || typeof Swiper === 'undefined') return;
|
||||
|
||||
var config = {};
|
||||
try {
|
||||
config = JSON.parse(container.dataset.swiperConfig || '{}');
|
||||
} catch (e) {}
|
||||
|
||||
new Swiper(container, Object.assign({
|
||||
effect: 'fade',
|
||||
fadeEffect: { crossFade: true },
|
||||
loop: true,
|
||||
speed: 800,
|
||||
autoplay: { delay: 5000, disableOnInteraction: false },
|
||||
pagination: {
|
||||
el: '.single-cover-slider__pagination',
|
||||
type: 'bullets',
|
||||
clickable: true,
|
||||
},
|
||||
navigation: {
|
||||
prevEl: '.single-cover-slider__prev',
|
||||
nextEl: '.single-cover-slider__next',
|
||||
},
|
||||
}, config));
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 5. 粘性元素 (Sticky)
|
||||
* ============================================================ */
|
||||
function initSticky() {
|
||||
document.querySelectorAll('[data-aksrt-sticky]').forEach(function (el) {
|
||||
var top = parseInt(el.dataset.aksrtStickyTop || '80', 10);
|
||||
var offset = parseInt(el.dataset.aksrtStickyOffset || '0', 10);
|
||||
|
||||
function update() {
|
||||
var rect = el.getBoundingClientRect();
|
||||
var parentRect = el.parentElement.getBoundingClientRect();
|
||||
|
||||
if (parentRect.top < top && parentRect.bottom > el.offsetHeight + top) {
|
||||
el.style.position = 'sticky';
|
||||
el.style.top = top + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', update, { passive: true });
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 6. 视差滚动
|
||||
* ============================================================ */
|
||||
function initParallax() {
|
||||
var elements = document.querySelectorAll('[data-aksrt-parallax]');
|
||||
if (elements.length === 0) return;
|
||||
|
||||
var ticking = false;
|
||||
|
||||
function update() {
|
||||
var scrollTop = window.pageYOffset;
|
||||
elements.forEach(function (el) {
|
||||
var speed = parseFloat(el.dataset.aksrtParallax || '0.3');
|
||||
var rect = el.getBoundingClientRect();
|
||||
var center = rect.top + rect.height / 2;
|
||||
var windowCenter = window.innerHeight / 2;
|
||||
var offset = (center - windowCenter) * speed;
|
||||
|
||||
el.style.transform = 'translateY(' + offset + 'px)';
|
||||
});
|
||||
ticking = false;
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', function () {
|
||||
if (!ticking) {
|
||||
requestAnimationFrame(update);
|
||||
ticking = true;
|
||||
}
|
||||
}, { passive: true });
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 7. 涟漪点击效果
|
||||
* ============================================================ */
|
||||
function initRipple() {
|
||||
document.addEventListener('click', function (e) {
|
||||
var el = e.target.closest('.aksrt-ripple');
|
||||
if (!el) return;
|
||||
|
||||
var rect = el.getBoundingClientRect();
|
||||
var x = e.clientX - rect.left;
|
||||
var y = e.clientY - rect.top;
|
||||
var size = Math.max(rect.width, rect.height) * 2;
|
||||
|
||||
var wave = document.createElement('span');
|
||||
wave.className = 'aksrt-ripple__wave';
|
||||
wave.style.width = wave.style.height = size + 'px';
|
||||
wave.style.left = (x - size / 2) + 'px';
|
||||
wave.style.top = (y - size / 2) + 'px';
|
||||
|
||||
el.appendChild(wave);
|
||||
|
||||
wave.addEventListener('animationend', function () {
|
||||
wave.remove();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 8. 表单浮动标签自动初始化
|
||||
* ============================================================ */
|
||||
function initFloatLabels() {
|
||||
document.querySelectorAll('.aksrt-float-label__input').forEach(function (input) {
|
||||
// 检查初始值
|
||||
if (input.value) {
|
||||
input.setAttribute('data-has-value', '1');
|
||||
}
|
||||
input.addEventListener('input', function () {
|
||||
if (this.value) {
|
||||
this.setAttribute('data-has-value', '1');
|
||||
} else {
|
||||
this.removeAttribute('data-has-value');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 8. 签到日历可视化
|
||||
* ============================================================ */
|
||||
function initSigninCalendar() {
|
||||
var calendar = document.querySelector('[data-aksrt-signin-calendar]');
|
||||
if (!calendar) return;
|
||||
|
||||
var data = [];
|
||||
try {
|
||||
data = JSON.parse(calendar.dataset.aksrtSigninCalendar || '[]');
|
||||
} catch (e) {}
|
||||
|
||||
// 生成最近 30 天的格子
|
||||
var today = new Date();
|
||||
var html = '<div class="aksrt-signin-calendar__grid">';
|
||||
|
||||
for (var i = 29; i >= 0; i--) {
|
||||
var d = new Date(today);
|
||||
d.setDate(d.getDate() - i);
|
||||
var dateStr = d.toISOString().split('T')[0];
|
||||
var isSigned = data.indexOf(dateStr) !== -1;
|
||||
var isToday = i === 0;
|
||||
|
||||
html += '<div class="aksrt-signin-calendar__day' +
|
||||
(isSigned ? ' is-signed' : '') +
|
||||
(isToday ? ' is-today' : '') +
|
||||
'" title="' + dateStr + (isSigned ? ' ✓' : '') + '">' +
|
||||
'<span>' + d.getDate() + '</span>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
html += '</div>';
|
||||
calendar.innerHTML = html;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 初始化入口
|
||||
* ============================================================ */
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
initTilt();
|
||||
initScrollAnimations();
|
||||
initCoverSlider();
|
||||
initRipple();
|
||||
initSticky();
|
||||
initParallax();
|
||||
initFloatLabels();
|
||||
initSigninCalendar();
|
||||
});
|
||||
|
||||
// 暴露到全局供动态内容使用
|
||||
window.AksrtEnhancements = {
|
||||
initTilt: initTilt,
|
||||
initScrollAnimations: initScrollAnimations,
|
||||
initRipple: initRipple,
|
||||
};
|
||||
|
||||
})();
|
||||
+1
@@ -0,0 +1 @@
|
||||
/*! EnlighterJS Syntax Highlighter 3.0.0 | Mozilla Public License 2.0 | https://enlighterjs.org */.enlighter-tooltip{z-index:100}.enlighter-default{font-family:Menlo,Monaco,Consolas,"Courier New",monospace;font-size:13px;line-height:1.4;overflow:hidden;white-space:pre-wrap;word-wrap:break-word;margin:0 0 20px 0;padding:0;position:relative;text-align:left;direction:ltr;border-radius:8px}.enlighter-default .enlighter-special:hover{background-color:#f4f8fc}.enlighter-default .enlighter-raw{display:none;white-space:pre-wrap;word-wrap:break-word;box-shadow:none;padding:0 17px!important;color:inherit}.enlighter-toolbar{opacity:0;position:absolute;right:10px;top:8px;z-index:10;transition:.2s}.enlighter-default:hover .enlighter-toolbar{opacity:1}.enlighter-default .enlighter-btn{font:normal normal normal 14px/1 FontAwesome;border-radius:4px;display:inline-block;transition:.15s;padding:.3em .6em;background:rgba(235,237,239,.8);color:#666;font-size:14px;margin-left:6px;cursor:pointer}.enlighter-default .enlighter-btn:hover{color:#157ff9}.enlighter-t-atomic .enlighter-btn,.enlighter-t-dracula .enlighter-btn,.enlighter-t-monokai .enlighter-btn{background:rgba(57,60,66,.87)}.enlighter-default .enlighter-toolbar .enlighter-btn-raw::after{content:"\f121"}.enlighter-default .enlighter-toolbar .enlighter-btn-copy::after{content:"\f0ea"}.enlighter-default .enlighter-toolbar .enlighter-btn-window::after{content:"\f1b2"}.enlighter-origin{display:none!important}.enlighter-clipboard{position:absolute;left:0;bottom:0;width:1px;height:1px;overflow:hidden}.enlighter-v-inline{display:inline-block;overflow:inherit;margin:0}.enlighter-v-standard{display:block}.enlighter-v-codegroup{display:block}.enlighter-v-codegroup .enlighter-codegroup-wrapper{position:relative}div.enlighter{width:100%;border-collapse:collapse;border-spacing:0;padding:12px 0;empty-cells:show;min-width:100%;font-size:10px;margin:0;text-indent:0;-webkit-overflow-scrolling:touch;counter-reset:enlighter 0}div.enlighter>div{margin:0;border:solid 0 #fff;list-style:none;font-size:inherit;line-height:1.4;min-height:14px}div.enlighter>div>div{display:table-cell;width:100%;padding-left:10px}div.enlighter>div>div::before{content:" "}span.enlighter{display:inline-block;padding:3px 5px 1px 5px;margin:0 2px 0 2px}.enlighter span{margin:0;padding:0;line-height:inherit;font-size:13px;font-family:inherit}.enlighter-linenumbers div.enlighter>div::before{white-space:nowrap;display:block;display:table-cell;width:45px;min-width:45px;counter-increment:enlighter;content:counter(enlighter,decimal) ".";text-align:right;padding-right:8px}.enlighter-overflow-scroll.enlighter-v-standard .enlighter{overflow-x:auto;word-wrap:normal!important}.enlighter-overflow-scroll.enlighter-v-codegroup .enlighter-codegroup-wrapper{overflow-x:auto;word-wrap:normal!important}.enlighter-overflow-scroll.enlighter-v-codegroup .enlighter>div>div,.enlighter-overflow-scroll.enlighter-v-standard .enlighter>div>div{white-space:pre!important}.enlighter-overflow-scroll.enlighter-v-codegroup .enlighter-raw,.enlighter-overflow-scroll.enlighter-v-standard .enlighter-raw{white-space:pre!important}.enlighter-show-rawcode .enlighter-raw{padding:12px 16px!important;display:block}.enlighter-show-rawcode .enlighter{display:none!important}.enlighter-t-enlighter{color:#555;background:#f8f9fa}.enlighter-t-enlighter.enlighter-hover div.enlighter>div:hover{color:#444;background-color:#fffcd3}.enlighter-t-enlighter div.enlighter>div{color:#aaa}.enlighter-t-enlighter div.enlighter>div.enlighter-special{background-color:#fdf5f0}.enlighter-t-enlighter.enlighter-linenumbers div.enlighter>div::before{border-right:solid 1px #e8e8e8}.enlighter-t-enlighter .enlighter-text{color:#555}.enlighter-t-enlighter .enlighter-c0{color:#99a}.enlighter-t-enlighter .enlighter-c1{color:#99a}.enlighter-t-enlighter .enlighter-c2{color:#99a}.enlighter-t-enlighter .enlighter-c9{color:#9baa8f}.enlighter-t-enlighter .enlighter-k0{color:#286491;font-weight:700}.enlighter-t-enlighter .enlighter-k1{color:#4573f7;font-weight:700}.enlighter-t-enlighter .enlighter-k2{color:#458;font-weight:700}.enlighter-t-enlighter .enlighter-k3{color:#4da0d2;background-color:#f0f0f0}.enlighter-t-enlighter .enlighter-k4{color:#4a9141;font-weight:700}.enlighter-t-enlighter .enlighter-k5{color:#286491;font-weight:700}.enlighter-t-enlighter .enlighter-k6{color:#286491;font-style:italic}.enlighter-t-enlighter .enlighter-k7{color:#286491;font-weight:700}.enlighter-t-enlighter .enlighter-k8{color:#4da0d2}.enlighter-t-enlighter .enlighter-k9{color:#990073;font-weight:700}.enlighter-t-enlighter .enlighter-k10{color:#4a9141;font-style:italic}.enlighter-t-enlighter .enlighter-e0{color:#34068a;font-weight:700}.enlighter-t-enlighter .enlighter-e1{color:#34068a;font-weight:700}.enlighter-t-enlighter .enlighter-e2{color:#009926}.enlighter-t-enlighter .enlighter-e3{color:#286491}.enlighter-t-enlighter .enlighter-e4{color:#ff8c00;font-style:italic}.enlighter-t-enlighter .enlighter-s0{color:#f1436eLine truncated
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
var EnlighterJS=function(e){"use strict";function t(e,t,r,n,s){return{text:e,type:t,index:n||0,end:e.length+n,filter:r||null,priority:s||0}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function n(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}function s(e,t,r){null===e&&(e=Function.prototype);var n=Object.getOwnPropertyDescriptor(e,t);if(void 0===n){var i=Object.getPrototypeOf(e);return null===i?void 0:s(i,t,r)}if("value"in n)return n.value;var o=n.get;return void 0!==o?o.call(r):void 0}function i(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function o(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function a(){r(this,a),this.rules=[],this.setupLanguage()}function g(){return r(this,g),o(this,(g.__proto__||Object.getPrototypeOf(g)).apply(this,arguments))}function l(){return r(this,l),o(this,(l.__proto__||Object.getPrototypeOf(l)).apply(this,arguments))}function p(){return r(this,p),o(this,(p.__proto__||Object.getPrototypeOf(p)).apply(this,arguments))}function u(){return r(this,u),o(this,(u.__proto__||Object.getPrototypeOf(u)).apply(this,arguments))}function c(e,r,n){for(var s=[],i=0,o=void 0;null!=(o=r.exec(e.text));){i<o.index&&s.push(t(e.text.substring(i,o.index),e.type,null,i));for(var a=n(o,e.type)||[],g=0;g<a.length;g++)s.push(a[g]);i=o.index+o[0].length,r.lastIndex=i}return 0==s.length?[e]:(i<e.text.length&&s.push(t(e.text.substring(i),e.type,null,i)),s)}function y(){return r(this,y),o(this,(y.__proto__||Object.getPrototypeOf(y)).apply(this,arguments))}function b(){return r(this,b),o(this,(b.__proto__||Object.getPrototypeOf(b)).apply(this,arguments))}function f(){return r(this,f),o(this,(f.__proto__||Object.getPrototypeOf(f)).apply(this,arguments))}function h(){return r(this,h),o(this,(h.__proto__||Object.getPrototypeOf(h)).apply(this,arguments))}function d(){return r(this,d),o(this,(d.__proto__||Object.getPrototypeOf(d)).apply(this,arguments))}function x(){return r(this,x),o(this,(x.__proto__||Object.getPrototypeOf(x)).apply(this,arguments))}function m(){return r(this,m),o(this,(m.__proto__||Object.getPrototypeOf(m)).apply(this,arguments))}function k(){return r(this,k),o(this,(k.__proto__||Object.getPrototypeOf(k)).apply(this,arguments))}function _(){return r(this,_),o(this,(_.__proto__||Object.getPrototypeOf(_)).apply(this,arguments))}function w(){return r(this,w),o(this,(w.__proto__||Object.getPrototypeOf(w)).apply(this,arguments))}function v(){return r(this,v),o(this,(v.__proto__||Object.getPrototypeOf(v)).apply(this,arguments))}function C(){return r(this,C),o(this,(C.__proto__||Object.getPrototypeOf(C)).apply(this,arguments))}function O(){return r(this,O),o(this,(O.__proto__||Object.getPrototypeOf(O)).apply(this,arguments))}function S(){return r(this,S),o(this,(S.__proto__||Object.getPrototypeOf(S)).apply(this,arguments))}function A(){return r(this,A),o(this,(A.__proto__||Object.getPrototypeOf(A)).apply(this,arguments))}function L(){return r(this,L),o(this,(L.__proto__||Object.getPrototypeOf(L)).apply(this,arguments))}function j(){return r(this,j),o(this,(j.__proto__||Object.getPrototypeOf(j)).apply(this,arguments))}function q(){return r(this,q),o(this,(q.__proto__||Object.getPrototypeOf(q)).apply(this,arguments))}function E(){return r(this,E),o(this,(E.__proto__||Object.getPrototypeOf(E)).apply(this,arguments))}function P(){return r(this,P),o(this,(P.__proto__||Object.getPrototypeOf(P)).apply(this,arguments))}function W(){return r(this,W),o(this,(W.__proto__||Object.getPrototypeOf(W)).apply(this,arguments))}function $(){return r(this,$),o(this,($.__proto__||Object.getPrototypeOf($)).apply(this,arguments))}function I(){return r(this,I),o(this,(I.__proto__||Object.getPrototypeOf(I)).apply(this,arguments))}function N(){return r(this,N),o(this,(N.__proto__||Object.getPrototypeOf(N)).apply(this,arguments))}function F(){return r(this,F),o(this,(F.__proto__||Object.getPrototypeOf(F)).apply(this,arguments))}function D(){return r(this,D),o(this,(D.__proto__||Object.getPrototypeOf(D)).apply(this,arguments))}function T(){return r(this,T),o(this,(T.__proto__||Object.getPrototypeOf(T)).apply(this,arguments))}function R(){return r(this,R),o(this,(R.__proto__||Object.getPrototypeOf(R)).apply(this,arguments))}function Z(){return r(this,Z),o(this,(Z.__proto__||Object.getPrototypeOf(Z)).apply(this,arguments))}function z(){return r(this,z),o(this,(z.__proto__||Object.getPrototypeOf(z)).apply(this,arguments))}function B(){return r(this,B),o(this,(B.__proto__||Object.getPrototypeOf(B)).apply(this,argumentLine truncated
|
||||
regex:/\b(Data|Do|DynamicParam|Exit|Filter|From|Function|In|InlineScript|Hidden|Parallel|Param|Process|Return|Sequence|Trap|Workflow)\b/gi,type:"k0"},{regex:/\b([A-Z]\w+(?:-\w+)+)\b/g,type:"m0"},{regex:/<#[\S\s]+?#>/gi,type:"c1"},ve.poundComments,{regex:/\$[A-Z_][\w]*/gim,type:"k7"},ve.mCalls,ve.fCalls,ve.int,ve.floats,ve.brackets]}}]),W),Xe=(i($,Se),Ce($,[{key:"setupLanguage",value:function(){this.rules=[{regex:/(%.*)$/gm,type:"c0"},ve.blockComments,ve.dqStrings,ve.sqStrings,{regex:/^(\w+)(?:\(.*?\))?\s*(?::-|\.)/gm,type:"k9"},{regex:/\b(true|false|Yes|No|not|fail)\b/gi,type:"e0"},{regex:/\b(catch|throw|repeat)\b/g,type:"k1"},{regex:/^(\?-)/g,type:"k9"},{regex:/\b(is)\b/g,type:"k3"},{regex:/[A-Z_][\w]*/g,type:"k7"},ve.brackets,ve.floats,ve.int,ve.fCalls]}}]),$),Ke=(i(I,Se),Ce(I,[{key:"setupLanguage",value:function(){this.rules=[ve.dqStrings,ve.prop,{regex:/\b([A-Z]\w+)\b/g,type:"k5"},{regex:/^(import)(\s+[\w.]+)/gm,type:["k0","k5"]},{regex:/\b(bool|char|double|float|int|long|short|void|string)\b/g,type:"k5"},ve.mCalls,ve.null,ve.boolean,ve.slashComments,ve.blockComments,ve.int,ve.floats,ve.brackets]}}]),I),et=(i(N,Se),Ce(N,[{key:"setupLanguage",value:function(){this.rules=[{regex:/^(.*?)$/g,type:"text"}]}}]),N),tt=(i(F,Se),Ce(F,[{key:"setupLanguage",value:function(){function e(e){return e.text.match(/^%r/)?e.type="e2":e.text.match(/^%x/)&&(e.type="e4"),[e]}this.rules=[ve.dqStrings,ve.sqStrings,ve.heredoc,{regex:/(`(?:[^`\\]|\\.)*`)/g,type:"e4"},ve.boolean,{regex:/\b(nil)\b/gi,type:"e1"},ve.fCalls,ve.prop,{regex:/@{1,2}[A-Za-z_]\w*\W/g,type:"k7"},{regex:/[^:](:[\w]+)\b/g,type:"k6"},{regex:/(\$[a-z0-9_-]+|\$.)\W/gi,type:"k9"},{regex:/\b(begin|break|case|do|else|elsif|end|ensure|for|if|in|next|redo|rescue|retry|then|unless|until|when|while)\b/gi,type:"k1"},{regex:/\b((?:__)?[A-Z][A-Z0-9_]+)\b/g,type:"e3"},{regex:/\b(alias|class|defined\?|undef|def|module|return|self|super|yield)\W/gi,type:"k0"},{regex:/\b(and|not|or)\b/gi,type:"k3"},ve.poundComments,{regex:/^=begin[\S\s]*?^=end/gim,type:"c2"},{regex:/(%[iqrswx](\W)(?:[^\2\n\\]|\\.)*\2[iomx]*)/gim,type:"s2",filter:e},{regex:/(%[iqrswx]?(\{(?:[^}\\]|\\.)*}|\[(?:[^}\\]|\\.)*]|\((?:[^)\\]|\\.)*\))[iomx]*)/gim,type:"s2",filter:e},{regex:/\W(\/(?:[^/\\]|\\.)*\/\w*)\W/g,type:"e2"},{regex:/\W\?(?:\w|\\M|\\C)(?:-\w|-\\M|-\\C)*\b/g,type:"n1"},{regex:/[\b\W](-?\d[\d_]+?)(?!\.)\b/g,type:"n1"},{regex:/[\b\W](-?0x[A-F0-9][A-F0-9_]+)\b/gi,type:"n2"},{regex:/[\b\W](-?0b[01][01_]+)\b/gi,type:"n3"},{regex:/[\b\W](-?[\d_]+(?:\.[\d_]+)?(?:e[+-]?\d+)?[ji]?)\b/gi,type:"n0"},ve.brackets]}}]),F),rt=(i(D,Se),Ce(D,[{key:"setupLanguage",value:function(){this.rules=[ve.char,{regex:/r((#+)".*?"\2)/gm,type:"s0"},{regex:/("(?:\\.|\\\s*\n|\\s*\r\n|[^\\"])*")/g,type:"s0"},{regex:/^\s*#.*$/gm,type:"k4"},{regex:/fn\s+([\w]+)\s*(<\w+\s*>)?\(/gm,type:"k0"},{regex:/\b\.?([\w]+)\s*(\(|::)/gm,type:"k1"},{regex:/\b([\w]+)!/gm,type:"k9"},{regex:/\bself\b/gi,type:"k9"},ve.boolean,{regex:/\b(while|loop|in|for|if|else|do|continue|break)\b/g,type:"k1"},{regex:/\b(type|struct|let|enum)\b/g,type:"k2"},{regex:/\b(const)\b/g,type:"k8"},{regex:/\b(yield|where|virtual|use|unsized|unsafe|trait|super|static|return|ref|pure|pub|proc|priv|override|offsetof|mut|move|mod|match|macro|impl|fn|final|extern|crate|box|become|as|alignof|abstract)\b/g,type:"k0"},{regex:/\b(sizeof|typeof)\b/g,type:"k3"},{regex:/\b([0-9_]+\.?[0-9_]+?(e\+[0-9_]+)?)(?:f32|f64)?\b/gim,type:"n0"},{regex:/\b([0-9_]+|0o[0-9_]+|0x[A-F0-9_]+|0b[0-1_]+)(?:u8|i8|u16|i16|u32|i32|u64|i64|isize|usize)?\b/gim,type:"n1"},ve.slashComments,ve.blockComments,{regex:/(?:^|[^\\])\/\/[/!].*$/gm,type:"c2"},{regex:/\/\*[*!][\s\S]*?\*\//gm,type:"c2"},ve.brackets,{regex:/\W(&)\w/g,type:"k3"}]}}]),D),nt=(i(T,Se),Ce(T,[{key:"setupLanguage",value:function(){this.rules=[ve.dqStrings,ve.char,{regex:/s"(?:[^"\\]|\\.)*"/g,type:"s2"},{regex:/`(?:[^`\\]|\\.)*`/g,type:"k7"},{regex:/@[\W\w_][\w]+/g,type:"s9"},{regex:/\b([A-Z]\w*)\b/g,type:"k5"},{regex:/\b(while|try|catch|else|throw|break|if|do|goto|switch|for|match)\b/g,type:"k1"},{regex:/(package|import)(\s+[\w.]+)/gm,type:["k0","k10"]},{regex:/[\b\w\s)](_|:|@|#|<-|←|<:|<%|=|=>|⇒|>:)[\b\w\s]/g,type:"k3"},{regex:/\b(abstract|class|case|extends|final|finally|forSome|implicit|lazy|object|override|private|protected|return|sealed|trait|with|yield)\b/g,type:"k0"},{regex:/\b(def)\s+(\w+)\b/gm,type:["k2","m0"]},{regex:/\b(type)\s+(\w+)\b/gm,type:["k2","k5"]},{regex:/\b(val)\s+(\w+)\b/gm,type:["k2","k7"]},{regex:/\b(var)\s+(\w+)\b/gm,type:["k2","k7"]},{regex:/\b(this|super)\b/g,type:"k9"},{regex:/\b(new)\b/g,type:"k3"},ve.mCalls,ve.fCalls,ve.null,ve.boolean,ve.slashComments,ve.blockComments,ve.docComments,ve.int,ve.floats,ve.bin,ve.brackets]}}]),T),st=(i(R,Pe),Ce(R,[{key:"setupLanguage",value:function(){s(R.prototype.__proto__||Object.getPrototypeOf(R.prototype),"setupLanguage",this).call(this);var e=[ve.slashComments,{regex:/\b([\w-]+)\s*\(/gm,type:"m0"},{regex:/\$[\w-]+\b/g,type:"k7"},{regex:/@[\w-]+\b/g,type:"k9"},{regex:/&/gi,Line truncated
|
||||
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* AKSRT Follow — 前台关注交互
|
||||
*
|
||||
* 监听 [data-aksrt-follow] 按钮点击,切换关注状态。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var API_ROOT = (window.aksrtData && window.aksrtData.apiUrl) || '/wp-json/aksrt/v1';
|
||||
var NONCE = (window.aksrtData && window.aksrtData.restNonce) || '';
|
||||
|
||||
function initFollowButtons() {
|
||||
document.addEventListener('click', function (e) {
|
||||
var btn = e.target.closest('[data-aksrt-follow]');
|
||||
if (!btn) return;
|
||||
e.preventDefault();
|
||||
|
||||
var targetUserId = parseInt(btn.getAttribute('data-aksrt-follow'));
|
||||
if (!targetUserId) return;
|
||||
|
||||
btn.disabled = true;
|
||||
|
||||
fetch(API_ROOT + '/follow/toggle', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-WP-Nonce': NONCE,
|
||||
},
|
||||
body: JSON.stringify({ target_user_id: targetUserId }),
|
||||
})
|
||||
.then(function (res) { return res.json(); })
|
||||
.then(function (result) {
|
||||
if (result.success && result.data) {
|
||||
var isFollowing = result.data.is_following;
|
||||
updateFollowButton(btn, isFollowing, result.data.follower_count);
|
||||
} else {
|
||||
showToast(result.message || '操作失败', 'error');
|
||||
}
|
||||
})
|
||||
.catch(function () {
|
||||
showToast('网络错误,请重试', 'error');
|
||||
})
|
||||
.finally(function () {
|
||||
btn.disabled = false;
|
||||
});
|
||||
});
|
||||
|
||||
// Check initial follow status for all follow buttons
|
||||
document.querySelectorAll('[data-aksrt-follow]').forEach(function (btn) {
|
||||
var targetUserId = parseInt(btn.getAttribute('data-aksrt-follow'));
|
||||
if (!targetUserId) return;
|
||||
|
||||
fetch(API_ROOT + '/follow/status?target_user_id=' + targetUserId, {
|
||||
headers: { 'X-WP-Nonce': NONCE },
|
||||
})
|
||||
.then(function (res) { return res.json(); })
|
||||
.then(function (result) {
|
||||
if (result.success && result.data) {
|
||||
updateFollowButton(btn, result.data.is_following, result.data.follower_count);
|
||||
}
|
||||
})
|
||||
.catch(function () { /* silent */ });
|
||||
});
|
||||
}
|
||||
|
||||
function updateFollowButton(btn, isFollowing, count) {
|
||||
var icon = btn.querySelector('i');
|
||||
var text = btn.querySelector('span');
|
||||
|
||||
if (isFollowing) {
|
||||
btn.classList.add('is-following');
|
||||
if (icon) icon.className = 'fas fa-heart';
|
||||
if (text) text.textContent = '已关注';
|
||||
btn.title = '点击取消关注';
|
||||
} else {
|
||||
btn.classList.remove('is-following');
|
||||
if (icon) icon.className = 'far fa-heart';
|
||||
if (text) text.textContent = '关注';
|
||||
btn.title = '关注该用户';
|
||||
}
|
||||
|
||||
// Update follower count display if exists
|
||||
var countEl = document.querySelector('.aksrt-user-home__stat-value[data-followers]');
|
||||
if (countEl && count !== undefined) {
|
||||
countEl.textContent = count;
|
||||
}
|
||||
}
|
||||
|
||||
function showToast(msg, type) {
|
||||
var toast = document.createElement('div');
|
||||
toast.textContent = msg;
|
||||
toast.style.cssText = 'position:fixed;top:20px;left:50%;transform:translateX(-50%);padding:12px 24px;border-radius:6px;color:#fff;font-size:14px;z-index:10000;transition:opacity 0.3s;';
|
||||
toast.style.background = type === 'error' ? '#e74c3c' : '#27ae60';
|
||||
document.body.appendChild(toast);
|
||||
setTimeout(function () {
|
||||
toast.style.opacity = '0';
|
||||
setTimeout(function () { toast.remove(); }, 300);
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initFollowButtons);
|
||||
} else {
|
||||
initFollowButtons();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* AKSRT Forum Edit — 帖子编辑页交互
|
||||
*
|
||||
* 处理论坛帖子编辑页的表单增强和标签输入。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var form = document.querySelector('.aksrt-forum-edit__form');
|
||||
if (!form) return;
|
||||
|
||||
// 标签输入增强:逗号分隔转标签 chips
|
||||
var tagInput = form.querySelector('#topic_tags');
|
||||
if (tagInput) {
|
||||
tagInput.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 表单提交确认
|
||||
form.addEventListener('submit', function (e) {
|
||||
var title = form.querySelector('#topic_title');
|
||||
var content = form.querySelector('#topic_content');
|
||||
|
||||
if (title && title.value.trim() === '') {
|
||||
e.preventDefault();
|
||||
alert('标题不能为空');
|
||||
title.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
// TinyMCE 检查
|
||||
if (typeof tinyMCE !== 'undefined' && tinyMCE.get('topic_content')) {
|
||||
var editorContent = tinyMCE.get('topic_content').getContent().trim();
|
||||
if (editorContent === '') {
|
||||
e.preventDefault();
|
||||
alert('内容不能为空');
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
})();
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,361 @@
|
||||
/**
|
||||
* AKSRT Front Submit
|
||||
*
|
||||
* Handles front-end post submission, draft save/load,
|
||||
* editor toolbar, cover preview, and form protection.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var i18n = (window.aksrtSubmitData && window.aksrtSubmitData.i18n) || {};
|
||||
var ajaxUrl = (window.aksrtSubmitData && window.aksrtSubmitData.ajaxUrl) || '/wp-admin/admin-ajax.php';
|
||||
var nonce = (window.aksrtSubmitData && window.aksrtSubmitData.nonce) || '';
|
||||
|
||||
var FRONT_SUBMIT = {
|
||||
form: null,
|
||||
isDirty: false,
|
||||
isSubmitting: false,
|
||||
|
||||
init: function () {
|
||||
this.form = document.getElementById('aksrt-submit-form');
|
||||
if (!this.form) return;
|
||||
|
||||
this.bindDirtyTracking();
|
||||
this.bindSubmit();
|
||||
this.bindDraftSave();
|
||||
this.bindDraftDelete();
|
||||
this.bindEditorToolbar();
|
||||
this.bindCoverPreview();
|
||||
this.bindWordCount();
|
||||
this.bindLeaveWarning();
|
||||
},
|
||||
|
||||
/**
|
||||
* Track form changes
|
||||
*/
|
||||
bindDirtyTracking: function () {
|
||||
var self = this;
|
||||
this.form.addEventListener('input', function () {
|
||||
self.isDirty = true;
|
||||
self.form.setAttribute('data-dirty', 'true');
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Leave page warning
|
||||
*/
|
||||
bindLeaveWarning: function () {
|
||||
var self = this;
|
||||
window.addEventListener('beforeunload', function (e) {
|
||||
if (self.isDirty && !self.isSubmitting) {
|
||||
e.preventDefault();
|
||||
e.returnValue = i18n.confirmLeave || '';
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Form submission
|
||||
*/
|
||||
bindSubmit: function () {
|
||||
var self = this;
|
||||
this.form.addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
if (self.isSubmitting) return;
|
||||
|
||||
var submitBtn = document.getElementById('aksrt-submit-btn');
|
||||
var statusInput = document.getElementById('submit-status');
|
||||
statusInput.value = 'pending';
|
||||
|
||||
self.submitForm(submitBtn, 'pending');
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Draft save
|
||||
*/
|
||||
bindDraftSave: function () {
|
||||
var self = this;
|
||||
var draftBtn = document.getElementById('aksrt-save-draft');
|
||||
if (!draftBtn) return;
|
||||
|
||||
draftBtn.addEventListener('click', function () {
|
||||
if (self.isSubmitting) return;
|
||||
var statusInput = document.getElementById('submit-status');
|
||||
statusInput.value = 'draft';
|
||||
self.submitForm(draftBtn, 'draft');
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Submit form via AJAX
|
||||
*/
|
||||
submitForm: function (btn, status) {
|
||||
var self = this;
|
||||
var formData = new FormData(this.form);
|
||||
formData.append('action', 'aksrt_submit_post');
|
||||
formData.append('_nonce', nonce);
|
||||
|
||||
var originalText = btn.innerHTML;
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> ' + (status === 'draft' ? (i18n.saving || '保存中...') : (i18n.submitting || '提交中...'));
|
||||
self.isSubmitting = true;
|
||||
|
||||
fetch(ajaxUrl, {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
credentials: 'same-origin',
|
||||
})
|
||||
.then(function (res) { return res.json(); })
|
||||
.then(function (data) {
|
||||
if (data.success) {
|
||||
self.isDirty = false;
|
||||
self.form.setAttribute('data-dirty', 'false');
|
||||
btn.innerHTML = '<i class="fas fa-check"></i> ' + (data.data && data.data.message ? data.data.message : (status === 'draft' ? (i18n.saved || '草稿已保存') : (i18n.submitted || '投稿已提交')));
|
||||
btn.classList.add('is-success');
|
||||
|
||||
if (status === 'pending' && data.data && data.data.redirect) {
|
||||
setTimeout(function () { window.location.href = data.data.redirect; }, 1500);
|
||||
} else if (status === 'draft') {
|
||||
// Reload to update draft list
|
||||
setTimeout(function () { window.location.reload(); }, 1000);
|
||||
}
|
||||
} else {
|
||||
alert(data.data && data.data.message ? data.data.message : (i18n.error || '操作失败'));
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = originalText;
|
||||
}
|
||||
})
|
||||
.catch(function () {
|
||||
alert(i18n.error || '操作失败,请重试');
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = originalText;
|
||||
})
|
||||
.finally(function () {
|
||||
self.isSubmitting = false;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Draft delete
|
||||
*/
|
||||
bindDraftDelete: function () {
|
||||
document.addEventListener('click', function (e) {
|
||||
var btn = e.target.closest('.aksrt-submit-drafts__delete');
|
||||
if (!btn) return;
|
||||
|
||||
var draftId = btn.getAttribute('data-draft-id');
|
||||
if (!draftId) return;
|
||||
if (!confirm(i18n.confirmDelete || '确定要删除这个草稿吗?')) return;
|
||||
|
||||
var formData = new FormData();
|
||||
formData.append('action', 'aksrt_delete_draft');
|
||||
formData.append('_nonce', nonce);
|
||||
formData.append('draft_id', draftId);
|
||||
|
||||
fetch(ajaxUrl, {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
credentials: 'same-origin',
|
||||
})
|
||||
.then(function (res) { return res.json(); })
|
||||
.then(function (data) {
|
||||
if (data.success) {
|
||||
var item = btn.closest('.aksrt-submit-drafts__item');
|
||||
if (item) item.remove();
|
||||
} else {
|
||||
alert(data.data && data.data.message ? data.data.message : '删除失败');
|
||||
}
|
||||
})
|
||||
.catch(function () { alert('删除失败'); });
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Editor toolbar actions
|
||||
*/
|
||||
bindEditorToolbar: function () {
|
||||
var textarea = document.getElementById('submit-content');
|
||||
if (!textarea) return;
|
||||
|
||||
document.addEventListener('click', function (e) {
|
||||
var btn = e.target.closest('[data-action]');
|
||||
if (!btn) return;
|
||||
|
||||
var action = btn.getAttribute('data-action');
|
||||
var form = btn.closest('.aksrt-submit-form');
|
||||
if (!form) return;
|
||||
var ta = form.querySelector('textarea');
|
||||
if (!ta) return;
|
||||
|
||||
switch (action) {
|
||||
case 'bold':
|
||||
FRONT_SUBMIT.wrapSelection(ta, '**');
|
||||
break;
|
||||
case 'italic':
|
||||
FRONT_SUBMIT.wrapSelection(ta, '*');
|
||||
break;
|
||||
case 'code':
|
||||
var sel = ta.value.substring(ta.selectionStart, ta.selectionEnd);
|
||||
if (sel.indexOf('\n') >= 0) {
|
||||
FRONT_SUBMIT.insertAtCursor(ta, '```\n', '\n```');
|
||||
} else {
|
||||
FRONT_SUBMIT.wrapSelection(ta, '`');
|
||||
}
|
||||
break;
|
||||
case 'link':
|
||||
FRONT_SUBMIT.askUrl(btn, '链接地址', function (url) {
|
||||
if (url) {
|
||||
var linkText = ta.value.substring(ta.selectionStart, ta.selectionEnd) || '链接文字';
|
||||
FRONT_SUBMIT.insertAtCursor(ta, '[' + linkText + '](' + url + ')');
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'image':
|
||||
FRONT_SUBMIT.askUrl(btn, '图片地址', function (url) {
|
||||
if (url) {
|
||||
FRONT_SUBMIT.insertAtCursor(ta, '');
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'quote':
|
||||
FRONT_SUBMIT.insertAtCursor(ta, '> ', '\n');
|
||||
break;
|
||||
case 'heading':
|
||||
FRONT_SUBMIT.insertAtCursor(ta, '## ', '\n');
|
||||
break;
|
||||
case 'list':
|
||||
FRONT_SUBMIT.insertAtCursor(ta, '- ', '\n');
|
||||
break;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
askUrl: function (anchor, placeholder, callback) {
|
||||
var existing = document.querySelector('.aksrt-inline-url-input');
|
||||
if (existing) existing.remove();
|
||||
|
||||
var input = document.createElement('input');
|
||||
input.type = 'url';
|
||||
input.className = 'aksrt-inline-url-input';
|
||||
input.placeholder = placeholder || 'https://';
|
||||
input.value = 'https://';
|
||||
input.style.cssText = 'display:block;width:100%;max-width:320px;margin:4px 0;padding:6px 10px;border:1px solid #dce3ec;border-radius:8px;font-size:13px;';
|
||||
|
||||
var parent = anchor.parentElement;
|
||||
parent.insertBefore(input, anchor.nextSibling);
|
||||
input.focus();
|
||||
input.select();
|
||||
|
||||
function done() {
|
||||
var val = input.value.trim();
|
||||
input.remove();
|
||||
callback(val);
|
||||
}
|
||||
|
||||
input.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'Enter') { e.preventDefault(); done(); }
|
||||
if (e.key === 'Escape') { input.remove(); callback(''); }
|
||||
});
|
||||
input.addEventListener('blur', function () { done(); });
|
||||
},
|
||||
|
||||
insertAtCursor: function (textarea, before, after) {
|
||||
var start = textarea.selectionStart;
|
||||
var end = textarea.selectionEnd;
|
||||
var text = textarea.value;
|
||||
var selected = text.substring(start, end);
|
||||
var replacement = before + (selected || '') + (after || '');
|
||||
textarea.value = text.substring(0, start) + replacement + text.substring(end);
|
||||
textarea.focus();
|
||||
var newPos = start + before.length + selected.length;
|
||||
textarea.setSelectionRange(newPos, newPos);
|
||||
textarea.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
},
|
||||
|
||||
wrapSelection: function (textarea, marker) {
|
||||
this.insertAtCursor(textarea, marker, marker);
|
||||
},
|
||||
|
||||
/**
|
||||
* Cover image preview
|
||||
*/
|
||||
bindCoverPreview: function () {
|
||||
var thumbInput = document.getElementById('submit-thumbnail');
|
||||
var previewWrap = document.getElementById('cover-preview');
|
||||
var previewImg = document.getElementById('cover-preview-img');
|
||||
var removeBtn = document.getElementById('cover-remove');
|
||||
|
||||
if (!thumbInput || !previewWrap || !previewImg) return;
|
||||
|
||||
thumbInput.addEventListener('change', function () {
|
||||
var url = thumbInput.value.trim();
|
||||
if (url && /^https?:\/\//.test(url)) {
|
||||
previewImg.src = url;
|
||||
previewWrap.style.display = 'flex';
|
||||
previewImg.onerror = function () { previewWrap.style.display = 'none'; };
|
||||
} else {
|
||||
previewWrap.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
if (removeBtn) {
|
||||
removeBtn.addEventListener('click', function () {
|
||||
thumbInput.value = '';
|
||||
previewWrap.style.display = 'none';
|
||||
thumbInput.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
});
|
||||
}
|
||||
|
||||
// Media library picker
|
||||
var pickBtn = document.getElementById('aksrt-pick-cover');
|
||||
if (pickBtn && window.wp && window.wp.media) {
|
||||
pickBtn.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
var mediaFrame = wp.media({
|
||||
title: '选择封面图',
|
||||
button: { text: '使用此图片' },
|
||||
multiple: false,
|
||||
library: { type: 'image' },
|
||||
});
|
||||
mediaFrame.on('select', function () {
|
||||
var attachment = mediaFrame.state().get('selection').first().toJSON();
|
||||
thumbInput.value = attachment.url;
|
||||
previewImg.src = attachment.url;
|
||||
previewWrap.style.display = 'flex';
|
||||
thumbInput.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
});
|
||||
mediaFrame.open();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Word count
|
||||
*/
|
||||
bindWordCount: function () {
|
||||
var contentEl = document.getElementById('submit-content');
|
||||
var countEl = document.getElementById('submit-word-count');
|
||||
if (!contentEl || !countEl) return;
|
||||
|
||||
var updateCount = function () {
|
||||
var text = contentEl.value.replace(/<[^>]*>/g, '').trim();
|
||||
var chars = text.length;
|
||||
var words = text ? text.split(/\s+/).length : 0;
|
||||
countEl.textContent = chars + ' 字 · ~' + words + ' 词';
|
||||
};
|
||||
|
||||
contentEl.addEventListener('input', updateCount);
|
||||
updateCount();
|
||||
},
|
||||
};
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', function () { FRONT_SUBMIT.init(); });
|
||||
} else {
|
||||
FRONT_SUBMIT.init();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* AKSRT Frontend Translate — 前端即时翻译
|
||||
*
|
||||
* 渐进增强,默认关。通过 Settings 启用后,
|
||||
* 在语言切换 Widget 中添加"翻译本页"按钮,
|
||||
* 使用浏览器原生翻译或自定义翻译 API。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var config = (window.aksrtData && window.aksrtData.translate) || {};
|
||||
if (!config.enabled) return;
|
||||
|
||||
/**
|
||||
* 触发浏览器原生翻译(Chrome/Edge 内置)
|
||||
*/
|
||||
function triggerBrowserTranslate(targetLang) {
|
||||
// Chrome/Edge 有内置翻译功能
|
||||
if (document.querySelector('.goog-te-banner-frame') || document.querySelector('#goog-gt-tt')) {
|
||||
return; // 已经在翻译中
|
||||
}
|
||||
|
||||
// 尝试使用 Google Translate Element
|
||||
if (window.google && window.google.translate) {
|
||||
new google.translate.TranslateElement({
|
||||
pageLanguage: config.sourceLang || 'zh-CN',
|
||||
includedLanguages: targetLang || '',
|
||||
layout: google.translate.TranslateElement.InlineLayout.SIMPLE,
|
||||
autoDisplay: false,
|
||||
}, 'aksrt-translate-container');
|
||||
return;
|
||||
}
|
||||
|
||||
// 动态加载 Google Translate
|
||||
var script = document.createElement('script');
|
||||
script.src = '//translate.google.com/translate_a/element.js?cb=aksrtTranslateInit';
|
||||
document.head.appendChild(script);
|
||||
|
||||
window.aksrtTranslateInit = function () {
|
||||
if (!window.google || !window.google.translate) return;
|
||||
new google.translate.TranslateElement({
|
||||
pageLanguage: config.sourceLang || 'zh-CN',
|
||||
includedLanguages: targetLang || config.targetLang || 'en',
|
||||
layout: google.translate.TranslateElement.InlineLayout.SIMPLE,
|
||||
autoDisplay: false,
|
||||
}, 'aksrt-translate-container');
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建翻译容器和按钮
|
||||
*/
|
||||
function init() {
|
||||
// 检查是否有语言切换 Widget
|
||||
var langWidget = document.querySelector('.aksrt-lang-switch, [data-aksrt-lang-switch]');
|
||||
if (!langWidget && !config.showButton) return;
|
||||
|
||||
// 创建隐藏的翻译容器
|
||||
var container = document.createElement('div');
|
||||
container.id = 'aksrt-translate-container';
|
||||
container.style.cssText = 'position:fixed;top:-9999px;left:-9999px;visibility:hidden;';
|
||||
document.body.appendChild(container);
|
||||
|
||||
// 如果配置了显示按钮,在语言切换 Widget 旁添加
|
||||
if (config.showButton && langWidget) {
|
||||
var btn = document.createElement('button');
|
||||
btn.type = 'button';
|
||||
btn.className = 'aksrt-translate-btn';
|
||||
btn.innerHTML = '<i class="fas fa-language"></i> 翻译本页';
|
||||
btn.addEventListener('click', function () {
|
||||
triggerBrowserTranslate(config.targetLang || 'en');
|
||||
btn.textContent = '翻译中...';
|
||||
btn.disabled = true;
|
||||
});
|
||||
langWidget.appendChild(btn);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
})();
|
||||
@@ -0,0 +1,737 @@
|
||||
/**
|
||||
* AKSRT Gutenberg Blocks
|
||||
*
|
||||
* Custom Gutenberg block extensions for the AKSRT theme.
|
||||
* Provides 9 generic content blocks adapted from zibll.
|
||||
*
|
||||
* Blocks: tabs, tab, enlighter, quote, alert, buttons, collapse, feature, iframe
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
if (!window.wp || !window.wp.blocks) return;
|
||||
|
||||
var el = wp.element.createElement;
|
||||
var Fragment = wp.element.Fragment;
|
||||
var registerBlockType = wp.blocks.registerBlockType;
|
||||
var InspectorControls = wp.blockEditor ? wp.blockEditor.InspectorControls : (wp.editor ? wp.editor.InspectorControls : null);
|
||||
var InnerBlocks = wp.blockEditor ? wp.blockEditor.InnerBlocks : (wp.editor ? wp.editor.InnerBlocks : null);
|
||||
var RichText = wp.blockEditor ? wp.blockEditor.RichText : (wp.editor ? wp.editor.RichText : null);
|
||||
var ColorPicker = wp.components.ColorPicker;
|
||||
var PanelBody = wp.components.PanelBody;
|
||||
var SelectControl = wp.components.SelectControl;
|
||||
var TextControl = wp.components.TextControl;
|
||||
var ToggleControl = wp.components.ToggleControl;
|
||||
var RangeControl = wp.components.RangeControl;
|
||||
|
||||
if (!registerBlockType || !el) return;
|
||||
|
||||
// ── Helper: create element shorthand ──
|
||||
function h(tag, props, children) {
|
||||
var args = [tag, props];
|
||||
if (children !== undefined) {
|
||||
if (Array.isArray(children)) {
|
||||
args = args.concat(children);
|
||||
} else {
|
||||
args.push(children);
|
||||
}
|
||||
}
|
||||
return el.apply(null, args);
|
||||
}
|
||||
|
||||
// ── Helper: InspectorControls wrapper ──
|
||||
function withInspector(title, children) {
|
||||
if (!InspectorControls) return null;
|
||||
return h(InspectorControls, { key: 'inspector' },
|
||||
h(PanelBody, { title: title }, children)
|
||||
);
|
||||
}
|
||||
|
||||
var CATEGORY = 'aksrt-blocks';
|
||||
var BLOCK_ICON = h('svg', { viewBox: '0 0 24 24', width: 20, height: 20 },
|
||||
h('path', { d: 'M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5', fill: 'none', stroke: 'currentColor', strokeWidth: 2 })
|
||||
);
|
||||
|
||||
// ================================================================
|
||||
// 1. Tabs Block
|
||||
// ================================================================
|
||||
|
||||
registerBlockType('aksrt/tabs', {
|
||||
title: '标签页',
|
||||
icon: BLOCK_ICON,
|
||||
category: CATEGORY,
|
||||
description: '可切换的标签页内容容器',
|
||||
attributes: {
|
||||
style: { type: 'string', default: 'default' },
|
||||
},
|
||||
edit: function (props) {
|
||||
return h(Fragment, null,
|
||||
withInspector('标签页设置',
|
||||
h(SelectControl, {
|
||||
label: '样式',
|
||||
value: props.attributes.style,
|
||||
options: [
|
||||
{ label: '默认', value: 'default' },
|
||||
{ label: '线条', value: 'line' },
|
||||
{ label: '卡片', value: 'card' },
|
||||
],
|
||||
onChange: function (v) { props.setAttributes({ style: v }); }
|
||||
})
|
||||
),
|
||||
h('div', { className: 'aksrt-block-tabs aksrt-block-tabs--' + props.attributes.style },
|
||||
h(InnerBlocks, {
|
||||
allowedBlocks: ['aksrt/tab'],
|
||||
template: [['aksrt/tab', { title: '标签 1' }], ['aksrt/tab', { title: '标签 2' }]],
|
||||
})
|
||||
)
|
||||
);
|
||||
},
|
||||
save: function (props) {
|
||||
return h('div', { className: 'aksrt-block-tabs aksrt-block-tabs--' + props.attributes.style },
|
||||
h(InnerBlocks.Content, null)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
registerBlockType('aksrt/tab', {
|
||||
title: '标签页项',
|
||||
icon: BLOCK_ICON,
|
||||
category: CATEGORY,
|
||||
parent: ['aksrt/tabs'],
|
||||
attributes: {
|
||||
title: { type: 'string', default: '标签' },
|
||||
},
|
||||
edit: function (props) {
|
||||
return h(Fragment, null,
|
||||
h(TextControl, {
|
||||
label: '标签标题',
|
||||
value: props.attributes.title,
|
||||
onChange: function (v) { props.setAttributes({ title: v }); }
|
||||
}),
|
||||
h('div', { className: 'aksrt-block-tab__content' },
|
||||
h(InnerBlocks, null)
|
||||
)
|
||||
);
|
||||
},
|
||||
save: function (props) {
|
||||
return h('div', { className: 'aksrt-block-tab', 'data-title': props.attributes.title },
|
||||
h(InnerBlocks.Content, null)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
// ================================================================
|
||||
// 2. EnlighterJS Code Block
|
||||
// ================================================================
|
||||
|
||||
registerBlockType('aksrt/enlighter', {
|
||||
title: '代码高亮',
|
||||
icon: 'editor-code',
|
||||
category: CATEGORY,
|
||||
description: '带语法高亮的代码块(EnlighterJS)',
|
||||
attributes: {
|
||||
code: { type: 'string', default: '' },
|
||||
language: { type: 'string', default: 'javascript' },
|
||||
theme: { type: 'string', default: '' },
|
||||
linenumbers: { type: 'boolean', default: true },
|
||||
},
|
||||
edit: function (props) {
|
||||
return h(Fragment, null,
|
||||
withInspector('代码块设置',
|
||||
h(SelectControl, {
|
||||
label: '语言',
|
||||
value: props.attributes.language,
|
||||
options: [
|
||||
{ label: 'JavaScript', value: 'javascript' },
|
||||
{ label: 'TypeScript', value: 'typescript' },
|
||||
{ label: 'PHP', value: 'php' },
|
||||
{ label: 'Python', value: 'python' },
|
||||
{ label: 'Java', value: 'java' },
|
||||
{ label: 'C/C++', value: 'cpp' },
|
||||
{ label: 'C#', value: 'csharp' },
|
||||
{ label: 'Go', value: 'go' },
|
||||
{ label: 'Rust', value: 'rust' },
|
||||
{ label: 'Ruby', value: 'ruby' },
|
||||
{ label: 'Swift', value: 'swift' },
|
||||
{ label: 'Kotlin', value: 'kotlin' },
|
||||
{ label: 'HTML', value: 'html' },
|
||||
{ label: 'CSS/SCSS', value: 'css' },
|
||||
{ label: 'SQL', value: 'sql' },
|
||||
{ label: 'Shell/Bash', value: 'shell' },
|
||||
{ label: 'JSON', value: 'json' },
|
||||
{ label: 'YAML', value: 'yaml' },
|
||||
{ label: 'Markdown', value: 'markdown' },
|
||||
{ label: 'Docker', value: 'dockerfile' },
|
||||
{ label: 'Diff', value: 'diff' },
|
||||
{ label: 'XML', value: 'xml' },
|
||||
],
|
||||
onChange: function (v) { props.setAttributes({ language: v }); }
|
||||
}),
|
||||
h(ToggleControl, {
|
||||
label: '显示行号',
|
||||
checked: props.attributes.linenumbers,
|
||||
onChange: function (v) { props.setAttributes({ linenumbers: v }); }
|
||||
})
|
||||
),
|
||||
h('div', { className: 'aksrt-block-enlighter' },
|
||||
h('div', { className: 'aksrt-block-enlighter__header' },
|
||||
h('span', { className: 'aksrt-block-enlighter__lang' }, props.attributes.language)
|
||||
),
|
||||
h('textarea', {
|
||||
className: 'aksrt-block-enlighter__code',
|
||||
value: props.attributes.code,
|
||||
onChange: function (e) { props.setAttributes({ code: e.target.value }); },
|
||||
placeholder: '在此输入代码...',
|
||||
rows: 10,
|
||||
spellCheck: false,
|
||||
})
|
||||
)
|
||||
);
|
||||
},
|
||||
save: function (props) {
|
||||
var attrs = {
|
||||
className: 'gl',
|
||||
'data-enlighter-language': props.attributes.language,
|
||||
};
|
||||
if (props.attributes.theme) attrs['data-enlighter-theme'] = props.attributes.theme;
|
||||
if (!props.attributes.linenumbers) attrs['data-enlighter-linenumbers'] = 'false';
|
||||
|
||||
return h('pre', { className: 'enlighter-pre' },
|
||||
h('code', attrs, props.attributes.code)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
// ================================================================
|
||||
// 3. Quote Block
|
||||
// ================================================================
|
||||
|
||||
registerBlockType('aksrt/quote-styled', {
|
||||
title: '样式引用',
|
||||
icon: 'editor-quote',
|
||||
category: CATEGORY,
|
||||
description: '带颜色样式的引用块',
|
||||
attributes: {
|
||||
content: { type: 'string', default: '' },
|
||||
style: { type: 'string', default: 'gray' },
|
||||
cite: { type: 'string', default: '' },
|
||||
},
|
||||
edit: function (props) {
|
||||
return h(Fragment, null,
|
||||
withInspector('引用设置',
|
||||
h(SelectControl, {
|
||||
label: '样式',
|
||||
value: props.attributes.style,
|
||||
options: [
|
||||
{ label: '灰色', value: 'gray' },
|
||||
{ label: '蓝色', value: 'blue' },
|
||||
{ label: '绿色', value: 'green' },
|
||||
{ label: '红色', value: 'red' },
|
||||
{ label: '黄色', value: 'yellow' },
|
||||
],
|
||||
onChange: function (v) { props.setAttributes({ style: v }); }
|
||||
}),
|
||||
h(TextControl, {
|
||||
label: '来源',
|
||||
value: props.attributes.cite,
|
||||
onChange: function (v) { props.setAttributes({ cite: v }); }
|
||||
})
|
||||
),
|
||||
h('blockquote', { className: 'aksrt-block-quote aksrt-block-quote--' + props.attributes.style },
|
||||
h(RichText, {
|
||||
tagName: 'p',
|
||||
value: props.attributes.content,
|
||||
onChange: function (v) { props.setAttributes({ content: v }); },
|
||||
placeholder: '输入引用内容...',
|
||||
}),
|
||||
props.attributes.cite ? h('cite', null, props.attributes.cite) : null
|
||||
)
|
||||
);
|
||||
},
|
||||
save: function (props) {
|
||||
return h('blockquote', { className: 'aksrt-block-quote aksrt-block-quote--' + props.attributes.style },
|
||||
h(RichText.Content, { tagName: 'p', value: props.attributes.content }),
|
||||
props.attributes.cite ? h('cite', null, props.attributes.cite) : null
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
// ================================================================
|
||||
// 4. Alert Block
|
||||
// ================================================================
|
||||
|
||||
registerBlockType('aksrt/alert', {
|
||||
title: '提示框',
|
||||
icon: 'warning',
|
||||
category: CATEGORY,
|
||||
description: '通知/警告/成功/信息提示框',
|
||||
attributes: {
|
||||
content: { type: 'string', default: '' },
|
||||
type: { type: 'string', default: 'info' },
|
||||
dismissible: { type: 'boolean', default: false },
|
||||
},
|
||||
edit: function (props) {
|
||||
return h(Fragment, null,
|
||||
withInspector('提示框设置',
|
||||
h(SelectControl, {
|
||||
label: '类型',
|
||||
value: props.attributes.type,
|
||||
options: [
|
||||
{ label: '信息', value: 'info' },
|
||||
{ label: '成功', value: 'success' },
|
||||
{ label: '警告', value: 'warning' },
|
||||
{ label: '错误', value: 'error' },
|
||||
],
|
||||
onChange: function (v) { props.setAttributes({ type: v }); }
|
||||
}),
|
||||
h(ToggleControl, {
|
||||
label: '可关闭',
|
||||
checked: props.attributes.dismissible,
|
||||
onChange: function (v) { props.setAttributes({ dismissible: v }); }
|
||||
})
|
||||
),
|
||||
h('div', {
|
||||
className: 'aksrt-block-alert aksrt-block-alert--' + props.attributes.type +
|
||||
(props.attributes.dismissible ? ' aksrt-block-alert--dismissible' : '')
|
||||
},
|
||||
h(RichText, {
|
||||
tagName: 'p',
|
||||
value: props.attributes.content,
|
||||
onChange: function (v) { props.setAttributes({ content: v }); },
|
||||
placeholder: '输入提示内容...',
|
||||
})
|
||||
)
|
||||
);
|
||||
},
|
||||
save: function (props) {
|
||||
var cls = 'aksrt-block-alert aksrt-block-alert--' + props.attributes.type;
|
||||
if (props.attributes.dismissible) cls += ' aksrt-block-alert--dismissible';
|
||||
return h('div', { className: cls, role: 'alert' },
|
||||
h(RichText.Content, { tagName: 'p', value: props.attributes.content }),
|
||||
props.attributes.dismissible ? h('button', { type: 'button', className: 'aksrt-block-alert__close', 'aria-label': '关闭' }, '×') : null
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
// ================================================================
|
||||
// 5. Buttons Block
|
||||
// ================================================================
|
||||
|
||||
registerBlockType('aksrt/buttons', {
|
||||
title: '按钮组',
|
||||
icon: 'button',
|
||||
category: CATEGORY,
|
||||
description: '多个按钮组合',
|
||||
attributes: {
|
||||
align: { type: 'string', default: 'left' },
|
||||
},
|
||||
edit: function (props) {
|
||||
return h(Fragment, null,
|
||||
withInspector('按钮组设置',
|
||||
h(SelectControl, {
|
||||
label: '对齐',
|
||||
value: props.attributes.align,
|
||||
options: [
|
||||
{ label: '左对齐', value: 'left' },
|
||||
{ label: '居中', value: 'center' },
|
||||
{ label: '右对齐', value: 'right' },
|
||||
],
|
||||
onChange: function (v) { props.setAttributes({ align: v }); }
|
||||
})
|
||||
),
|
||||
h('div', { className: 'aksrt-block-buttons aksrt-block-buttons--' + props.attributes.align },
|
||||
h(InnerBlocks, {
|
||||
allowedBlocks: ['aksrt/button'],
|
||||
template: [['aksrt/button', { text: '按钮', style: 'primary' }]],
|
||||
})
|
||||
)
|
||||
);
|
||||
},
|
||||
save: function (props) {
|
||||
return h('div', { className: 'aksrt-block-buttons aksrt-block-buttons--' + props.attributes.align },
|
||||
h(InnerBlocks.Content, null)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
registerBlockType('aksrt/button', {
|
||||
title: '按钮',
|
||||
icon: 'button',
|
||||
category: CATEGORY,
|
||||
parent: ['aksrt/buttons'],
|
||||
attributes: {
|
||||
text: { type: 'string', default: '按钮' },
|
||||
url: { type: 'string', default: '' },
|
||||
style: { type: 'string', default: 'primary' },
|
||||
size: { type: 'string', default: 'md' },
|
||||
newTab: { type: 'boolean', default: false },
|
||||
},
|
||||
edit: function (props) {
|
||||
return h(Fragment, null,
|
||||
withInspector('按钮设置',
|
||||
h(TextControl, {
|
||||
label: '链接',
|
||||
value: props.attributes.url,
|
||||
onChange: function (v) { props.setAttributes({ url: v }); }
|
||||
}),
|
||||
h(SelectControl, {
|
||||
label: '样式',
|
||||
value: props.attributes.style,
|
||||
options: [
|
||||
{ label: '主要', value: 'primary' },
|
||||
{ label: '次要', value: 'secondary' },
|
||||
{ label: '轮廓', value: 'outline' },
|
||||
{ label: '幽灵', value: 'ghost' },
|
||||
],
|
||||
onChange: function (v) { props.setAttributes({ style: v }); }
|
||||
}),
|
||||
h(SelectControl, {
|
||||
label: '大小',
|
||||
value: props.attributes.size,
|
||||
options: [
|
||||
{ label: '小', value: 'sm' },
|
||||
{ label: '中', value: 'md' },
|
||||
{ label: '大', value: 'lg' },
|
||||
],
|
||||
onChange: function (v) { props.setAttributes({ size: v }); }
|
||||
}),
|
||||
h(ToggleControl, {
|
||||
label: '新窗口打开',
|
||||
checked: props.attributes.newTab,
|
||||
onChange: function (v) { props.setAttributes({ newTab: v }); }
|
||||
})
|
||||
),
|
||||
h(RichText, {
|
||||
tagName: 'span',
|
||||
className: 'aksrt-block-btn aksrt-block-btn--' + props.attributes.style + ' aksrt-block-btn--' + props.attributes.size,
|
||||
value: props.attributes.text,
|
||||
onChange: function (v) { props.setAttributes({ text: v }); },
|
||||
placeholder: '按钮文字...',
|
||||
withoutInteractiveFormatting: true,
|
||||
})
|
||||
);
|
||||
},
|
||||
save: function (props) {
|
||||
var linkProps = {
|
||||
className: 'aksrt-block-btn aksrt-block-btn--' + props.attributes.style + ' aksrt-block-btn--' + props.attributes.size,
|
||||
};
|
||||
if (props.attributes.url) {
|
||||
linkProps.href = props.attributes.url;
|
||||
if (props.attributes.newTab) {
|
||||
linkProps.target = '_blank';
|
||||
linkProps.rel = 'noopener noreferrer';
|
||||
}
|
||||
return h('a', linkProps, props.attributes.text);
|
||||
}
|
||||
return h('span', linkProps, props.attributes.text);
|
||||
},
|
||||
});
|
||||
|
||||
// ================================================================
|
||||
// 6. Collapse Block
|
||||
// ================================================================
|
||||
|
||||
registerBlockType('aksrt/collapse', {
|
||||
title: '折叠面板',
|
||||
icon: 'arrow-down',
|
||||
category: CATEGORY,
|
||||
description: '可展开/收起的内容面板',
|
||||
attributes: {
|
||||
title: { type: 'string', default: '点击展开' },
|
||||
open: { type: 'boolean', default: false },
|
||||
},
|
||||
edit: function (props) {
|
||||
return h(Fragment, null,
|
||||
withInspector('折叠面板设置',
|
||||
h(ToggleControl, {
|
||||
label: '默认展开',
|
||||
checked: props.attributes.open,
|
||||
onChange: function (v) { props.setAttributes({ open: v }); }
|
||||
})
|
||||
),
|
||||
h('div', { className: 'aksrt-block-collapse' },
|
||||
h('div', { className: 'aksrt-block-collapse__header' },
|
||||
h(RichText, {
|
||||
tagName: 'span',
|
||||
className: 'aksrt-block-collapse__title',
|
||||
value: props.attributes.title,
|
||||
onChange: function (v) { props.setAttributes({ title: v }); },
|
||||
placeholder: '面板标题...',
|
||||
}),
|
||||
h('span', { className: 'aksrt-block-collapse__arrow' }, '▼')
|
||||
),
|
||||
h('div', { className: 'aksrt-block-collapse__body' },
|
||||
h(InnerBlocks, null)
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
save: function (props) {
|
||||
return h('details', {
|
||||
className: 'aksrt-block-collapse',
|
||||
open: props.attributes.open ? true : undefined,
|
||||
},
|
||||
h('summary', { className: 'aksrt-block-collapse__header' },
|
||||
h('span', { className: 'aksrt-block-collapse__title' }, props.attributes.title)
|
||||
),
|
||||
h('div', { className: 'aksrt-block-collapse__body' },
|
||||
h(InnerBlocks.Content, null)
|
||||
)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
// ================================================================
|
||||
// 7. Feature Grid Block
|
||||
// ================================================================
|
||||
|
||||
registerBlockType('aksrt/feature', {
|
||||
title: '特性网格',
|
||||
icon: 'grid-view',
|
||||
category: CATEGORY,
|
||||
description: '图标+标题+描述的特性展示网格',
|
||||
attributes: {
|
||||
columns: { type: 'number', default: 3 },
|
||||
},
|
||||
edit: function (props) {
|
||||
return h(Fragment, null,
|
||||
withInspector('特性网格设置',
|
||||
h(RangeControl, {
|
||||
label: '列数',
|
||||
value: props.attributes.columns,
|
||||
min: 2,
|
||||
max: 4,
|
||||
onChange: function (v) { props.setAttributes({ columns: v }); }
|
||||
})
|
||||
),
|
||||
h('div', { className: 'aksrt-block-feature aksrt-block-feature--cols-' + props.attributes.columns },
|
||||
h(InnerBlocks, {
|
||||
allowedBlocks: ['aksrt/feature-item'],
|
||||
template: [
|
||||
['aksrt/feature-item', { icon: 'fas fa-star', title: '特性一', desc: '特性描述' }],
|
||||
['aksrt/feature-item', { icon: 'fas fa-heart', title: '特性二', desc: '特性描述' }],
|
||||
['aksrt/feature-item', { icon: 'fas fa-bolt', title: '特性三', desc: '特性描述' }],
|
||||
],
|
||||
})
|
||||
)
|
||||
);
|
||||
},
|
||||
save: function (props) {
|
||||
return h('div', { className: 'aksrt-block-feature aksrt-block-feature--cols-' + props.attributes.columns },
|
||||
h(InnerBlocks.Content, null)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
registerBlockType('aksrt/feature-item', {
|
||||
title: '特性项',
|
||||
icon: 'star-filled',
|
||||
category: CATEGORY,
|
||||
parent: ['aksrt/feature'],
|
||||
attributes: {
|
||||
icon: { type: 'string', default: 'fas fa-star' },
|
||||
title: { type: 'string', default: '' },
|
||||
desc: { type: 'string', default: '' },
|
||||
},
|
||||
edit: function (props) {
|
||||
return h('div', { className: 'aksrt-block-feature__item' },
|
||||
h(TextControl, {
|
||||
label: '图标类名',
|
||||
value: props.attributes.icon,
|
||||
onChange: function (v) { props.setAttributes({ icon: v }); }
|
||||
}),
|
||||
h('i', { className: props.attributes.icon + ' aksrt-block-feature__icon' }),
|
||||
h(RichText, {
|
||||
tagName: 'h3',
|
||||
className: 'aksrt-block-feature__title',
|
||||
value: props.attributes.title,
|
||||
onChange: function (v) { props.setAttributes({ title: v }); },
|
||||
placeholder: '标题...',
|
||||
}),
|
||||
h(RichText, {
|
||||
tagName: 'p',
|
||||
className: 'aksrt-block-feature__desc',
|
||||
value: props.attributes.desc,
|
||||
onChange: function (v) { props.setAttributes({ desc: v }); },
|
||||
placeholder: '描述...',
|
||||
})
|
||||
);
|
||||
},
|
||||
save: function (props) {
|
||||
return h('div', { className: 'aksrt-block-feature__item' },
|
||||
h('i', { className: props.attributes.icon + ' aksrt-block-feature__icon' }),
|
||||
h('h3', { className: 'aksrt-block-feature__title' }, props.attributes.title),
|
||||
h('p', { className: 'aksrt-block-feature__desc' }, props.attributes.desc)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
// ================================================================
|
||||
// 8. Responsive Iframe Block
|
||||
// ================================================================
|
||||
|
||||
registerBlockType('aksrt/iframe', {
|
||||
title: '响应式嵌入',
|
||||
icon: 'video-alt3',
|
||||
category: CATEGORY,
|
||||
description: '响应式 iframe 嵌入(视频、地图等)',
|
||||
attributes: {
|
||||
src: { type: 'string', default: '' },
|
||||
ratio: { type: 'string', default: '16:9' },
|
||||
title: { type: 'string', default: '' },
|
||||
},
|
||||
edit: function (props) {
|
||||
return h(Fragment, null,
|
||||
withInspector('嵌入设置',
|
||||
h(TextControl, {
|
||||
label: 'URL',
|
||||
value: props.attributes.src,
|
||||
onChange: function (v) { props.setAttributes({ src: v }); }
|
||||
}),
|
||||
h(SelectControl, {
|
||||
label: '宽高比',
|
||||
value: props.attributes.ratio,
|
||||
options: [
|
||||
{ label: '16:9', value: '16:9' },
|
||||
{ label: '4:3', value: '4:3' },
|
||||
{ label: '1:1', value: '1:1' },
|
||||
{ label: '自适应', value: 'auto' },
|
||||
],
|
||||
onChange: function (v) { props.setAttributes({ ratio: v }); }
|
||||
}),
|
||||
h(TextControl, {
|
||||
label: '标题',
|
||||
value: props.attributes.title,
|
||||
onChange: function (v) { props.setAttributes({ title: v }); }
|
||||
})
|
||||
),
|
||||
h('div', { className: 'aksrt-block-iframe aksrt-block-iframe--' + props.attributes.ratio.replace(':', '-') },
|
||||
props.attributes.src
|
||||
? h('iframe', { src: props.attributes.src, title: props.attributes.title || '嵌入内容', allowfullscreen: true })
|
||||
: h('div', { className: 'aksrt-block-iframe__placeholder' }, '请输入嵌入 URL')
|
||||
)
|
||||
);
|
||||
},
|
||||
save: function (props) {
|
||||
return h('div', { className: 'aksrt-block-iframe aksrt-block-iframe--' + props.attributes.ratio.replace(':', '-') },
|
||||
h('iframe', {
|
||||
src: props.attributes.src,
|
||||
title: props.attributes.title || '嵌入内容',
|
||||
allowfullscreen: true,
|
||||
loading: 'lazy',
|
||||
})
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
// ── Register block category ──
|
||||
|
||||
if (window.wp.hooks && window.wp.hooks.addFilter) {
|
||||
wp.hooks.addFilter('blocks.getBlockCategories', 'aksrt/block-categories', function (categories) {
|
||||
var hasAksrt = categories.some(function (c) { return c.slug === CATEGORY; });
|
||||
if (hasAksrt) return categories;
|
||||
return categories.concat([{
|
||||
slug: CATEGORY,
|
||||
title: 'AKSRT',
|
||||
icon: BLOCK_ICON,
|
||||
}]);
|
||||
});
|
||||
}
|
||||
|
||||
// ── Carousel Block (Gallery → Swiper) ──
|
||||
if (MediaUpload && InnerBlocks) {
|
||||
registerBlockType('aksrt/carousel', {
|
||||
title: '轮播图',
|
||||
icon: 'images-alt2',
|
||||
category: CATEGORY,
|
||||
description: '图片轮播/幻灯片(基于 Swiper)',
|
||||
attributes: {
|
||||
images: { type: 'array', default: [] },
|
||||
autoplay: { type: 'boolean', default: true },
|
||||
delay: { type: 'number', default: 3000 },
|
||||
effect: { type: 'string', default: 'slide' },
|
||||
},
|
||||
edit: function (props) {
|
||||
var attrs = props.attributes;
|
||||
var setAttributes = props.setAttributes;
|
||||
|
||||
var onSelectImages = function (media) {
|
||||
setAttributes({
|
||||
images: media.map(function (m) {
|
||||
return { url: m.url, alt: m.alt || '', id: m.id };
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
var inspector = h(InspectorControls, { key: 'insp' },
|
||||
h(PanelBody, { title: '轮播设置' },
|
||||
h(ToggleControl, {
|
||||
label: '自动播放',
|
||||
checked: attrs.autoplay,
|
||||
onChange: function (v) { setAttributes({ autoplay: v }); },
|
||||
}),
|
||||
h(RangeControl, {
|
||||
label: '切换间隔(毫秒)',
|
||||
value: attrs.delay,
|
||||
min: 1000,
|
||||
max: 10000,
|
||||
step: 500,
|
||||
onChange: function (v) { setAttributes({ delay: v }); },
|
||||
}),
|
||||
h(SelectControl, {
|
||||
label: '切换效果',
|
||||
value: attrs.effect,
|
||||
options: [
|
||||
{ label: '滑动', value: 'slide' },
|
||||
{ label: '淡入淡出', value: 'fade' },
|
||||
{ label: '立方体', value: 'cube' },
|
||||
],
|
||||
onChange: function (v) { setAttributes({ effect: v }); },
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
var preview = attrs.images.length > 0
|
||||
? h('div', { className: 'aksrt-carousel-preview', style: { display: 'flex', gap: '8px', flexWrap: 'wrap' } },
|
||||
attrs.images.map(function (img, i) {
|
||||
return h('img', {
|
||||
key: i,
|
||||
src: img.url,
|
||||
alt: img.alt,
|
||||
style: { width: '120px', height: '80px', objectFit: 'cover', borderRadius: '6px' },
|
||||
});
|
||||
})
|
||||
)
|
||||
: h('p', { style: { color: '#999', textAlign: 'center', padding: '20px' } }, '请选择图片');
|
||||
|
||||
return h(Fragment, null,
|
||||
inspector,
|
||||
h('div', { className: 'aksrt-carousel-block' },
|
||||
preview,
|
||||
h(MediaUpload, {
|
||||
onSelect: onSelectImages,
|
||||
allowedTypes: ['image'],
|
||||
multiple: true,
|
||||
value: attrs.images.map(function (img) { return img.id; }),
|
||||
render: function (obj) {
|
||||
return h(wp.components.Button, {
|
||||
onClick: obj.open,
|
||||
variant: 'secondary',
|
||||
style: { marginTop: '8px' },
|
||||
}, attrs.images.length ? '重新选择图片' : '选择图片');
|
||||
},
|
||||
})
|
||||
)
|
||||
);
|
||||
},
|
||||
save: function () {
|
||||
// Dynamic block — rendered via PHP
|
||||
return null;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,799 @@
|
||||
/**
|
||||
* Homepage Fixed - Interactive Layer (v2.0 Zibll-aligned)
|
||||
*
|
||||
* Unified AJAX protocol for homepage tabs, sort, pagination, and view toggle.
|
||||
* Uses Zibll-style ajaxpager DOM conventions and custom event flow:
|
||||
* post_ajax.before → fetch → post_ajax.ed → aksrt:posts:rendered
|
||||
*
|
||||
* @package AKSRT
|
||||
* @since 4.0.0
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var STORAGE_KEY = 'aksrt_homepage_view_mode';
|
||||
var SORT_QUERY_KEY = 'home_sort';
|
||||
var DEFAULT_SORT = 'modified';
|
||||
var DEFAULT_VIEW = 'list';
|
||||
var REST_PATH = '/wp-json/aksrt/v1/homepage/tab-posts';
|
||||
|
||||
/* ============================================================
|
||||
* Utilities
|
||||
* ============================================================ */
|
||||
|
||||
function safeLocalStorage() {
|
||||
try { return window.localStorage; } catch (e) { return null; }
|
||||
}
|
||||
|
||||
function getViewMode() {
|
||||
var store = safeLocalStorage();
|
||||
if (store) {
|
||||
var saved = store.getItem(STORAGE_KEY);
|
||||
if (saved === 'card' || saved === 'list') return saved;
|
||||
}
|
||||
return getDefaultView();
|
||||
}
|
||||
|
||||
function setViewMode(mode) {
|
||||
var store = safeLocalStorage();
|
||||
if (store) { try { store.setItem(STORAGE_KEY, mode); } catch (e) { /* */ } }
|
||||
}
|
||||
|
||||
function getRenderedPostCount(scope) {
|
||||
if (!scope) return 0;
|
||||
return scope.querySelectorAll('.posts-item, .posts-mini').length;
|
||||
}
|
||||
|
||||
function getHomepagePerPage(panel) {
|
||||
var panelCount = getRenderedPostCount(panel);
|
||||
if (panelCount > 0) return panelCount;
|
||||
|
||||
var configured = window.aksrtData && parseInt(aksrtData.homepagePostsPerPage, 10);
|
||||
if (configured && configured > 0) return configured;
|
||||
|
||||
var latestPanel = document.querySelector('[data-home-tab-panel="latest"]');
|
||||
var latestCount = getRenderedPostCount(latestPanel);
|
||||
return latestCount || 10;
|
||||
}
|
||||
|
||||
function getDefaultSort() {
|
||||
var configured = window.aksrtData && aksrtData.homepageDefaultSort;
|
||||
var allowed = ['modified', 'date', 'downloads', 'views', 'likes', 'comments'];
|
||||
return allowed.indexOf(configured) !== -1 ? configured : DEFAULT_SORT;
|
||||
}
|
||||
|
||||
function getDefaultView() {
|
||||
var configured = window.aksrtData && aksrtData.homepageDefaultView;
|
||||
return configured === 'card' || configured === 'list' ? configured : DEFAULT_VIEW;
|
||||
}
|
||||
|
||||
function isSortAjaxEnabled(sortbar) {
|
||||
var attr = sortbar && sortbar.getAttribute('data-sort-ajax');
|
||||
if (attr === 'false') return false;
|
||||
return !(window.aksrtData && aksrtData.homepageSortAjax === false);
|
||||
}
|
||||
|
||||
function isStickyTabsEnabled() {
|
||||
return !(window.aksrtData && aksrtData.homepageStickyTabs === false);
|
||||
}
|
||||
|
||||
function getRestBaseUrl() {
|
||||
var baseUrl = (window.aksrtData && aksrtData.siteUrl) || '/';
|
||||
return baseUrl.replace(/\/?$/, '');
|
||||
}
|
||||
|
||||
function getSortFromUrl() {
|
||||
return new URLSearchParams(window.location.search).get(SORT_QUERY_KEY) || getDefaultSort();
|
||||
}
|
||||
|
||||
function getCurrentSort(stream) {
|
||||
var activeLink = stream ? stream.querySelector('.aksrt-homepage__sortbar-link.is-active') : null;
|
||||
return (activeLink && activeLink.getAttribute('data-sort')) || getSortFromUrl();
|
||||
}
|
||||
|
||||
function setActiveSortLink(sortbar, sort) {
|
||||
var links = sortbar.querySelectorAll('.aksrt-homepage__sortbar-link, .aksrt-homepage__sortbar-dropdown-item');
|
||||
links.forEach(function (link) {
|
||||
link.classList.toggle('is-active', link.getAttribute('data-sort') === sort);
|
||||
});
|
||||
// Update dropdown trigger text to match the active item
|
||||
var activeItem = sortbar.querySelector('.aksrt-homepage__sortbar-dropdown-item[data-sort="' + sort + '"]');
|
||||
var trigger = sortbar.querySelector('[data-sort-dropdown-trigger]');
|
||||
if (activeItem && trigger) {
|
||||
trigger.firstChild.textContent = activeItem.textContent;
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeHomepageUrl(url) {
|
||||
url.searchParams.delete('paged');
|
||||
url.searchParams.delete('page');
|
||||
url.pathname = url.pathname.replace(/\/page\/\d+\/?$/, '/');
|
||||
return url;
|
||||
}
|
||||
|
||||
function replaceUrlSort(sort) {
|
||||
if (!window.history || !window.history.replaceState) return;
|
||||
var url = normalizeHomepageUrl(new URL(window.location.href));
|
||||
url.searchParams.set(SORT_QUERY_KEY, sort);
|
||||
window.history.replaceState({}, '', url.toString());
|
||||
}
|
||||
|
||||
function getStreamViewMode(stream) {
|
||||
var activeBtn = stream.querySelector('.aksrt-homepage__view-btn.is-active');
|
||||
return (activeBtn && activeBtn.getAttribute('data-view-mode')) || getViewMode();
|
||||
}
|
||||
|
||||
function getActivePanel(stream) {
|
||||
return stream.querySelector('.aksrt-homepage__panel.is-active, .aksrt-homepage__panel:not([hidden])');
|
||||
}
|
||||
|
||||
function getPanelTermId(panel) {
|
||||
if (!panel) return 0;
|
||||
var target = panel.getAttribute('data-home-tab-panel');
|
||||
if (target === 'latest') return 0;
|
||||
var match = target ? target.match(/^term-(\d+)$/) : null;
|
||||
return match ? parseInt(match[1], 10) : 0;
|
||||
}
|
||||
|
||||
function getPanelTabOrderby(panel) {
|
||||
if (!panel) return '';
|
||||
return panel.getAttribute('data-tab-orderby') || '';
|
||||
}
|
||||
|
||||
function getPanelSource(panel) {
|
||||
var target = panel ? panel.getAttribute('data-home-tab-panel') : '';
|
||||
if (target === 'latest') return 'home';
|
||||
return target ? 'home' : 'widget';
|
||||
}
|
||||
|
||||
function buildRestUrl(options) {
|
||||
options = options || {};
|
||||
return getRestBaseUrl() + REST_PATH +
|
||||
'?term_id=' + encodeURIComponent(options.termId || 0) +
|
||||
'&page=' + encodeURIComponent(options.page || 1) +
|
||||
'&per_page=' + encodeURIComponent(options.perPage || 10) +
|
||||
'&sort=' + encodeURIComponent(options.sort || getDefaultSort()) +
|
||||
'&view_mode=' + encodeURIComponent(options.viewMode || getDefaultView()) +
|
||||
'&page_url=' + encodeURIComponent(options.pageUrl || window.location.href) +
|
||||
'&panel=' + encodeURIComponent(options.panel || 'latest') +
|
||||
'&source=' + encodeURIComponent(options.source || 'home') +
|
||||
'&tab_orderby=' + encodeURIComponent(options.tabOrderby || '');
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Zibll-style event dispatching
|
||||
* ============================================================ */
|
||||
|
||||
/**
|
||||
* Dispatch post_ajax.before — fired before AJAX request is sent.
|
||||
* Detail: { termId, page, sort, viewMode, panel, source, url }
|
||||
*/
|
||||
function dispatchBeforeEvent(container, detail) {
|
||||
try {
|
||||
container.dispatchEvent(new CustomEvent('post_ajax.before', {
|
||||
bubbles: true,
|
||||
detail: detail
|
||||
}));
|
||||
} catch (e) { /* */ }
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch post_ajax.ed — fired after AJAX response is injected.
|
||||
* Detail: { termId, page, sort, viewMode, panel, source, total, hasMore }
|
||||
*/
|
||||
function dispatchAfterEvent(container, detail) {
|
||||
try {
|
||||
container.dispatchEvent(new CustomEvent('post_ajax.ed', {
|
||||
bubbles: true,
|
||||
detail: detail
|
||||
}));
|
||||
} catch (e) { /* */ }
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch aksrt:posts:rendered — fired after DOM is hydrated (lazyload etc).
|
||||
* Detail: { viewMode, panel }
|
||||
*/
|
||||
function dispatchRenderedEvent(container, detail) {
|
||||
try {
|
||||
container.dispatchEvent(new CustomEvent('aksrt:posts:rendered', {
|
||||
bubbles: true,
|
||||
detail: detail
|
||||
}));
|
||||
} catch (e) { /* */ }
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Skeleton, lazyload, and hydration
|
||||
* ============================================================ */
|
||||
|
||||
function buildSkeleton(count) {
|
||||
count = count || 3;
|
||||
var wrapper = document.createElement('div');
|
||||
wrapper.className = 'aksrt-homepage__tab-skeleton';
|
||||
for (var i = 0; i < count; i++) {
|
||||
var item = document.createElement('div');
|
||||
item.className = 'aksrt-homepage__tab-skeleton-item';
|
||||
item.innerHTML =
|
||||
'<div class="aksrt-homepage__tab-skeleton-thumb"></div>' +
|
||||
'<div class="aksrt-homepage__tab-skeleton-body">' +
|
||||
'<div class="aksrt-homepage__tab-skeleton-line"></div>' +
|
||||
'<div class="aksrt-homepage__tab-skeleton-line"></div>' +
|
||||
'<div class="aksrt-homepage__tab-skeleton-line"></div>' +
|
||||
'</div>';
|
||||
wrapper.appendChild(item);
|
||||
}
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
function hydrateLazyImages(scope) {
|
||||
var lazyImages = (scope || document).querySelectorAll('img.aksrt-lazy');
|
||||
if (!lazyImages.length) return;
|
||||
|
||||
if (!('IntersectionObserver' in window)) {
|
||||
lazyImages.forEach(function (img) {
|
||||
var src = img.dataset.src;
|
||||
if (src) {
|
||||
img.src = src;
|
||||
img.classList.remove('aksrt-lazy');
|
||||
img.classList.add('aksrt-loaded');
|
||||
}
|
||||
var skeleton = img.previousElementSibling;
|
||||
if (skeleton && skeleton.classList.contains('aksrt-skeleton')) skeleton.remove();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var observer = new IntersectionObserver(function (entries) {
|
||||
entries.forEach(function (entry) {
|
||||
if (!entry.isIntersecting) return;
|
||||
var img = entry.target;
|
||||
var src = img.dataset.src;
|
||||
if (!src) { observer.unobserve(img); return; }
|
||||
|
||||
var tempImg = new Image();
|
||||
tempImg.onload = function () {
|
||||
img.src = src;
|
||||
img.classList.remove('aksrt-lazy');
|
||||
img.classList.add('aksrt-loaded');
|
||||
var skeleton = img.previousElementSibling;
|
||||
if (skeleton && skeleton.classList.contains('aksrt-skeleton')) skeleton.remove();
|
||||
};
|
||||
tempImg.onerror = function () {
|
||||
img.classList.remove('aksrt-lazy');
|
||||
img.classList.add('aksrt-error');
|
||||
var skeleton = img.previousElementSibling;
|
||||
if (skeleton && skeleton.classList.contains('aksrt-skeleton')) skeleton.remove();
|
||||
};
|
||||
tempImg.src = src;
|
||||
observer.unobserve(img);
|
||||
});
|
||||
}, { rootMargin: '200px 0px', threshold: 0.01 });
|
||||
|
||||
lazyImages.forEach(function (img) { observer.observe(img); });
|
||||
}
|
||||
|
||||
/**
|
||||
* Hydrate a panel after AJAX content injection.
|
||||
* Sets data-view, re-binds lazy images, and dispatches events.
|
||||
*/
|
||||
function notifyPostsRendered(panel, viewMode) {
|
||||
var postsContainer = panel.querySelector('.aksrt-homepage__posts, .posts-row');
|
||||
if (postsContainer) {
|
||||
postsContainer.setAttribute('data-view', viewMode || getDefaultView());
|
||||
}
|
||||
|
||||
hydrateLazyImages(panel);
|
||||
dispatchRenderedEvent(panel, {
|
||||
viewMode: viewMode || getDefaultView(),
|
||||
panel: panel.getAttribute('data-home-tab-panel') || ''
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Unified AJAX panel loader
|
||||
* ============================================================ */
|
||||
|
||||
function buildErrorState(panel, requestOptions) {
|
||||
var wrapper = document.createElement('div');
|
||||
wrapper.className = 'aksrt-homepage__tab-error';
|
||||
|
||||
var msg = document.createElement('p');
|
||||
msg.textContent = (window.aksrtData && aksrtData.ajaxLoadError) || '加载失败,请重试';
|
||||
wrapper.appendChild(msg);
|
||||
|
||||
var retry = document.createElement('button');
|
||||
retry.type = 'button';
|
||||
retry.className = 'aksrt-homepage__tab-retry';
|
||||
retry.innerHTML = '<i class="fas fa-redo"></i> ' +
|
||||
((window.aksrtData && aksrtData.ajaxRetry) || '重试');
|
||||
retry.addEventListener('click', function () {
|
||||
requestHomepagePanel(panel, requestOptions);
|
||||
});
|
||||
wrapper.appendChild(retry);
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Core AJAX loader. Shared by tab switch, sort change, pagination, and widget tabs.
|
||||
*
|
||||
* Dispatches the full Zibll-aligned event lifecycle:
|
||||
* 1. post_ajax.before (before fetch)
|
||||
* 2. [inject HTML]
|
||||
* 3. post_ajax.ed (after inject, before hydrate)
|
||||
* 4. aksrt:posts:rendered (after lazyload rebind)
|
||||
*/
|
||||
function requestHomepagePanel(panel, requestOptions) {
|
||||
var options = {
|
||||
termId: requestOptions.termId || 0,
|
||||
page: requestOptions.page || 1,
|
||||
perPage: requestOptions.perPage || getHomepagePerPage(panel),
|
||||
sort: requestOptions.sort || getDefaultSort(),
|
||||
viewMode: requestOptions.viewMode || getDefaultView(),
|
||||
pageUrl: requestOptions.pageUrl || window.location.href,
|
||||
panel: requestOptions.panel || panel.getAttribute('data-home-tab-panel') || 'latest',
|
||||
source: requestOptions.source || getPanelSource(panel),
|
||||
tabOrderby: requestOptions.tabOrderby || getPanelTabOrderby(panel) || ''
|
||||
};
|
||||
|
||||
var restUrl = buildRestUrl(options);
|
||||
var retryCount = 0;
|
||||
var maxRetries = 1;
|
||||
|
||||
// 1. Pre-request event
|
||||
dispatchBeforeEvent(panel, {
|
||||
termId: options.termId,
|
||||
page: options.page,
|
||||
sort: options.sort,
|
||||
viewMode: options.viewMode,
|
||||
panel: options.panel,
|
||||
source: options.source,
|
||||
url: restUrl
|
||||
});
|
||||
|
||||
// Show loading skeleton
|
||||
panel.innerHTML = '';
|
||||
panel.appendChild(buildSkeleton(options.perPage > 6 ? 4 : 3));
|
||||
|
||||
function markLoaded() {
|
||||
panel.dataset.loaded = 'true';
|
||||
panel.dataset.loadedPage = String(options.page);
|
||||
panel.dataset.loadedSort = options.sort;
|
||||
panel.dataset.loadedTermId = String(options.termId);
|
||||
}
|
||||
|
||||
function doFetch() {
|
||||
fetch(restUrl, {
|
||||
method: 'GET',
|
||||
headers: { Accept: 'application/json' },
|
||||
credentials: 'same-origin'
|
||||
})
|
||||
.then(function (response) {
|
||||
if (!response.ok) throw new Error('HTTP ' + response.status);
|
||||
return response.json();
|
||||
})
|
||||
.then(function (data) {
|
||||
panel.innerHTML = '';
|
||||
markLoaded();
|
||||
|
||||
if (data && data.html) {
|
||||
// 2. Inject HTML
|
||||
panel.innerHTML = data.html;
|
||||
|
||||
// 3. Post-inject event
|
||||
dispatchAfterEvent(panel, {
|
||||
termId: options.termId,
|
||||
page: options.page,
|
||||
sort: options.sort,
|
||||
viewMode: options.viewMode,
|
||||
panel: options.panel,
|
||||
source: options.source,
|
||||
total: data.total || 0,
|
||||
hasMore: !!data.has_more
|
||||
});
|
||||
|
||||
// 4. Hydrate + rendered event
|
||||
notifyPostsRendered(panel, options.viewMode);
|
||||
|
||||
// 5. Rehydrate dynamic components on new content
|
||||
if (window.AksrtFrontend && typeof window.AksrtFrontend.rehydrate === 'function') {
|
||||
window.AksrtFrontend.rehydrate(panel, 'ajax');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Empty response
|
||||
var empty = document.createElement('div');
|
||||
empty.className = 'no-results';
|
||||
empty.innerHTML = '<p>' + ((window.aksrtData && aksrtData.ajaxEmpty) || '暂无文章') + '</p>';
|
||||
panel.appendChild(empty);
|
||||
|
||||
dispatchAfterEvent(panel, {
|
||||
termId: options.termId,
|
||||
page: options.page,
|
||||
sort: options.sort,
|
||||
viewMode: options.viewMode,
|
||||
panel: options.panel,
|
||||
source: options.source,
|
||||
total: 0,
|
||||
hasMore: false
|
||||
});
|
||||
})
|
||||
.catch(function () {
|
||||
if (retryCount < maxRetries) {
|
||||
retryCount++;
|
||||
window.setTimeout(doFetch, 3000);
|
||||
return;
|
||||
}
|
||||
panel.innerHTML = '';
|
||||
panel.appendChild(buildErrorState(panel, options));
|
||||
});
|
||||
}
|
||||
|
||||
doFetch();
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Tab Navigation
|
||||
* ============================================================ */
|
||||
|
||||
function initHomeTabs(scope) {
|
||||
var tablists = (scope || document).querySelectorAll('[data-aksrt-home-tabs]');
|
||||
|
||||
tablists.forEach(function (list, listIndex) {
|
||||
var stream = list.closest('.aksrt-homepage__stream');
|
||||
if (!stream) return;
|
||||
|
||||
var buttons = Array.from(list.querySelectorAll('[data-home-tab-target]'));
|
||||
var panels = Array.from(stream.querySelectorAll('[data-home-tab-panel]'));
|
||||
|
||||
if (buttons.length < 2 || !panels.length) return;
|
||||
|
||||
function getPanel(button) {
|
||||
var target = button.getAttribute('data-home-tab-target');
|
||||
return panels.find(function (p) {
|
||||
return p.getAttribute('data-home-tab-panel') === target;
|
||||
});
|
||||
}
|
||||
|
||||
function activate(button) {
|
||||
var target = button.getAttribute('data-home-tab-target');
|
||||
var panel = getPanel(button);
|
||||
var termId = getPanelTermId(panel);
|
||||
var currentSort = getCurrentSort(stream);
|
||||
var viewMode = getStreamViewMode(stream);
|
||||
var tabOrderby = button.getAttribute('data-tab-orderby') || getPanelTabOrderby(panel) || '';
|
||||
|
||||
// Toggle active state on tab buttons
|
||||
buttons.forEach(function (item) {
|
||||
var isActive = item === button;
|
||||
var itemWrap = item.closest('.aksrt-homepage__tab-item');
|
||||
if (itemWrap) itemWrap.classList.toggle('is-active', isActive);
|
||||
item.setAttribute('aria-selected', isActive ? 'true' : 'false');
|
||||
item.tabIndex = isActive ? 0 : -1;
|
||||
});
|
||||
|
||||
// Toggle active state on panels (ajaxpager convention)
|
||||
panels.forEach(function (tabPanel) {
|
||||
var isActive = tabPanel === panel;
|
||||
tabPanel.classList.toggle('is-active', isActive);
|
||||
if (isActive) {
|
||||
tabPanel.removeAttribute('hidden');
|
||||
tabPanel.setAttribute('aria-hidden', 'false');
|
||||
} else {
|
||||
tabPanel.setAttribute('hidden', '');
|
||||
tabPanel.setAttribute('aria-hidden', 'true');
|
||||
}
|
||||
});
|
||||
|
||||
// Load content if needed (lazy AJAX load like Zibll)
|
||||
// For tab panels, the "loaded sort" check uses tabOrderby, not main stream sort
|
||||
var effectiveSort = tabOrderby || currentSort;
|
||||
if (panel && (panel.dataset.loaded !== 'true' || panel.dataset.loadedSort !== effectiveSort)) {
|
||||
requestHomepagePanel(panel, {
|
||||
termId: termId,
|
||||
page: 1,
|
||||
perPage: getHomepagePerPage(panel),
|
||||
sort: currentSort,
|
||||
viewMode: viewMode,
|
||||
panel: target,
|
||||
source: 'home',
|
||||
tabOrderby: tabOrderby
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Set up ARIA relationships
|
||||
buttons.forEach(function (button) {
|
||||
var target = button.getAttribute('data-home-tab-target');
|
||||
var panel = getPanel(button);
|
||||
var buttonId = 'aksrt-home-tab-' + listIndex + '-' + target;
|
||||
|
||||
button.id = button.id || buttonId;
|
||||
if (panel) {
|
||||
panel.id = panel.id || buttonId + '-panel';
|
||||
panel.setAttribute('aria-labelledby', button.id);
|
||||
button.setAttribute('aria-controls', panel.id);
|
||||
// Add ajaxpager class for Zibll DOM convention
|
||||
panel.classList.add('ajaxpager');
|
||||
}
|
||||
|
||||
button.addEventListener('click', function () { activate(button); });
|
||||
|
||||
button.addEventListener('keydown', function (event) {
|
||||
if (event.key !== 'ArrowRight' && event.key !== 'ArrowLeft') return;
|
||||
event.preventDefault();
|
||||
var direction = event.key === 'ArrowRight' ? 1 : -1;
|
||||
var currentIndex = buttons.indexOf(button);
|
||||
var nextIndex = (currentIndex + direction + buttons.length) % buttons.length;
|
||||
var nextButton = buttons[nextIndex];
|
||||
if (nextButton) {
|
||||
nextButton.focus();
|
||||
activate(nextButton);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Mark server-rendered panels as already loaded
|
||||
panels.forEach(function (panel) {
|
||||
if (!panel.querySelector('.aksrt-homepage__posts, .posts-row')) return;
|
||||
panel.dataset.loaded = 'true';
|
||||
panel.dataset.loadedPage = '1';
|
||||
panel.dataset.loadedSort = getCurrentSort(stream);
|
||||
panel.dataset.loadedTermId = String(getPanelTermId(panel));
|
||||
});
|
||||
|
||||
// Activate initial tab
|
||||
var initialButton = buttons.find(function (b) {
|
||||
return b.getAttribute('aria-selected') === 'true';
|
||||
}) || buttons[0];
|
||||
activate(initialButton);
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Sortbar Dropdown Toggle
|
||||
* ============================================================ */
|
||||
|
||||
function initSortbarDropdown() {
|
||||
document.querySelectorAll('[data-sort-dropdown-trigger]').forEach(function (trigger) {
|
||||
var wrapper = trigger.closest('.aksrt-homepage__sortbar-dropdown');
|
||||
if (!wrapper) return;
|
||||
var menu = wrapper.querySelector('.aksrt-homepage__sortbar-dropdown-menu');
|
||||
if (!menu) return;
|
||||
|
||||
function close() {
|
||||
menu.setAttribute('hidden', '');
|
||||
trigger.setAttribute('aria-expanded', 'false');
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
var isOpen = !menu.hasAttribute('hidden');
|
||||
if (isOpen) {
|
||||
close();
|
||||
} else {
|
||||
menu.removeAttribute('hidden');
|
||||
trigger.setAttribute('aria-expanded', 'true');
|
||||
}
|
||||
}
|
||||
|
||||
trigger.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
toggle();
|
||||
});
|
||||
|
||||
// Close when clicking an item
|
||||
menu.addEventListener('click', function (e) {
|
||||
var item = e.target.closest('.aksrt-homepage__sortbar-dropdown-item');
|
||||
if (!item) return;
|
||||
// Update trigger text
|
||||
trigger.firstChild.textContent = item.textContent;
|
||||
// Update active state
|
||||
menu.querySelectorAll('.aksrt-homepage__sortbar-dropdown-item').forEach(function (el) {
|
||||
el.classList.toggle('is-active', el === item);
|
||||
});
|
||||
close();
|
||||
});
|
||||
|
||||
// Close on outside click
|
||||
document.addEventListener('click', function (e) {
|
||||
if (!wrapper.contains(e.target)) close();
|
||||
});
|
||||
|
||||
// Close on Escape
|
||||
document.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'Escape' && !menu.hasAttribute('hidden')) {
|
||||
close();
|
||||
trigger.focus();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Sortbar AJAX
|
||||
* ============================================================ */
|
||||
|
||||
function initSortbar() {
|
||||
document.querySelectorAll('.aksrt-homepage__stream').forEach(function (stream) {
|
||||
var sortbar = stream.querySelector('.aksrt-homepage__sortbar');
|
||||
if (!sortbar || !isSortAjaxEnabled(sortbar)) return;
|
||||
|
||||
sortbar.addEventListener('click', function (event) {
|
||||
var link = event.target.closest('.aksrt-homepage__sortbar-link, .aksrt-homepage__sortbar-dropdown-item');
|
||||
var activePanel = getActivePanel(stream);
|
||||
var sort = link ? link.getAttribute('data-sort') : '';
|
||||
var termId = getPanelTermId(activePanel);
|
||||
|
||||
if (!link || !activePanel || !sort) return;
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
setActiveSortLink(sortbar, sort);
|
||||
replaceUrlSort(sort);
|
||||
|
||||
requestHomepagePanel(activePanel, {
|
||||
termId: termId,
|
||||
page: 1,
|
||||
perPage: getHomepagePerPage(activePanel),
|
||||
sort: sort,
|
||||
viewMode: getStreamViewMode(stream),
|
||||
panel: activePanel.getAttribute('data-home-tab-panel') || 'latest',
|
||||
source: 'home'
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Sticky Tabs
|
||||
* ============================================================ */
|
||||
|
||||
function supportsStickyPosition() {
|
||||
if (window.CSS && typeof window.CSS.supports === 'function') {
|
||||
return window.CSS.supports('position', 'sticky') || window.CSS.supports('position', '-webkit-sticky');
|
||||
}
|
||||
var testNode = document.createElement('div');
|
||||
testNode.style.position = 'sticky';
|
||||
return testNode.style.position.indexOf('sticky') !== -1;
|
||||
}
|
||||
|
||||
function getStickyOffset() {
|
||||
var docStyles = window.getComputedStyle(document.documentElement);
|
||||
var offset = parseFloat(docStyles.getPropertyValue('--nav-height') || '60');
|
||||
return isNaN(offset) ? 60 : offset;
|
||||
}
|
||||
|
||||
function initStickyTabs() {
|
||||
if (!isStickyTabsEnabled()) return;
|
||||
|
||||
document.querySelectorAll('.aksrt-homepage__tabs.home-tab-nav-box').forEach(function (tabs) {
|
||||
var parent = tabs.parentNode;
|
||||
var sentinel = tabs.previousElementSibling;
|
||||
var canUseSticky = supportsStickyPosition();
|
||||
var hasObserver = 'IntersectionObserver' in window;
|
||||
var observer = null;
|
||||
|
||||
if (!parent || tabs.getAttribute('data-sticky-tabs') === 'false') return;
|
||||
|
||||
if (!sentinel || !sentinel.classList.contains('aksrt-homepage__tabs-sentinel')) {
|
||||
sentinel = document.createElement('div');
|
||||
sentinel.className = 'aksrt-homepage__tabs-sentinel';
|
||||
parent.insertBefore(sentinel, tabs);
|
||||
}
|
||||
|
||||
function clearAffixBox() {
|
||||
sentinel.style.height = '1px';
|
||||
tabs.style.left = '';
|
||||
tabs.style.width = '';
|
||||
}
|
||||
|
||||
function syncAffixBox() {
|
||||
var rect = sentinel.getBoundingClientRect();
|
||||
sentinel.style.height = tabs.offsetHeight + 'px';
|
||||
tabs.style.left = rect.left + 'px';
|
||||
tabs.style.width = rect.width + 'px';
|
||||
}
|
||||
|
||||
function setStickyState(isStuck) {
|
||||
tabs.classList.toggle('is-stuck', isStuck);
|
||||
if (!canUseSticky) {
|
||||
tabs.classList.toggle('is-affixed', isStuck);
|
||||
if (isStuck) { syncAffixBox(); } else { clearAffixBox(); }
|
||||
return;
|
||||
}
|
||||
tabs.classList.remove('is-affixed');
|
||||
clearAffixBox();
|
||||
}
|
||||
|
||||
function evaluateFallbackState() {
|
||||
setStickyState(sentinel.getBoundingClientRect().top <= getStickyOffset());
|
||||
}
|
||||
|
||||
if (canUseSticky && hasObserver) {
|
||||
var bindObserver = function () {
|
||||
if (observer) observer.disconnect();
|
||||
observer = new IntersectionObserver(function (entries) {
|
||||
setStickyState(!entries[0].isIntersecting);
|
||||
}, { rootMargin: '-' + getStickyOffset() + 'px 0px 0px 0px', threshold: [1] });
|
||||
observer.observe(sentinel);
|
||||
};
|
||||
bindObserver();
|
||||
window.addEventListener('resize', bindObserver);
|
||||
return;
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', evaluateFallbackState, { passive: true });
|
||||
window.addEventListener('resize', evaluateFallbackState);
|
||||
evaluateFallbackState();
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* View Mode Toggle
|
||||
* ============================================================ */
|
||||
|
||||
function applyViewMode(buttons, postsContainers, mode) {
|
||||
buttons.forEach(function (btn) {
|
||||
var btnMode = btn.getAttribute('data-view-mode');
|
||||
btn.classList.toggle('is-active', btnMode === mode);
|
||||
});
|
||||
Array.prototype.forEach.call(postsContainers, function (container) {
|
||||
container.setAttribute('data-view', mode);
|
||||
});
|
||||
}
|
||||
|
||||
function initViewToggle() {
|
||||
var toggles = document.querySelectorAll('[data-aksrt-view-toggle]');
|
||||
|
||||
toggles.forEach(function (toggle) {
|
||||
var buttons = toggle.querySelectorAll('.aksrt-homepage__view-btn');
|
||||
var stream = toggle.closest('.aksrt-homepage__stream');
|
||||
if (!stream) return;
|
||||
|
||||
function getPostsContainers() {
|
||||
return stream.querySelectorAll('.aksrt-homepage__posts, .posts-row');
|
||||
}
|
||||
|
||||
function getActiveMode() {
|
||||
var activeBtn = toggle.querySelector('.aksrt-homepage__view-btn.is-active');
|
||||
return (activeBtn && activeBtn.getAttribute('data-view-mode')) || getViewMode();
|
||||
}
|
||||
|
||||
applyViewMode(buttons, getPostsContainers(), getViewMode());
|
||||
|
||||
buttons.forEach(function (btn) {
|
||||
btn.addEventListener('click', function () {
|
||||
var mode = btn.getAttribute('data-view-mode') || getDefaultView();
|
||||
applyViewMode(buttons, getPostsContainers(), mode);
|
||||
setViewMode(mode);
|
||||
});
|
||||
});
|
||||
|
||||
// Re-apply view mode after AJAX content renders
|
||||
stream.addEventListener('aksrt:posts:rendered', function () {
|
||||
applyViewMode(buttons, getPostsContainers(), getActiveMode());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Init
|
||||
* ============================================================ */
|
||||
|
||||
function init() {
|
||||
initHomeTabs();
|
||||
initSortbarDropdown();
|
||||
initSortbar();
|
||||
initStickyTabs();
|
||||
initViewToggle();
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
* AKSRT Input Expand
|
||||
*
|
||||
* Lightweight input field enhancements:
|
||||
* - Textarea auto-resize on input
|
||||
* - Character counter with limit display
|
||||
* - Validation feedback (min/max length, required)
|
||||
*
|
||||
* No external dependencies — pure vanilla JS.
|
||||
*
|
||||
* Usage:
|
||||
* <textarea data-aksrt-autoresize></textarea>
|
||||
* <input data-aksrt-counter data-aksrt-maxlength="200">
|
||||
* <input data-aksrt-validate data-aksrt-minlength="3" required>
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var STYLE_ID = 'aksrt-input-expand-style';
|
||||
|
||||
function injectStyle() {
|
||||
if (document.getElementById(STYLE_ID)) return;
|
||||
var style = document.createElement('style');
|
||||
style.id = STYLE_ID;
|
||||
style.textContent =
|
||||
'.aksrt-counter{display:block;text-align:right;font-size:12px;color:#8a909c;margin-top:4px;transition:color 0.2s;}' +
|
||||
'.aksrt-counter.is-over{color:#e74c3c;}' +
|
||||
'.aksrt-counter.is-warn{color:#f39c12;}' +
|
||||
'.aksrt-validate-msg{display:block;font-size:12px;margin-top:4px;color:#e74c3c;opacity:0;max-height:0;overflow:hidden;transition:all 0.2s;}' +
|
||||
'.aksrt-validate-msg.is-visible{opacity:1;max-height:30px;}' +
|
||||
'textarea[data-aksrt-autoresize]{overflow:hidden;resize:none;}';
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
|
||||
// ── Auto-resize Textarea ──
|
||||
|
||||
function initAutoResize() {
|
||||
var textareas = document.querySelectorAll('textarea[data-aksrt-autoresize]');
|
||||
textareas.forEach(function (ta) {
|
||||
function resize() {
|
||||
ta.style.height = 'auto';
|
||||
ta.style.height = ta.scrollHeight + 'px';
|
||||
}
|
||||
ta.addEventListener('input', resize);
|
||||
// Initial resize
|
||||
resize();
|
||||
});
|
||||
}
|
||||
|
||||
// ── Character Counter ──
|
||||
|
||||
function initCounters() {
|
||||
var fields = document.querySelectorAll('[data-aksrt-counter]');
|
||||
fields.forEach(function (field) {
|
||||
var max = parseInt(field.getAttribute('data-aksrt-maxlength') || field.getAttribute('maxlength') || '0', 10);
|
||||
var counter = document.createElement('span');
|
||||
counter.className = 'aksrt-counter';
|
||||
field.parentNode.insertBefore(counter, field.nextSibling);
|
||||
|
||||
function update() {
|
||||
var len = (field.value || '').length;
|
||||
if (max > 0) {
|
||||
counter.textContent = len + ' / ' + max;
|
||||
counter.classList.toggle('is-over', len > max);
|
||||
counter.classList.toggle('is-warn', len > max * 0.9 && len <= max);
|
||||
} else {
|
||||
counter.textContent = len + ' 字';
|
||||
counter.classList.remove('is-over', 'is-warn');
|
||||
}
|
||||
}
|
||||
|
||||
field.addEventListener('input', update);
|
||||
update();
|
||||
});
|
||||
}
|
||||
|
||||
// ── Validation Feedback ──
|
||||
|
||||
function initValidation() {
|
||||
var fields = document.querySelectorAll('[data-aksrt-validate]');
|
||||
fields.forEach(function (field) {
|
||||
var minLen = parseInt(field.getAttribute('data-aksrt-minlength') || field.getAttribute('minlength') || '0', 10);
|
||||
var maxLen = parseInt(field.getAttribute('data-aksrt-maxlength') || field.getAttribute('maxlength') || '0', 10);
|
||||
var required = field.hasAttribute('required');
|
||||
|
||||
var msg = document.createElement('span');
|
||||
msg.className = 'aksrt-validate-msg';
|
||||
field.parentNode.insertBefore(msg, field.nextSibling);
|
||||
|
||||
function validate() {
|
||||
var val = (field.value || '').trim();
|
||||
var error = '';
|
||||
|
||||
if (required && val === '') {
|
||||
error = '此项为必填';
|
||||
} else if (minLen > 0 && val.length > 0 && val.length < minLen) {
|
||||
error = '至少需要 ' + minLen + ' 个字符';
|
||||
} else if (maxLen > 0 && val.length > maxLen) {
|
||||
error = '不能超过 ' + maxLen + ' 个字符';
|
||||
}
|
||||
|
||||
msg.textContent = error;
|
||||
msg.classList.toggle('is-visible', error !== '');
|
||||
field.classList.toggle('is-invalid', error !== '');
|
||||
field.classList.toggle('is-valid', error === '' && val !== '');
|
||||
}
|
||||
|
||||
field.addEventListener('input', validate);
|
||||
field.addEventListener('blur', validate);
|
||||
});
|
||||
}
|
||||
|
||||
// ── Main Init ──
|
||||
|
||||
function init() {
|
||||
injectStyle();
|
||||
initAutoResize();
|
||||
initCounters();
|
||||
initValidation();
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* AKSRT Instant Page
|
||||
*
|
||||
* Lightweight page prefetch on hover/focus.
|
||||
* Preloads pages when the user hovers over a link, so navigation feels instant.
|
||||
* No external dependencies — pure vanilla JS.
|
||||
*
|
||||
* Based on the instant.page concept (MIT license).
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
// Only prefetch on desktop (no touch-only devices) with good connection
|
||||
if ('connection' in navigator) {
|
||||
var conn = navigator.connection;
|
||||
if (conn.saveData || (conn.effectiveType && conn.effectiveType.indexOf('2g') !== -1)) return;
|
||||
}
|
||||
|
||||
// Don't run on touch-only devices (they don't benefit from hover prefetch)
|
||||
var hasHoverSupport = window.matchMedia('(hover: hover) and (pointer: fine)').matches;
|
||||
if (!hasHoverSupport) return;
|
||||
|
||||
var prefetcher = document.createElement('link');
|
||||
var isPrefetched = {};
|
||||
var timer = null;
|
||||
var DELAY = 65; // ms to wait before prefetching
|
||||
var MAX_PREFETCH = 3; // max concurrent prefetches
|
||||
var prefetchedCount = 0;
|
||||
|
||||
if (!prefetcher.relList || !prefetcher.relList.supports || !prefetcher.relList.supports('prefetch')) return;
|
||||
|
||||
function prefetch(url) {
|
||||
if (isPrefetched[url] || prefetchedCount >= MAX_PREFETCH) return;
|
||||
|
||||
// Don't prefetch URLs with hash (same page navigation)
|
||||
if (url.indexOf('#') !== -1) return;
|
||||
|
||||
// Only prefetch same-origin URLs
|
||||
try {
|
||||
var link = new URL(url, window.location.origin);
|
||||
if (link.origin !== window.location.origin) return;
|
||||
// Don't prefetch the current page
|
||||
if (link.pathname === window.location.pathname && link.search === window.location.search) return;
|
||||
} catch (e) { return; }
|
||||
|
||||
// Don't prefetch files/downloads
|
||||
if (/\.(pdf|zip|rar|7z|tar|gz|exe|dmg|apk|mp[34]|avi|mov|wmv|flv|webm|ogg|wav|bmp|gif|ico|svg|woff2?|ttf|eot)(\?|$)/i.test(url)) return;
|
||||
|
||||
isPrefetched[url] = true;
|
||||
prefetchedCount++;
|
||||
|
||||
var linkEl = document.createElement('link');
|
||||
linkEl.rel = 'prefetch';
|
||||
linkEl.href = url;
|
||||
linkEl.as = 'document';
|
||||
document.head.appendChild(linkEl);
|
||||
}
|
||||
|
||||
function onHoverStart(e) {
|
||||
var link = e.target.closest('a');
|
||||
if (!link || !link.href) return;
|
||||
if (link.target === '_blank') return;
|
||||
if (link.hasAttribute('download')) return;
|
||||
if (link.getAttribute('rel') === 'nofollow') return;
|
||||
if (link.closest('.no-prefetch,[data-no-prefetch]')) return;
|
||||
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(function () {
|
||||
prefetch(link.href);
|
||||
}, DELAY);
|
||||
}
|
||||
|
||||
function onHoverEnd() {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
|
||||
document.addEventListener('mouseover', onHoverStart, { passive: true, capture: true });
|
||||
document.addEventListener('mouseout', onHoverEnd, { passive: true, capture: true });
|
||||
|
||||
// Also prefetch on focus for keyboard navigation
|
||||
document.addEventListener('focusin', function (e) {
|
||||
var link = e.target.closest('a');
|
||||
if (link && link.href) {
|
||||
prefetch(link.href);
|
||||
}
|
||||
}, { passive: true, capture: true });
|
||||
|
||||
// Cleanup after page hides (bfcache)
|
||||
window.addEventListener('pagehide', function () {
|
||||
isPrefetched = {};
|
||||
prefetchedCount = 0;
|
||||
});
|
||||
})();
|
||||
@@ -0,0 +1,172 @@
|
||||
/**
|
||||
* AKSRT Page Loader
|
||||
*
|
||||
* Lightweight top progress bar for page transitions and AJAX requests.
|
||||
* No external dependencies — pure vanilla JS.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var STYLE_ID = 'aksrt-loader-style';
|
||||
var BAR_ID = 'aksrt-loader-bar';
|
||||
var CSS =
|
||||
'#' + BAR_ID + '{' +
|
||||
'position:fixed;top:0;left:0;width:0;height:3px;z-index:99999;' +
|
||||
'background:linear-gradient(90deg,#1890ff,#36cfc9);' +
|
||||
'transition:width 0.3s ease,opacity 0.3s ease;' +
|
||||
'pointer-events:none;opacity:0;' +
|
||||
'}' +
|
||||
'#' + BAR_ID + '.is-active{opacity:1;}' +
|
||||
'#' + BAR_ID + '.is-done{' +
|
||||
'width:100%!important;opacity:0;' +
|
||||
'}';
|
||||
|
||||
var bar = null;
|
||||
var timer = null;
|
||||
var progress = 0;
|
||||
|
||||
function injectStyle() {
|
||||
if (document.getElementById(STYLE_ID)) return;
|
||||
var style = document.createElement('style');
|
||||
style.id = STYLE_ID;
|
||||
style.textContent = CSS;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
|
||||
function createBar() {
|
||||
if (bar) return;
|
||||
bar = document.createElement('div');
|
||||
bar.id = BAR_ID;
|
||||
document.body.appendChild(bar);
|
||||
}
|
||||
|
||||
function start() {
|
||||
if (!bar) createBar();
|
||||
clearTimeout(timer);
|
||||
bar.classList.remove('is-done');
|
||||
bar.classList.add('is-active');
|
||||
progress = 0;
|
||||
bar.style.width = '0%';
|
||||
trickle();
|
||||
}
|
||||
|
||||
function trickle() {
|
||||
if (progress >= 90) return;
|
||||
var increment = progress < 30 ? 8 : progress < 60 ? 4 : 2;
|
||||
progress = Math.min(90, progress + increment * (0.8 + Math.random() * 0.4));
|
||||
bar.style.width = progress + '%';
|
||||
timer = setTimeout(trickle, 200 + Math.random() * 300);
|
||||
}
|
||||
|
||||
function done() {
|
||||
if (!bar) return;
|
||||
clearTimeout(timer);
|
||||
bar.style.width = '100%';
|
||||
bar.classList.add('is-done');
|
||||
setTimeout(function () {
|
||||
bar.classList.remove('is-active', 'is-done');
|
||||
bar.style.width = '0%';
|
||||
progress = 0;
|
||||
}, 400);
|
||||
}
|
||||
|
||||
// Intercept link clicks for same-origin page transitions
|
||||
function onLinkClick(e) {
|
||||
if (e.defaultPrevented) return;
|
||||
if (e.button !== 0) return; // left click only
|
||||
if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
|
||||
|
||||
var link = e.target.closest('a');
|
||||
if (!link || !link.href) return;
|
||||
if (link.target === '_blank') return;
|
||||
if (link.hasAttribute('download')) return;
|
||||
if (link.href.indexOf('#') === 0) return;
|
||||
|
||||
// Same-origin only
|
||||
try {
|
||||
var url = new URL(link.href);
|
||||
if (url.origin !== window.location.origin) return;
|
||||
if (url.protocol !== "http:" && url.protocol !== "https:") return;
|
||||
if (url.pathname === window.location.pathname && url.search === window.location.search) return;
|
||||
} catch (ex) { return; }
|
||||
|
||||
start();
|
||||
}
|
||||
|
||||
// Intercept form submissions
|
||||
function onFormSubmit(e) {
|
||||
var form = e.target;
|
||||
if (!form || form.tagName !== 'FORM') return;
|
||||
if (form.target === '_blank') return;
|
||||
start();
|
||||
}
|
||||
|
||||
// Hook into AJAX (fetch) if available
|
||||
function hookFetch() {
|
||||
if (!window.fetch) return;
|
||||
var origFetch = window.fetch;
|
||||
window.fetch = function () {
|
||||
start();
|
||||
return origFetch.apply(this, arguments).then(function (response) {
|
||||
done();
|
||||
return response;
|
||||
}).catch(function (err) {
|
||||
done();
|
||||
throw err;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// Hook into XMLHttpRequest
|
||||
function hookXHR() {
|
||||
if (!window.XMLHttpRequest) return;
|
||||
var origOpen = XMLHttpRequest.prototype.open;
|
||||
var origSend = XMLHttpRequest.prototype.send;
|
||||
|
||||
XMLHttpRequest.prototype.open = function () {
|
||||
this._aksrtLoader = true;
|
||||
return origOpen.apply(this, arguments);
|
||||
};
|
||||
|
||||
XMLHttpRequest.prototype.send = function () {
|
||||
if (this._aksrtLoader) {
|
||||
start();
|
||||
var self = this;
|
||||
this.addEventListener('loadend', function () { done(); });
|
||||
}
|
||||
return origSend.apply(this, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
function init() {
|
||||
injectStyle();
|
||||
createBar();
|
||||
|
||||
document.addEventListener('click', onLinkClick, true);
|
||||
document.addEventListener('submit', onFormSubmit, true);
|
||||
|
||||
// Done on page load (handles bfcache)
|
||||
window.addEventListener('pageshow', function (e) {
|
||||
if (e.persisted) done();
|
||||
});
|
||||
window.addEventListener('load', done);
|
||||
|
||||
hookFetch();
|
||||
hookXHR();
|
||||
}
|
||||
|
||||
// Public API
|
||||
window.AksrtLoader = {
|
||||
start: start,
|
||||
done: done
|
||||
};
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* AKSRT Frontend Shell
|
||||
*
|
||||
* All init modules have been extracted to assets/js/core/*.js.
|
||||
* This file remains as the enqueue anchor (handle: aksrt-script) that
|
||||
* other scripts depend on, and provides the AksrtFrontend fallback
|
||||
* for edge cases where rehydrate.js is not loaded first.
|
||||
*
|
||||
* @package AKSRT
|
||||
* @since 5.0.0
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
if (!window.AksrtFrontend) {
|
||||
window.AksrtFrontend = {
|
||||
register: function (name, fn) {
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", function () { fn(document, "init"); });
|
||||
} else {
|
||||
fn(document, "init");
|
||||
}
|
||||
},
|
||||
rehydrate: function () {}
|
||||
};
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,168 @@
|
||||
/**
|
||||
* AKSRT messages center interactions.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var nonce = typeof aksrtData !== 'undefined' ? aksrtData.nonce : '';
|
||||
var ajaxUrl = typeof aksrtData !== 'undefined' ? aksrtData.ajaxUrl : '/wp-admin/admin-ajax.php';
|
||||
var pollTimer = null;
|
||||
var pollInterval = 60000;
|
||||
|
||||
function post(action, data) {
|
||||
var body = new URLSearchParams({ action: action, nonce: nonce });
|
||||
if (data) {
|
||||
Object.keys(data).forEach(function (key) {
|
||||
var value = data[key];
|
||||
if (Array.isArray(value)) {
|
||||
value.forEach(function (item) {
|
||||
body.append(key + '[]', item);
|
||||
});
|
||||
return;
|
||||
}
|
||||
body.append(key, value);
|
||||
});
|
||||
}
|
||||
|
||||
return fetch(ajaxUrl, { method: 'POST', body: body, credentials: 'same-origin' })
|
||||
.then(function (response) { return response.json(); });
|
||||
}
|
||||
|
||||
document.addEventListener('click', function (event) {
|
||||
var item = event.target.closest('.messages-nav__item[data-type]');
|
||||
if (!item) return;
|
||||
|
||||
event.preventDefault();
|
||||
var url = new URL(window.location.href);
|
||||
url.searchParams.set('msg_type', item.dataset.type);
|
||||
url.searchParams.delete('msg_page');
|
||||
window.location.href = url.toString();
|
||||
});
|
||||
|
||||
document.addEventListener('click', function (event) {
|
||||
var button = event.target.closest('.js-msg-mark-read');
|
||||
if (!button) return;
|
||||
|
||||
var id = button.dataset.id;
|
||||
var msgItem = button.closest('.message-item');
|
||||
post('aksrt_mark_notification_read', { notification_id: id }).then(function (result) {
|
||||
if (!result.success) return;
|
||||
|
||||
if (msgItem) {
|
||||
msgItem.classList.remove('is-unread');
|
||||
}
|
||||
button.remove();
|
||||
updateBadges(result.data && result.data.unread !== undefined ? result.data.unread : countUnread());
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener('click', function (event) {
|
||||
var button = event.target.closest('.js-msg-delete');
|
||||
if (!button) return;
|
||||
|
||||
var id = button.dataset.id;
|
||||
var msgItem = button.closest('.message-item');
|
||||
post('aksrt_delete_notification', { notification_id: id }).then(function (result) {
|
||||
if (!result.success) return;
|
||||
|
||||
if (msgItem) {
|
||||
msgItem.style.opacity = '0';
|
||||
msgItem.style.transform = 'translateX(20px)';
|
||||
msgItem.style.transition = 'all 0.2s';
|
||||
setTimeout(function () { msgItem.remove(); }, 200);
|
||||
}
|
||||
|
||||
updateBadges(result.data && result.data.unread !== undefined ? result.data.unread : countUnread());
|
||||
checkEmpty();
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener('click', function (event) {
|
||||
var button = event.target.closest('.js-msg-mark-all-read');
|
||||
if (!button) return;
|
||||
|
||||
post('aksrt_mark_notification_read', { mark_all: '1' }).then(function (result) {
|
||||
if (!result.success) return;
|
||||
|
||||
document.querySelectorAll('.message-item.is-unread').forEach(function (item) {
|
||||
item.classList.remove('is-unread');
|
||||
});
|
||||
document.querySelectorAll('.js-msg-mark-read').forEach(function (item) {
|
||||
item.remove();
|
||||
});
|
||||
updateBadges(0);
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener('click', function (event) {
|
||||
var button = event.target.closest('.js-msg-clear-read');
|
||||
if (!button) return;
|
||||
|
||||
var readItems = document.querySelectorAll('.message-item:not(.is-unread)');
|
||||
var ids = [];
|
||||
readItems.forEach(function (item) {
|
||||
var id = item.dataset.notificationId;
|
||||
if (id) ids.push(id);
|
||||
});
|
||||
if (!ids.length) return;
|
||||
|
||||
post('aksrt_delete_notifications', { notification_ids: ids }).then(function (result) {
|
||||
if (!result.success) return;
|
||||
|
||||
readItems.forEach(function (item) {
|
||||
item.style.opacity = '0';
|
||||
item.style.transform = 'translateX(20px)';
|
||||
item.style.transition = 'all 0.2s';
|
||||
setTimeout(function () { item.remove(); }, 200);
|
||||
});
|
||||
setTimeout(checkEmpty, 250);
|
||||
updateBadges(result.data && result.data.unread !== undefined ? result.data.unread : countUnread());
|
||||
});
|
||||
});
|
||||
|
||||
function countUnread() {
|
||||
return document.querySelectorAll('.message-item.is-unread').length;
|
||||
}
|
||||
|
||||
function updateBadges(unread) {
|
||||
var nextUnread = unread === undefined ? countUnread() : unread;
|
||||
|
||||
document.querySelectorAll('.messages-nav__badge[data-type="unread"]').forEach(function (badge) {
|
||||
badge.textContent = String(nextUnread);
|
||||
badge.dataset.count = String(nextUnread);
|
||||
badge.style.display = nextUnread > 0 ? '' : 'none';
|
||||
});
|
||||
|
||||
var headerBadge = document.querySelector('.user-dropdown__badge') || document.querySelector('.aksrt-notification-badge');
|
||||
if (headerBadge) {
|
||||
headerBadge.textContent = String(nextUnread);
|
||||
headerBadge.style.display = nextUnread > 0 ? '' : 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function checkEmpty() {
|
||||
var list = document.querySelector('.messages-list');
|
||||
if (list && list.children.length === 0) {
|
||||
list.outerHTML = '<div class="messages-empty"><span class="messages-empty__icon"><i class="fas fa-bell-slash"></i></span><p class="messages-empty__text">暂无消息</p></div>';
|
||||
}
|
||||
}
|
||||
|
||||
function startPolling() {
|
||||
pollTimer = setInterval(function () {
|
||||
post('aksrt_check_new_notifications', {}).then(function (result) {
|
||||
if (!result.success || !result.data) return;
|
||||
if (result.data.unread !== undefined) {
|
||||
updateBadges(result.data.unread);
|
||||
return;
|
||||
}
|
||||
if (result.data.count !== undefined) {
|
||||
updateBadges(result.data.count);
|
||||
}
|
||||
}).catch(function () {});
|
||||
}, pollInterval);
|
||||
}
|
||||
|
||||
startPolling();
|
||||
})();
|
||||
@@ -0,0 +1,256 @@
|
||||
/**
|
||||
* AKSRT Mini Touch — General Direction Gesture Engine
|
||||
*
|
||||
* Full direction gesture (top/bottom/left/right) via atan2 angle filtering,
|
||||
* real-time translate3d follow + cursor, onStart/onIng/onEnd callbacks,
|
||||
* compatible with swiper/scroll-x containers.
|
||||
*
|
||||
* Supports:
|
||||
* - [data-aksrt-swipe] left/right swipe triggers
|
||||
* - [data-aksrt-pull-dismiss] pull-to-dismiss with opacity tracking
|
||||
* - [data-mini-touch="mobile-nav"] mobile menu right-swipe close
|
||||
* - aksrt.minitouch(el, opts) programmatic API (from aksrt-runtime.js)
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var MIN_SWIPE_DISTANCE = 40;
|
||||
var MAX_SWIPE_TIME = 300;
|
||||
|
||||
function getDirection(angle) {
|
||||
if (angle >= -45 && angle < 45) return 'right';
|
||||
if (angle >= 45 && angle < 135) return 'bottom';
|
||||
if (angle >= -135 && angle < -45) return 'top';
|
||||
return 'left';
|
||||
}
|
||||
|
||||
// ── Declarative swipe: [data-aksrt-swipe] ──
|
||||
|
||||
function bindSwipe(container) {
|
||||
if (container.dataset.aksrtSwipeBound) return;
|
||||
container.dataset.aksrtSwipeBound = '1';
|
||||
|
||||
var startX = 0, startY = 0, startTime = 0;
|
||||
var moving = false;
|
||||
|
||||
container.addEventListener('touchstart', function (e) {
|
||||
if (e.touches.length !== 1) return;
|
||||
startX = e.touches[0].clientX;
|
||||
startY = e.touches[0].clientY;
|
||||
startTime = Date.now();
|
||||
moving = true;
|
||||
}, { passive: true });
|
||||
|
||||
container.addEventListener('touchmove', function (e) {
|
||||
if (!moving) return;
|
||||
var dx = e.touches[0].clientX - startX;
|
||||
var dy = e.touches[0].clientY - startY;
|
||||
if (Math.abs(dy) > Math.abs(dx) * 1.5) moving = false;
|
||||
}, { passive: true });
|
||||
|
||||
container.addEventListener('touchend', function (e) {
|
||||
if (!moving) return;
|
||||
moving = false;
|
||||
var ct = e.changedTouches ? e.changedTouches[0] : e;
|
||||
var dx = ct.clientX - startX;
|
||||
var dt = Date.now() - startTime;
|
||||
|
||||
if (dt > MAX_SWIPE_TIME || Math.abs(dx) < MIN_SWIPE_DISTANCE) return;
|
||||
if (Math.abs(ct.clientY - startY) > Math.abs(dx)) return;
|
||||
|
||||
var direction = dx > 0 ? 'right' : 'left';
|
||||
var selector = container.getAttribute('data-aksrt-swipe-' + direction);
|
||||
if (selector) {
|
||||
var target = container.querySelector(selector) || document.querySelector(selector);
|
||||
if (target) { target.click(); return; }
|
||||
}
|
||||
|
||||
container.dispatchEvent(new CustomEvent('aksrt:swipe', {
|
||||
detail: { direction: direction, distance: Math.abs(dx) },
|
||||
bubbles: true
|
||||
}));
|
||||
}, { passive: true });
|
||||
}
|
||||
|
||||
// ── Pull to dismiss with real-time opacity tracking ──
|
||||
|
||||
function bindPullDismiss(el) {
|
||||
if (el.dataset.aksrtPullBound) return;
|
||||
el.dataset.aksrtPullBound = '1';
|
||||
|
||||
var startY = 0, currentY = 0, pulling = false;
|
||||
|
||||
el.addEventListener('touchstart', function (e) {
|
||||
if (e.touches.length !== 1) return;
|
||||
// Disable pull when zoomed (scale > 1)
|
||||
var img = el.querySelector('img');
|
||||
if (img) {
|
||||
var transform = getComputedStyle(img).transform;
|
||||
if (transform && transform !== 'none') {
|
||||
var parts = transform.match(/matrix\(([^)]+)\)/);
|
||||
if (parts) {
|
||||
var vals = parts[1].split(',').map(Number);
|
||||
var scaleX = Math.sqrt(vals[0] * vals[0] + vals[1] * vals[1]);
|
||||
if (scaleX > 1.05) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (el.scrollTop > 0) return;
|
||||
startY = e.touches[0].clientY;
|
||||
currentY = startY;
|
||||
pulling = true;
|
||||
}, { passive: true });
|
||||
|
||||
el.addEventListener('touchmove', function (e) {
|
||||
if (!pulling) return;
|
||||
currentY = e.touches[0].clientY;
|
||||
var dy = currentY - startY;
|
||||
if (dy > 0) {
|
||||
var opacity = Math.max(0.2, (150 - dy) / 80);
|
||||
el.style.transform = 'translate3d(0, ' + (dy * 0.5) + 'px, 0)';
|
||||
el.style.opacity = String(Math.min(1, opacity));
|
||||
}
|
||||
}, { passive: true });
|
||||
|
||||
el.addEventListener('touchend', function () {
|
||||
if (!pulling) return;
|
||||
pulling = false;
|
||||
var dy = currentY - startY;
|
||||
|
||||
if (dy > 120) {
|
||||
el.style.transform = 'translate3d(0, ' + (dy + 100) + 'px, 0)';
|
||||
el.style.opacity = '0';
|
||||
el.style.transition = 'transform 0.2s ease-out, opacity 0.2s ease-out';
|
||||
setTimeout(function () {
|
||||
el.dispatchEvent(new CustomEvent('aksrt:pull-dismiss', { bubbles: true }));
|
||||
el.style.transform = '';
|
||||
el.style.opacity = '';
|
||||
el.style.transition = '';
|
||||
}, 200);
|
||||
} else {
|
||||
el.style.transition = 'transform 0.2s ease-out, opacity 0.2s ease-out';
|
||||
el.style.transform = '';
|
||||
el.style.opacity = '';
|
||||
setTimeout(function () { el.style.transition = ''; }, 200);
|
||||
}
|
||||
}, { passive: true });
|
||||
}
|
||||
|
||||
// ── [data-mini-touch="..."] declarative gesture ──
|
||||
|
||||
function bindMiniTouch(el) {
|
||||
if (el.dataset.miniTouchBound) return;
|
||||
el.dataset.miniTouchBound = '1';
|
||||
|
||||
var type = el.getAttribute('data-mini-touch');
|
||||
|
||||
if (type === 'mobile-nav') {
|
||||
bindMobileNavSwipe(el);
|
||||
} else if (type === 'bottom-close') {
|
||||
bindBottomClose(el);
|
||||
}
|
||||
}
|
||||
|
||||
function bindMobileNavSwipe(el) {
|
||||
var startX = 0, currentX = 0, active = false;
|
||||
|
||||
el.addEventListener('touchstart', function (e) {
|
||||
if (e.touches.length !== 1) return;
|
||||
startX = e.touches[0].clientX;
|
||||
currentX = startX;
|
||||
active = true;
|
||||
}, { passive: true });
|
||||
|
||||
el.addEventListener('touchmove', function (e) {
|
||||
if (!active) return;
|
||||
currentX = e.touches[0].clientX;
|
||||
var dx = currentX - startX;
|
||||
if (dx > 0) {
|
||||
el.style.transform = 'translateX(' + dx + 'px)';
|
||||
el.style.opacity = String(Math.max(0.3, 1 - dx / 300));
|
||||
}
|
||||
}, { passive: true });
|
||||
|
||||
el.addEventListener('touchend', function () {
|
||||
if (!active) return;
|
||||
active = false;
|
||||
var dx = currentX - startX;
|
||||
if (dx > 80) {
|
||||
el.style.transform = 'translateX(100%)';
|
||||
el.style.opacity = '0';
|
||||
setTimeout(function () {
|
||||
el.classList.remove('is-open');
|
||||
el.style.transform = '';
|
||||
el.style.opacity = '';
|
||||
document.body.classList.remove('nav-open');
|
||||
}, 200);
|
||||
} else {
|
||||
el.style.transition = 'transform 0.2s, opacity 0.2s';
|
||||
el.style.transform = '';
|
||||
el.style.opacity = '';
|
||||
setTimeout(function () { el.style.transition = ''; }, 200);
|
||||
}
|
||||
}, { passive: true });
|
||||
}
|
||||
|
||||
function bindBottomClose(el) {
|
||||
var startY = 0, currentY = 0, active = false;
|
||||
|
||||
el.addEventListener('touchstart', function (e) {
|
||||
if (e.touches.length !== 1) return;
|
||||
startY = e.touches[0].clientY;
|
||||
currentY = startY;
|
||||
active = true;
|
||||
}, { passive: true });
|
||||
|
||||
el.addEventListener('touchmove', function (e) {
|
||||
if (!active) return;
|
||||
currentY = e.touches[0].clientY;
|
||||
var dy = currentY - startY;
|
||||
if (dy > 0) {
|
||||
el.style.transform = 'translateY(' + dy + 'px)';
|
||||
}
|
||||
}, { passive: true });
|
||||
|
||||
el.addEventListener('touchend', function () {
|
||||
if (!active) return;
|
||||
active = false;
|
||||
var dy = currentY - startY;
|
||||
if (dy > 80) {
|
||||
el.dispatchEvent(new CustomEvent('aksrt:pull-dismiss', { bubbles: true }));
|
||||
}
|
||||
el.style.transform = '';
|
||||
}, { passive: true });
|
||||
}
|
||||
|
||||
// ── Auto-init ──
|
||||
|
||||
function init() {
|
||||
document.querySelectorAll('[data-aksrt-swipe]').forEach(bindSwipe);
|
||||
document.querySelectorAll('[data-aksrt-pull-dismiss]').forEach(bindPullDismiss);
|
||||
document.querySelectorAll('[data-mini-touch]').forEach(bindMiniTouch);
|
||||
|
||||
document.addEventListener('aksrt:lightbox-open', function (e) {
|
||||
var lightbox = e.target;
|
||||
if (lightbox) bindPullDismiss(lightbox);
|
||||
});
|
||||
}
|
||||
|
||||
// Register for rehydration
|
||||
if (window.AksrtFrontend) {
|
||||
AksrtFrontend.register('aksrt-mini-touch', function (root) {
|
||||
(root || document).querySelectorAll('[data-aksrt-swipe]').forEach(bindSwipe);
|
||||
(root || document).querySelectorAll('[data-aksrt-pull-dismiss]').forEach(bindPullDismiss);
|
||||
(root || document).querySelectorAll('[data-mini-touch]').forEach(bindMiniTouch);
|
||||
});
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,332 @@
|
||||
/**
|
||||
* AKSRT Mini Upload — 小型文件上传器
|
||||
*
|
||||
* 提供拖拽上传、进度显示、预览功能。
|
||||
* 用于前台投稿、商品编辑等需要文件上传的页面。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* 初始化小型上传器
|
||||
*
|
||||
* @param {HTMLElement} container 上传器容器
|
||||
* @param {Object} options 配置项
|
||||
*/
|
||||
function MiniUpload(container, options) {
|
||||
if (!container) return;
|
||||
|
||||
this.options = Object.assign({
|
||||
maxFileSize: 5 * 1024 * 1024, // 5MB
|
||||
allowedTypes: ['image/jpeg', 'image/png', 'image/gif', 'image/webp'],
|
||||
multiple: false,
|
||||
uploadUrl: '',
|
||||
fieldName: 'file',
|
||||
nonce: '',
|
||||
onSelect: null,
|
||||
onSuccess: null,
|
||||
onError: null,
|
||||
}, options || {});
|
||||
|
||||
this.container = container;
|
||||
this.files = [];
|
||||
this.init();
|
||||
}
|
||||
|
||||
MiniUpload.prototype.init = function () {
|
||||
var self = this;
|
||||
|
||||
// 创建文件输入
|
||||
this.input = document.createElement('input');
|
||||
this.input.type = 'file';
|
||||
this.input.accept = this.options.allowedTypes.join(',');
|
||||
this.input.multiple = this.options.multiple;
|
||||
this.input.style.display = 'none';
|
||||
this.container.appendChild(this.input);
|
||||
|
||||
// 创建拖拽区域
|
||||
this.dropzone = document.createElement('div');
|
||||
this.dropzone.className = 'aksrt-mini-upload__dropzone';
|
||||
this.dropzone.innerHTML =
|
||||
'<div class="aksrt-mini-upload__icon"><i class="fas fa-cloud-upload-alt"></i></div>' +
|
||||
'<div class="aksrt-mini-upload__text">点击或拖拽文件到此处上传</div>' +
|
||||
'<div class="aksrt-mini-upload__hint">支持 ' + this.options.allowedTypes.map(function (t) {
|
||||
return t.split('/')[1].toUpperCase();
|
||||
}).join(', ') + ',最大 ' + Math.round(this.options.maxFileSize / 1024 / 1024) + 'MB</div>';
|
||||
this.container.appendChild(this.dropzone);
|
||||
|
||||
// 创建预览区域
|
||||
this.preview = document.createElement('div');
|
||||
this.preview.className = 'aksrt-mini-upload__preview';
|
||||
this.container.appendChild(this.preview);
|
||||
|
||||
// 事件绑定
|
||||
this.dropzone.addEventListener('click', function () {
|
||||
self.input.click();
|
||||
});
|
||||
|
||||
this.dropzone.addEventListener('dragover', function (e) {
|
||||
e.preventDefault();
|
||||
self.dropzone.classList.add('aksrt-mini-upload__dropzone--dragover');
|
||||
});
|
||||
|
||||
this.dropzone.addEventListener('dragleave', function () {
|
||||
self.dropzone.classList.remove('aksrt-mini-upload__dropzone--dragover');
|
||||
});
|
||||
|
||||
this.dropzone.addEventListener('drop', function (e) {
|
||||
e.preventDefault();
|
||||
self.dropzone.classList.remove('aksrt-mini-upload__dropzone--dragover');
|
||||
if (e.dataTransfer.files.length > 0) {
|
||||
self.handleFiles(e.dataTransfer.files);
|
||||
}
|
||||
});
|
||||
|
||||
this.input.addEventListener('change', function () {
|
||||
if (self.input.files.length > 0) {
|
||||
self.handleFiles(self.input.files);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
MiniUpload.prototype.handleFiles = function (fileList) {
|
||||
var self = this;
|
||||
var files = Array.prototype.slice.call(fileList);
|
||||
|
||||
files.forEach(function (file) {
|
||||
// 验证文件类型
|
||||
if (self.options.allowedTypes.length > 0 && self.options.allowedTypes.indexOf(file.type) === -1) {
|
||||
self.showError('不支持的文件类型: ' + file.type);
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证文件大小
|
||||
if (file.size > self.options.maxFileSize) {
|
||||
self.showError('文件大小超过限制: ' + Math.round(file.size / 1024 / 1024) + 'MB');
|
||||
return;
|
||||
}
|
||||
|
||||
self.files.push(file);
|
||||
self.addPreview(file);
|
||||
|
||||
if (typeof self.options.onSelect === 'function') {
|
||||
self.options.onSelect(file);
|
||||
}
|
||||
|
||||
// 如果有上传 URL,自动上传
|
||||
if (self.options.uploadUrl) {
|
||||
self.uploadFile(file);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
MiniUpload.prototype.addPreview = function (file) {
|
||||
var self = this;
|
||||
var item = document.createElement('div');
|
||||
item.className = 'aksrt-mini-upload__item';
|
||||
|
||||
if (file.type.startsWith('image/')) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function (e) {
|
||||
item.innerHTML =
|
||||
'<img src="' + e.target.result + '" class="aksrt-mini-upload__thumb">' +
|
||||
'<div class="aksrt-mini-upload__info">' +
|
||||
'<span class="aksrt-mini-upload__name">' + file.name + '</span>' +
|
||||
'<span class="aksrt-mini-upload__size">' + self.formatSize(file.size) + '</span>' +
|
||||
'</div>' +
|
||||
'<button type="button" class="aksrt-mini-upload__remove"><i class="fas fa-times"></i></button>' +
|
||||
'<div class="aksrt-mini-upload__progress"><div class="aksrt-mini-upload__progress-bar"></div></div>';
|
||||
self.bindRemove(item, file);
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
} else {
|
||||
item.innerHTML =
|
||||
'<div class="aksrt-mini-upload__file-icon"><i class="fas fa-file"></i></div>' +
|
||||
'<div class="aksrt-mini-upload__info">' +
|
||||
'<span class="aksrt-mini-upload__name">' + file.name + '</span>' +
|
||||
'<span class="aksrt-mini-upload__size">' + self.formatSize(file.size) + '</span>' +
|
||||
'</div>' +
|
||||
'<button type="button" class="aksrt-mini-upload__remove"><i class="fas fa-times"></i></button>' +
|
||||
'<div class="aksrt-mini-upload__progress"><div class="aksrt-mini-upload__progress-bar"></div></div>';
|
||||
this.bindRemove(item, file);
|
||||
}
|
||||
|
||||
this.preview.appendChild(item);
|
||||
};
|
||||
|
||||
MiniUpload.prototype.bindRemove = function (item, file) {
|
||||
var self = this;
|
||||
var removeBtn = item.querySelector('.aksrt-mini-upload__remove');
|
||||
if (removeBtn) {
|
||||
removeBtn.addEventListener('click', function () {
|
||||
var index = self.files.indexOf(file);
|
||||
if (index > -1) self.files.splice(index, 1);
|
||||
item.remove();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
MiniUpload.prototype.uploadFile = function (file) {
|
||||
var self = this;
|
||||
var formData = new FormData();
|
||||
formData.append(this.options.fieldName, file);
|
||||
|
||||
if (this.options.nonce) {
|
||||
formData.append('_wpnonce', this.options.nonce);
|
||||
}
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', this.options.uploadUrl, true);
|
||||
|
||||
// 进度更新
|
||||
var item = this.preview.lastElementChild;
|
||||
var progressBar = item ? item.querySelector('.aksrt-mini-upload__progress-bar') : null;
|
||||
|
||||
xhr.upload.onprogress = function (e) {
|
||||
if (e.lengthComputable && progressBar) {
|
||||
var percent = Math.round((e.loaded / e.total) * 100);
|
||||
progressBar.style.width = percent + '%';
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onload = function () {
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
try {
|
||||
var response = JSON.parse(xhr.responseText);
|
||||
if (typeof self.options.onSuccess === 'function') {
|
||||
self.options.onSuccess(response, file);
|
||||
}
|
||||
if (item) item.classList.add('aksrt-mini-upload__item--success');
|
||||
} catch (e) {
|
||||
self.showError('上传响应解析失败');
|
||||
}
|
||||
} else {
|
||||
self.showError('上传失败: HTTP ' + xhr.status);
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onerror = function () {
|
||||
self.showError('网络错误,上传失败');
|
||||
if (item) item.classList.add('aksrt-mini-upload__item--error');
|
||||
};
|
||||
|
||||
xhr.send(formData);
|
||||
};
|
||||
|
||||
MiniUpload.prototype.showError = function (msg) {
|
||||
if (typeof this.options.onError === 'function') {
|
||||
this.options.onError(msg);
|
||||
}
|
||||
console.error('[AKSRT MiniUpload]', msg);
|
||||
};
|
||||
|
||||
MiniUpload.prototype.formatSize = function (bytes) {
|
||||
if (bytes < 1024) return bytes + ' B';
|
||||
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
|
||||
return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
|
||||
};
|
||||
|
||||
MiniUpload.prototype.getFiles = function () {
|
||||
return this.files;
|
||||
};
|
||||
|
||||
MiniUpload.prototype.clear = function () {
|
||||
this.files = [];
|
||||
this.preview.innerHTML = '';
|
||||
this.input.value = '';
|
||||
};
|
||||
|
||||
/**
|
||||
* 分片上传大文件
|
||||
* @param {File} file - 要上传的文件
|
||||
* @param {Object} opts - { chunkSize, uploadUrl, fieldName, nonce, onProgress, onComplete, onError }
|
||||
*/
|
||||
MiniUpload.prototype.uploadChunked = function (file, opts) {
|
||||
var chunkSize = (opts.chunkSize || 2) * 1024 * 1024; // default 2MB
|
||||
var totalChunks = Math.ceil(file.size / chunkSize);
|
||||
var currentChunk = 0;
|
||||
var fileId = file.name + '-' + file.size + '-' + file.lastModified;
|
||||
|
||||
function uploadNext() {
|
||||
if (currentChunk >= totalChunks) {
|
||||
if (opts.onComplete) opts.onComplete({ fileId: fileId, totalChunks: totalChunks });
|
||||
return;
|
||||
}
|
||||
|
||||
var start = currentChunk * chunkSize;
|
||||
var end = Math.min(start + chunkSize, file.size);
|
||||
var blob = file.slice(start, end);
|
||||
|
||||
var formData = new FormData();
|
||||
formData.append(opts.fieldName || 'file', blob, file.name);
|
||||
formData.append('chunk', currentChunk);
|
||||
formData.append('total_chunks', totalChunks);
|
||||
formData.append('file_id', fileId);
|
||||
formData.append('file_name', file.name);
|
||||
formData.append('file_size', file.size);
|
||||
if (opts.nonce) formData.append('_ajax_nonce', opts.nonce);
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', opts.uploadUrl, true);
|
||||
|
||||
xhr.upload.onprogress = function (e) {
|
||||
if (e.lengthComputable && opts.onProgress) {
|
||||
var chunkProgress = e.loaded / e.total;
|
||||
var totalProgress = (currentChunk + chunkProgress) / totalChunks;
|
||||
opts.onProgress(totalProgress, currentChunk, totalChunks);
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onload = function () {
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
currentChunk++;
|
||||
uploadNext();
|
||||
} else {
|
||||
if (opts.onError) opts.onError('上传失败: HTTP ' + xhr.status);
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onerror = function () {
|
||||
if (opts.onError) opts.onError('网络错误');
|
||||
};
|
||||
|
||||
xhr.send(formData);
|
||||
}
|
||||
|
||||
uploadNext();
|
||||
};
|
||||
|
||||
/**
|
||||
* 快速文件标识(替代 spark-md5,用文件名+大小+最后修改时间生成简易 hash)
|
||||
*/
|
||||
MiniUpload.prototype.getFileId = function (file) {
|
||||
return file.name + '-' + file.size + '-' + file.lastModified;
|
||||
};
|
||||
|
||||
// 自动初始化
|
||||
function autoInit() {
|
||||
document.querySelectorAll('[data-aksrt-mini-upload]').forEach(function (el) {
|
||||
if (el.dataset.miniUploadInit) return;
|
||||
el.dataset.miniUploadInit = '1';
|
||||
|
||||
var options = {};
|
||||
try {
|
||||
options = JSON.parse(el.dataset.aksrtMiniUpload || '{}');
|
||||
} catch (e) {}
|
||||
|
||||
new MiniUpload(el, options);
|
||||
});
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', autoInit);
|
||||
} else {
|
||||
autoInit();
|
||||
}
|
||||
|
||||
// 暴露到全局
|
||||
window.AksrtMiniUpload = MiniUpload;
|
||||
})();
|
||||
@@ -0,0 +1,484 @@
|
||||
/**
|
||||
* AKSRT modal auth interactions.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var API_ROOT = (window.aksrtData && window.aksrtData.apiUrl) || '/wp-json/aksrt/v1';
|
||||
var NONCE = (window.aksrtData && window.aksrtData.restNonce) || '';
|
||||
|
||||
var modal = null;
|
||||
var currentTab = 'login';
|
||||
|
||||
function init() {
|
||||
modal = document.getElementById('aksrt-modal-auth');
|
||||
if (!modal) {
|
||||
return;
|
||||
}
|
||||
|
||||
var closeBtn = modal.querySelector('.aksrt-modal-auth__close');
|
||||
var overlay = modal.querySelector('.aksrt-modal-auth__overlay');
|
||||
if (closeBtn) {
|
||||
closeBtn.addEventListener('click', close);
|
||||
}
|
||||
if (overlay) {
|
||||
overlay.addEventListener('click', close);
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', function (event) {
|
||||
if (event.key === 'Escape' && modal.classList.contains('is-open')) {
|
||||
close();
|
||||
}
|
||||
});
|
||||
|
||||
modal.querySelectorAll('.aksrt-modal-auth__tab').forEach(function (tab) {
|
||||
tab.addEventListener('click', function () {
|
||||
switchTab(this.dataset.tab || 'login');
|
||||
});
|
||||
});
|
||||
|
||||
modal.querySelectorAll('.aksrt-modal-auth__switch').forEach(function (button) {
|
||||
button.addEventListener('click', function () {
|
||||
switchTab(this.dataset.switch || 'login');
|
||||
});
|
||||
});
|
||||
|
||||
modal.querySelectorAll('.aksrt-modal-auth__pass-toggle').forEach(function (button) {
|
||||
button.addEventListener('click', function () {
|
||||
var input = this.parentElement.querySelector('input');
|
||||
var icon = this.querySelector('i');
|
||||
if (!input || !icon) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (input.type === 'password') {
|
||||
input.type = 'text';
|
||||
icon.className = 'far fa-eye-slash';
|
||||
} else {
|
||||
input.type = 'password';
|
||||
icon.className = 'far fa-eye';
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var loginForm = document.getElementById('aksrt-modal-login-form');
|
||||
if (loginForm) {
|
||||
loginForm.addEventListener('submit', function (event) {
|
||||
event.preventDefault();
|
||||
handleLogin(loginForm);
|
||||
});
|
||||
}
|
||||
|
||||
var registerForm = document.getElementById('aksrt-modal-register-form');
|
||||
if (registerForm) {
|
||||
registerForm.addEventListener('submit', function (event) {
|
||||
event.preventDefault();
|
||||
handleRegister(registerForm);
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('click', function (event) {
|
||||
var trigger = event.target.closest('[data-aksrt-auth-required], .aksrt-login-trigger, #nav-login-btn, .signin-loader, .signup-loader, .qrcode-signin');
|
||||
if (!trigger) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
if (trigger.classList.contains('signup-loader')) {
|
||||
open(trigger.dataset.authRedirect || '');
|
||||
switchTab('register');
|
||||
return;
|
||||
}
|
||||
if (trigger.classList.contains('qrcode-signin')) {
|
||||
open(trigger.dataset.authRedirect || '');
|
||||
switchTab('qrcode');
|
||||
return;
|
||||
}
|
||||
|
||||
open(trigger.dataset.authRedirect || '');
|
||||
});
|
||||
|
||||
initQrLogin();
|
||||
initAgreementShake();
|
||||
initSocialPriority();
|
||||
}
|
||||
|
||||
function open(redirectUrl) {
|
||||
if (!modal) {
|
||||
return;
|
||||
}
|
||||
|
||||
modal.classList.add('is-open');
|
||||
modal.setAttribute('aria-hidden', 'false');
|
||||
document.body.style.overflow = 'hidden';
|
||||
|
||||
if (redirectUrl) {
|
||||
modal.dataset.redirect = redirectUrl;
|
||||
}
|
||||
|
||||
setTimeout(function () {
|
||||
var firstInput = modal.querySelector('.aksrt-modal-auth__panel.is-active input:not([type="hidden"])');
|
||||
if (firstInput) {
|
||||
firstInput.focus();
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
var qrLoginTimer = null;
|
||||
|
||||
function close() {
|
||||
if (!modal) {
|
||||
return;
|
||||
}
|
||||
|
||||
modal.classList.remove('is-open');
|
||||
modal.setAttribute('aria-hidden', 'true');
|
||||
document.body.style.overflow = '';
|
||||
clearMessages();
|
||||
stopQrPolling();
|
||||
}
|
||||
|
||||
function switchTab(tab) {
|
||||
currentTab = tab;
|
||||
|
||||
modal.querySelectorAll('.aksrt-modal-auth__tab').forEach(function (button) {
|
||||
var isActive = button.dataset.tab === tab;
|
||||
button.classList.toggle('is-active', isActive);
|
||||
button.setAttribute('aria-selected', isActive ? 'true' : 'false');
|
||||
});
|
||||
|
||||
modal.querySelectorAll('.aksrt-modal-auth__panel').forEach(function (panel) {
|
||||
panel.classList.toggle('is-active', panel.dataset.panel === tab);
|
||||
});
|
||||
|
||||
modal.querySelectorAll('.aksrt-modal-auth__footer-text').forEach(function (row) {
|
||||
row.hidden = row.dataset.for !== tab;
|
||||
});
|
||||
|
||||
modal.setAttribute('aria-label', tab === 'register' ? '注册' : '登录');
|
||||
clearMessages();
|
||||
}
|
||||
|
||||
function handleLogin(form) {
|
||||
var payload = serializeForm(form);
|
||||
if (!payload.log || !payload.pwd) {
|
||||
showMessage('login', '请输入用户名和密码', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(form, true);
|
||||
clearMessages();
|
||||
|
||||
request('/auth/modal-login', payload)
|
||||
.then(function (result) {
|
||||
if (result.ok && result.data.success) {
|
||||
onAuthSuccess(result.data);
|
||||
return;
|
||||
}
|
||||
|
||||
var message = result.data.message || '登录失败';
|
||||
if (result.data.verify_url) {
|
||||
message += ' <a href="' + escapeAttribute(result.data.verify_url) + '">前往验证</a>';
|
||||
}
|
||||
showMessage('login', message, 'error');
|
||||
})
|
||||
.catch(function () {
|
||||
showMessage('login', '网络错误,请稍后重试', 'error');
|
||||
})
|
||||
.finally(function () {
|
||||
setLoading(form, false);
|
||||
});
|
||||
}
|
||||
|
||||
function handleRegister(form) {
|
||||
var payload = serializeForm(form);
|
||||
if (!payload.user_login || !payload.user_email || !payload.user_pass || !payload.user_pass_confirm) {
|
||||
showMessage('register', '请完整填写注册信息', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (payload.user_pass !== payload.user_pass_confirm) {
|
||||
showMessage('register', '两次输入的密码不一致', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(form, true);
|
||||
clearMessages();
|
||||
|
||||
request('/auth/modal-register', payload)
|
||||
.then(function (result) {
|
||||
if (!result.ok || !result.data.success) {
|
||||
showMessage('register', result.data.message || '注册失败', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.data.user) {
|
||||
onAuthSuccess(result.data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.data.verification_required) {
|
||||
var verifyMessage = result.data.message || '注册成功,请完成邮箱验证';
|
||||
if (result.data.verify_url) {
|
||||
verifyMessage += ' <a href="' + escapeAttribute(result.data.verify_url) + '">前往验证</a>';
|
||||
}
|
||||
showMessage('register', verifyMessage, 'success');
|
||||
form.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
var loginMessage = result.data.message || '注册成功,请登录';
|
||||
switchTab('login');
|
||||
prefillLogin(result.data.user_login || result.data.user_email || '');
|
||||
showMessage('login', loginMessage, 'success');
|
||||
form.reset();
|
||||
})
|
||||
.catch(function () {
|
||||
showMessage('register', '网络错误,请稍后重试', 'error');
|
||||
})
|
||||
.finally(function () {
|
||||
setLoading(form, false);
|
||||
});
|
||||
}
|
||||
|
||||
function serializeForm(form) {
|
||||
var payload = {};
|
||||
var formData = new FormData(form);
|
||||
|
||||
formData.forEach(function (value, key) {
|
||||
if (payload[key] !== undefined) {
|
||||
if (!Array.isArray(payload[key])) {
|
||||
payload[key] = [payload[key]];
|
||||
}
|
||||
payload[key].push(value);
|
||||
} else {
|
||||
payload[key] = value;
|
||||
}
|
||||
});
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
function request(path, payload) {
|
||||
var headers = { 'Content-Type': 'application/json' };
|
||||
if (NONCE) {
|
||||
headers['X-WP-Nonce'] = NONCE;
|
||||
}
|
||||
|
||||
return fetch(API_ROOT + path, {
|
||||
method: 'POST',
|
||||
headers: headers,
|
||||
body: JSON.stringify(payload),
|
||||
}).then(function (response) {
|
||||
return response.json().then(function (data) {
|
||||
return { ok: response.ok, data: data };
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function prefillLogin(value) {
|
||||
var loginInput = document.getElementById('modal-login-user');
|
||||
if (loginInput && value) {
|
||||
loginInput.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
function onAuthSuccess(data) {
|
||||
close();
|
||||
|
||||
if (data.user) {
|
||||
updateNavUser(data.user);
|
||||
}
|
||||
|
||||
if (window.aksrt && aksrt.notyf) {
|
||||
aksrt.notyf(data.message || '登录成功', 'success');
|
||||
} else if (typeof window.aksrtToast === 'function') {
|
||||
window.aksrtToast(data.message || '登录成功', 'success');
|
||||
}
|
||||
|
||||
var redirect = modal.dataset.redirect || data.redirect;
|
||||
if (redirect && redirect !== window.location.href) {
|
||||
setTimeout(function () {
|
||||
window.location.href = redirect;
|
||||
}, 500);
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout(function () {
|
||||
window.location.reload();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
function updateNavUser(user) {
|
||||
document.querySelectorAll('.nav-user__avatar img, .nav-user__toggle img').forEach(function (image) {
|
||||
if (user.avatar_url) {
|
||||
image.src = user.avatar_url;
|
||||
}
|
||||
});
|
||||
|
||||
document.querySelectorAll('.nav-user__name').forEach(function (el) {
|
||||
if (user.display_name) {
|
||||
el.textContent = user.display_name;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function showMessage(panel, message, type) {
|
||||
var box = document.getElementById('aksrt-modal-' + panel + '-error');
|
||||
if (!box) {
|
||||
return;
|
||||
}
|
||||
|
||||
box.innerHTML = message;
|
||||
box.hidden = false;
|
||||
box.classList.toggle('is-success', type === 'success');
|
||||
}
|
||||
|
||||
function clearMessages() {
|
||||
if (!modal) {
|
||||
return;
|
||||
}
|
||||
|
||||
modal.querySelectorAll('.aksrt-modal-auth__error').forEach(function (box) {
|
||||
box.hidden = true;
|
||||
box.innerHTML = '';
|
||||
box.classList.remove('is-success');
|
||||
});
|
||||
}
|
||||
|
||||
function setLoading(form, loading) {
|
||||
var submit = form.querySelector('.aksrt-modal-auth__submit');
|
||||
if (!submit) {
|
||||
return;
|
||||
}
|
||||
|
||||
var label = submit.querySelector('span');
|
||||
var spinner = submit.querySelector('i');
|
||||
submit.disabled = loading;
|
||||
|
||||
if (label) {
|
||||
label.hidden = loading;
|
||||
}
|
||||
if (spinner) {
|
||||
spinner.hidden = !loading;
|
||||
}
|
||||
}
|
||||
|
||||
function escapeAttribute(value) {
|
||||
return String(value || '')
|
||||
.replace(/&/g, '&')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>');
|
||||
}
|
||||
|
||||
// ── QR Code Login (§10.7) ──
|
||||
|
||||
function initQrLogin() {
|
||||
var qrPanel = modal.querySelector('[data-panel="qrcode"]');
|
||||
if (!qrPanel) return;
|
||||
|
||||
var qrContainer = qrPanel.querySelector('.aksrt-modal-auth__qr-code');
|
||||
if (!qrContainer) return;
|
||||
|
||||
// When qrcode tab is activated, fetch QR and start polling
|
||||
var observer = new MutationObserver(function () {
|
||||
if (qrPanel.classList.contains('is-active')) {
|
||||
fetchQrCode(qrContainer);
|
||||
} else {
|
||||
stopQrPolling();
|
||||
}
|
||||
});
|
||||
observer.observe(qrPanel, { attributes: true, attributeFilter: ['class'] });
|
||||
}
|
||||
|
||||
function fetchQrCode(container) {
|
||||
container.innerHTML = '<div class="aksrt-modal-auth__qr-loading"><i class="fas fa-spinner fa-spin"></i></div>';
|
||||
|
||||
request('/auth/qrcode-login', {})
|
||||
.then(function (result) {
|
||||
if (result.ok && result.data && result.data.qr_html) {
|
||||
container.innerHTML = result.data.qr_html;
|
||||
startQrPolling(result.data.check_url || '/auth/check-qrcode-login', result.data.token || '');
|
||||
} else {
|
||||
container.innerHTML = '<p class="aksrt-modal-auth__qr-error">扫码登录暂不可用</p>';
|
||||
}
|
||||
})
|
||||
.catch(function () {
|
||||
container.innerHTML = '<p class="aksrt-modal-auth__qr-error">网络错误</p>';
|
||||
});
|
||||
}
|
||||
|
||||
function startQrPolling(checkUrl, token) {
|
||||
stopQrPolling();
|
||||
qrLoginTimer = setInterval(function () {
|
||||
request(checkUrl, { token: token })
|
||||
.then(function (result) {
|
||||
if (result.ok && result.data && result.data.logged_in) {
|
||||
stopQrPolling();
|
||||
onAuthSuccess(result.data);
|
||||
}
|
||||
})
|
||||
.catch(function () { /* keep polling */ });
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
function stopQrPolling() {
|
||||
if (qrLoginTimer) {
|
||||
clearInterval(qrLoginTimer);
|
||||
qrLoginTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
// ── Social Login Priority (§10.7) ──
|
||||
|
||||
function initSocialPriority() {
|
||||
var wxPriority = window.aksrtData && aksrtData.signinWxPriority;
|
||||
if (wxPriority && modal) {
|
||||
var wxBtn = modal.querySelector('.social-login-item.weixingzh, .social-login-item[data-provider="wechat"]');
|
||||
if (wxBtn) {
|
||||
setTimeout(function () { wxBtn.click(); }, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Agreement Check: shake instead of disable (§10.7) ──
|
||||
|
||||
function initAgreementShake() {
|
||||
if (!modal) return;
|
||||
modal.querySelectorAll('.aksrt-modal-auth__submit').forEach(function (btn) {
|
||||
btn.addEventListener('click', function (e) {
|
||||
var form = btn.closest('form');
|
||||
if (!form) return;
|
||||
var agree = form.querySelector('[name="user_agreement"]');
|
||||
if (agree && !agree.checked) {
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
agree.closest('label, .aksrt-modal-auth__agreement').classList.add('ani', 'shake');
|
||||
if (window.aksrt && aksrt.notyf) aksrt.notyf('请先同意用户协议', 'warning');
|
||||
setTimeout(function () {
|
||||
agree.closest('label, .aksrt-modal-auth__agreement').classList.remove('ani', 'shake');
|
||||
}, 400);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ── Password Visibility: unified (§10.7) ──
|
||||
// Already handled above; added unification note.
|
||||
|
||||
window.AksrtAuth = {
|
||||
open: open,
|
||||
close: close,
|
||||
};
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,306 @@
|
||||
/**
|
||||
* AKSRT Order Center — v2.0
|
||||
*
|
||||
* 前台订单中心交互:
|
||||
* - 支付 / 取消 / 售后:操作成功后局部刷新订单卡片,不再整页 reload
|
||||
* - 倒计时
|
||||
* - Toast 通知替代 window.alert
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
var page = document.querySelector("[data-aksrt-order-center]");
|
||||
if (!page || !window.aksrtData) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* ── Toast helper ── */
|
||||
function showToast(text, duration) {
|
||||
duration = duration || 2500;
|
||||
var container = document.getElementById("toast-container");
|
||||
if (!container) {
|
||||
container = document.createElement("div");
|
||||
container.id = "toast-container";
|
||||
container.style.cssText = "position:fixed;bottom:24px;right:24px;z-index:99999;display:flex;flex-direction:column-reverse;gap:10px;pointer-events:none;";
|
||||
document.body.appendChild(container);
|
||||
}
|
||||
var toast = document.createElement("div");
|
||||
toast.style.cssText = "pointer-events:auto;display:flex;align-items:center;gap:8px;padding:10px 20px;background:rgba(0,0,0,0.78);backdrop-filter:blur(12px);color:#fff;font-family:var(--font-ui);font-size:14px;font-weight:500;border-radius:100px;box-shadow:0 4px 20px rgba(0,0,0,0.2);animation:aksrtToastIn 0.35s cubic-bezier(0.22,1,0.36,1) forwards;white-space:nowrap;";
|
||||
toast.textContent = text;
|
||||
container.appendChild(toast);
|
||||
setTimeout(function () {
|
||||
toast.style.animation = "aksrtToastOut 0.4s ease forwards";
|
||||
setTimeout(function () { if (toast.parentNode) toast.parentNode.removeChild(toast); }, 400);
|
||||
}, duration);
|
||||
}
|
||||
|
||||
// Inject toast keyframes if not present
|
||||
if (!document.getElementById("aksrt-toast-keyframes")) {
|
||||
var style = document.createElement("style");
|
||||
style.id = "aksrt-toast-keyframes";
|
||||
style.textContent = "@keyframes aksrtToastIn{0%{opacity:0;transform:translateY(16px) scale(0.92)}100%{opacity:1;transform:translateY(0) scale(1)}}@keyframes aksrtToastOut{0%{opacity:1;transform:translateY(0) scale(1)}100%{opacity:0;transform:translateY(8px) scale(0.95)}}";
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
|
||||
/* ── REST helper ── */
|
||||
function request(path, body) {
|
||||
return fetch("/wp-json/aksrt/v1" + path, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-WP-Nonce": aksrtData.restNonce
|
||||
},
|
||||
body: JSON.stringify(body || {})
|
||||
}).then(function (response) {
|
||||
return response.json();
|
||||
});
|
||||
}
|
||||
|
||||
/* ── 扫码支付弹层(微信 Native code_url 等)── */
|
||||
function showPaymentQr(content, orderNumber) {
|
||||
var existing = document.getElementById("aksrt-pay-qr-overlay");
|
||||
if (existing) existing.remove();
|
||||
|
||||
var overlay = document.createElement("div");
|
||||
overlay.id = "aksrt-pay-qr-overlay";
|
||||
overlay.style.cssText = "position:fixed;inset:0;z-index:100000;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,0.5);";
|
||||
|
||||
var qrImg = "";
|
||||
if (window.AksrtShare && typeof window.AksrtShare.buildQrDataUrl === "function") {
|
||||
var dataUrl = window.AksrtShare.buildQrDataUrl(content, 220);
|
||||
if (dataUrl) {
|
||||
qrImg = '<img src="' + dataUrl + '" alt="支付二维码" width="220" height="220" style="display:block;margin:0 auto;">';
|
||||
}
|
||||
}
|
||||
if (!qrImg) {
|
||||
qrImg = '<p style="word-break:break-all;font-size:12px;color:#666;">' + String(content).replace(/[<>&]/g, "") + "</p>";
|
||||
}
|
||||
|
||||
var card = document.createElement("div");
|
||||
card.style.cssText = "background:#fff;border-radius:12px;padding:24px;max-width:300px;text-align:center;box-shadow:0 10px 40px rgba(0,0,0,0.2);";
|
||||
card.innerHTML =
|
||||
'<h3 style="margin:0 0 12px;font-size:16px;">请扫码完成支付</h3>' +
|
||||
qrImg +
|
||||
'<p style="margin:12px 0 0;font-size:13px;color:#888;">支付完成后本页将自动更新</p>' +
|
||||
'<button type="button" id="aksrt-pay-qr-close" style="margin-top:14px;padding:8px 20px;border:none;border-radius:8px;background:var(--color-primary,#f04494);color:#fff;cursor:pointer;">完成 / 关闭</button>';
|
||||
overlay.appendChild(card);
|
||||
document.body.appendChild(overlay);
|
||||
|
||||
function close() { overlay.remove(); }
|
||||
overlay.addEventListener("click", function (e) { if (e.target === overlay) close(); });
|
||||
card.querySelector("#aksrt-pay-qr-close").addEventListener("click", function () {
|
||||
close();
|
||||
// 关闭后查询订单是否已到账
|
||||
if (orderNumber) {
|
||||
request("/shop/frontend/orders/" + orderNumber, {}).then(function () {
|
||||
window.location.reload();
|
||||
}).catch(function () {});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* ── 第三方支付返回提示(?payment=success|pending|cancelled)── */
|
||||
(function paymentReturnNotice() {
|
||||
var params = new URLSearchParams(window.location.search);
|
||||
var pay = params.get("payment");
|
||||
if (!pay) return;
|
||||
var map = { success: "支付成功!", pending: "支付处理中,到账后将自动更新。", cancelled: "支付已取消。", fail: "支付失败,请重试。" };
|
||||
showToast(map[pay] || "支付状态:" + pay, 3500);
|
||||
})();
|
||||
|
||||
/* ── Local card refresh helpers ── */
|
||||
function findOrderCard(orderNumber) {
|
||||
return page.querySelector('[data-aksrt-order-card="' + orderNumber + '"]');
|
||||
}
|
||||
|
||||
function updateCardStatus(card, newStatus, statusLabel) {
|
||||
if (!card) return;
|
||||
var badge = card.querySelector(".aksrt-orders-page__item-badge");
|
||||
if (badge) {
|
||||
badge.textContent = statusLabel || newStatus;
|
||||
}
|
||||
// Hide action buttons that are no longer relevant
|
||||
var actions = card.querySelectorAll("[data-aksrt-order-pay], [data-aksrt-order-cancel], [data-aksrt-order-after-sale]");
|
||||
for (var i = 0; i < actions.length; i++) {
|
||||
actions[i].style.display = "none";
|
||||
}
|
||||
// Hide countdown if present
|
||||
var countdown = card.querySelector("[data-aksrt-order-countdown]");
|
||||
if (countdown) {
|
||||
countdown.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
/* ── After-Sale Modal ── */
|
||||
var afterSaleModal = page.querySelector("[data-aksrt-aftersale-modal]");
|
||||
var afterSaleForm = page.querySelector("[data-aksrt-aftersale-form]");
|
||||
var afterSaleOrderInput = afterSaleForm ? afterSaleForm.querySelector('[name="order_number"]') : null;
|
||||
|
||||
function openAfterSaleModal(orderNumber) {
|
||||
if (!afterSaleModal || !afterSaleForm) {
|
||||
showToast("售后表单加载失败,请刷新页面后重试。");
|
||||
return;
|
||||
}
|
||||
afterSaleForm.reset();
|
||||
if (afterSaleOrderInput) afterSaleOrderInput.value = orderNumber;
|
||||
afterSaleModal.hidden = false;
|
||||
}
|
||||
|
||||
function closeAfterSaleModal() {
|
||||
if (afterSaleModal) afterSaleModal.hidden = true;
|
||||
}
|
||||
|
||||
if (afterSaleForm) {
|
||||
afterSaleForm.addEventListener("submit", function (event) {
|
||||
event.preventDefault();
|
||||
var formData = new FormData(afterSaleForm);
|
||||
var orderNumber = formData.get("order_number");
|
||||
var reason = (formData.get("reason") || "").trim();
|
||||
if (!reason) {
|
||||
showToast("请填写售后原因。");
|
||||
return;
|
||||
}
|
||||
|
||||
var submitBtn = afterSaleForm.querySelector('button[type="submit"]');
|
||||
if (submitBtn) {
|
||||
submitBtn.disabled = true;
|
||||
submitBtn.textContent = "提交中...";
|
||||
}
|
||||
|
||||
request("/shop/frontend/orders/" + orderNumber + "/after-sale", {
|
||||
type: formData.get("type") || "refund",
|
||||
reason: reason,
|
||||
note: (formData.get("note") || "").trim()
|
||||
}).then(function (result) {
|
||||
if (submitBtn) {
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.textContent = "提交售后";
|
||||
}
|
||||
if (!result.success) {
|
||||
showToast(result.message || "提交售后失败。");
|
||||
return;
|
||||
}
|
||||
closeAfterSaleModal();
|
||||
showToast("售后申请已提交。");
|
||||
// Local refresh: update card status
|
||||
var card = findOrderCard(orderNumber);
|
||||
updateCardStatus(card, "refunded", "已退款");
|
||||
}).catch(function () {
|
||||
if (submitBtn) {
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.textContent = "提交售后";
|
||||
}
|
||||
showToast("网络错误,请稍后重试。");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* ── Countdown timer ── */
|
||||
function updateCountdowns() {
|
||||
var nodes = page.querySelectorAll("[data-aksrt-order-countdown]");
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
var node = nodes[i];
|
||||
var value = Number(node.getAttribute("data-aksrt-order-countdown") || 0);
|
||||
if (!value) continue;
|
||||
|
||||
value -= 1;
|
||||
node.setAttribute("data-aksrt-order-countdown", String(value));
|
||||
node.textContent = value > 0 ? "剩余支付时间 " + value + " 秒" : "待支付已超时,请重新发起。";
|
||||
}
|
||||
}
|
||||
|
||||
setInterval(updateCountdowns, 1000);
|
||||
|
||||
/* ── Event delegation ── */
|
||||
page.addEventListener("click", function (event) {
|
||||
// Pay
|
||||
var payButton = event.target.closest("[data-aksrt-order-pay]");
|
||||
if (payButton) {
|
||||
var payOrderNumber = payButton.getAttribute("data-aksrt-order-pay");
|
||||
// 支付方式取订单创建时选定的方式(按钮 data 属性可覆盖);
|
||||
// 留空则由服务端使用订单存储的 payment_method。
|
||||
var payMethod = payButton.getAttribute("data-aksrt-order-method") || "";
|
||||
payButton.disabled = true;
|
||||
payButton.textContent = "处理中...";
|
||||
request("/shop/frontend/orders/" + payOrderNumber + "/pay", payMethod ? { payment_method: payMethod } : {})
|
||||
.then(function (result) {
|
||||
if (!result.success) {
|
||||
payButton.disabled = false;
|
||||
payButton.textContent = "立即支付";
|
||||
showToast(result.message || "支付失败。");
|
||||
return;
|
||||
}
|
||||
|
||||
var data = result.data || {};
|
||||
|
||||
// 跳转/扫码型网关:到第三方支付页或展示二维码,订单仍为待支付,
|
||||
// 由回调确认到账。
|
||||
if (data.redirect) {
|
||||
if (data.payment_url && /^https?:\/\//i.test(data.payment_url)) {
|
||||
window.location.href = data.payment_url;
|
||||
return;
|
||||
}
|
||||
if (data.qr_content || data.payment_url) {
|
||||
showPaymentQr(data.qr_content || data.payment_url, payOrderNumber);
|
||||
payButton.disabled = false;
|
||||
payButton.textContent = "已下单,待支付";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 同步型网关(站内余额):已到账。
|
||||
showToast("支付成功!");
|
||||
var card = findOrderCard(payOrderNumber);
|
||||
updateCardStatus(card, "paid", "已支付");
|
||||
})
|
||||
.catch(function () {
|
||||
payButton.disabled = false;
|
||||
payButton.textContent = "立即支付";
|
||||
showToast("网络错误,请稍后重试。");
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Cancel
|
||||
var cancelButton = event.target.closest("[data-aksrt-order-cancel]");
|
||||
if (cancelButton) {
|
||||
var cancelOrderNumber = cancelButton.getAttribute("data-aksrt-order-cancel");
|
||||
cancelButton.disabled = true;
|
||||
cancelButton.textContent = "取消中...";
|
||||
request("/shop/frontend/orders/" + cancelOrderNumber + "/cancel")
|
||||
.then(function (result) {
|
||||
if (!result.success) {
|
||||
cancelButton.disabled = false;
|
||||
cancelButton.textContent = "取消订单";
|
||||
showToast(result.message || "取消失败。");
|
||||
return;
|
||||
}
|
||||
showToast("订单已取消。");
|
||||
var card = findOrderCard(cancelOrderNumber);
|
||||
updateCardStatus(card, "cancelled", "已取消");
|
||||
})
|
||||
.catch(function () {
|
||||
cancelButton.disabled = false;
|
||||
cancelButton.textContent = "取消订单";
|
||||
showToast("网络错误,请稍后重试。");
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// After-Sale
|
||||
var afterSaleButton = event.target.closest("[data-aksrt-order-after-sale]");
|
||||
if (afterSaleButton) {
|
||||
var afterSaleOrderNumber = afterSaleButton.getAttribute("data-aksrt-order-after-sale");
|
||||
openAfterSaleModal(afterSaleOrderNumber);
|
||||
return;
|
||||
}
|
||||
|
||||
// Close modal
|
||||
if (event.target.closest("[data-aksrt-aftersale-modal-close]") || (event.target.classList && event.target.classList.contains("aksrt-modal__overlay"))) {
|
||||
closeAfterSaleModal();
|
||||
}
|
||||
});
|
||||
})();
|
||||
@@ -0,0 +1,255 @@
|
||||
/**
|
||||
* AKSRT Page Edit — 前台编辑增强
|
||||
*
|
||||
* 提供前台编辑页面的增强功能:
|
||||
* - 自动保存草稿
|
||||
* - 字数统计
|
||||
* - 标签建议
|
||||
* - 快捷键支持
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var DRAFT_KEY_PREFIX = 'aksrt_draft_';
|
||||
|
||||
/**
|
||||
* 初始化页面编辑增强
|
||||
*
|
||||
* @param {Object} options 配置项
|
||||
*/
|
||||
function PageEdit(options) {
|
||||
this.options = Object.assign({
|
||||
formSelector: 'form[data-aksrt-edit]',
|
||||
titleSelector: 'input[name="title"], input[name="topic_title"]',
|
||||
contentSelector: 'textarea[name="content"], textarea[name="topic_content"]',
|
||||
tagsSelector: 'input[name="tags"], input[name="topic_tags"]',
|
||||
autoSaveInterval: 30000, // 30秒
|
||||
maxTitleLength: 200,
|
||||
maxContentLength: 100000,
|
||||
draftKey: '',
|
||||
}, options || {});
|
||||
|
||||
this.form = document.querySelector(this.options.formSelector);
|
||||
if (!this.form) return;
|
||||
|
||||
this.autoSaveTimer = null;
|
||||
this.lastSavedContent = '';
|
||||
this.init();
|
||||
}
|
||||
|
||||
PageEdit.prototype.init = function () {
|
||||
var self = this;
|
||||
|
||||
this.titleInput = this.form.querySelector(this.options.titleSelector);
|
||||
this.contentTextarea = this.form.querySelector(this.options.contentSelector);
|
||||
this.tagsInput = this.form.querySelector(this.options.tagsSelector);
|
||||
|
||||
// 字数统计
|
||||
this.initWordCount();
|
||||
|
||||
// 自动保存草稿
|
||||
this.initAutoSave();
|
||||
|
||||
// 快捷键
|
||||
this.initShortcuts();
|
||||
|
||||
// 标签输入增强
|
||||
this.initTagInput();
|
||||
|
||||
// 表单提交时清除草稿
|
||||
this.form.addEventListener('submit', function () {
|
||||
self.clearDraft();
|
||||
});
|
||||
|
||||
// 页面离开提醒
|
||||
window.addEventListener('beforeunload', function (e) {
|
||||
if (self.hasUnsavedChanges()) {
|
||||
e.preventDefault();
|
||||
e.returnValue = '您有未保存的修改,确定要离开吗?';
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
PageEdit.prototype.initWordCount = function () {
|
||||
var self = this;
|
||||
|
||||
// 创建字数统计显示
|
||||
this.wordCountEl = document.createElement('div');
|
||||
this.wordCountEl.className = 'aksrt-page-edit__word-count';
|
||||
|
||||
if (this.titleInput) {
|
||||
var titleCount = document.createElement('span');
|
||||
titleCount.className = 'aksrt-page-edit__title-count';
|
||||
this.titleInput.parentNode.appendChild(titleCount);
|
||||
|
||||
this.titleInput.addEventListener('input', function () {
|
||||
var len = self.titleInput.value.length;
|
||||
titleCount.textContent = len + '/' + self.options.maxTitleLength;
|
||||
titleCount.classList.toggle('aksrt-page-edit__count--warn', len > self.options.maxTitleLength * 0.9);
|
||||
titleCount.classList.toggle('aksrt-page-edit__count--error', len > self.options.maxTitleLength);
|
||||
});
|
||||
}
|
||||
|
||||
if (this.contentTextarea) {
|
||||
this.contentTextarea.parentNode.appendChild(this.wordCountEl);
|
||||
this.updateWordCount();
|
||||
|
||||
this.contentTextarea.addEventListener('input', function () {
|
||||
self.updateWordCount();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
PageEdit.prototype.updateWordCount = function () {
|
||||
if (!this.contentTextarea || !this.wordCountEl) return;
|
||||
|
||||
var text = this.contentTextarea.value;
|
||||
var chars = text.length;
|
||||
var words = text.trim() ? text.trim().split(/\s+/).length : 0;
|
||||
var chinese = (text.match(/[一-鿿]/g) || []).length;
|
||||
|
||||
this.wordCountEl.textContent = '字数: ' + chars + ' | 词数: ' + words + ' | 中文: ' + chinese;
|
||||
this.wordCountEl.classList.toggle('aksrt-page-edit__count--warn', chars > this.options.maxContentLength * 0.9);
|
||||
this.wordCountEl.classList.toggle('aksrt-page-edit__count--error', chars > this.options.maxContentLength);
|
||||
};
|
||||
|
||||
PageEdit.prototype.initAutoSave = function () {
|
||||
var self = this;
|
||||
|
||||
if (!this.options.draftKey) {
|
||||
// 从页面 URL 生成 draft key
|
||||
this.options.draftKey = DRAFT_KEY_PREFIX + (window.location.pathname.replace(/\//g, '_') || 'page');
|
||||
}
|
||||
|
||||
// 恢复草稿
|
||||
this.restoreDraft();
|
||||
|
||||
// 定时自动保存
|
||||
if (this.options.autoSaveInterval > 0) {
|
||||
this.autoSaveTimer = setInterval(function () {
|
||||
self.saveDraft();
|
||||
}, this.options.autoSaveInterval);
|
||||
}
|
||||
};
|
||||
|
||||
PageEdit.prototype.saveDraft = function () {
|
||||
if (!this.form) return;
|
||||
|
||||
var data = {};
|
||||
if (this.titleInput) data.title = this.titleInput.value;
|
||||
if (this.contentTextarea) data.content = this.contentTextarea.value;
|
||||
if (this.tagsInput) data.tags = this.tagsInput.value;
|
||||
|
||||
var content = JSON.stringify(data);
|
||||
if (content === this.lastSavedContent) return;
|
||||
|
||||
try {
|
||||
localStorage.setItem(this.options.draftKey, content);
|
||||
this.lastSavedContent = content;
|
||||
|
||||
// 显示保存提示
|
||||
var toast = document.getElementById('aksrt-draft-toast');
|
||||
if (!toast) {
|
||||
toast = document.createElement('div');
|
||||
toast.id = 'aksrt-draft-toast';
|
||||
toast.className = 'aksrt-page-edit__toast';
|
||||
document.body.appendChild(toast);
|
||||
}
|
||||
toast.textContent = '草稿已自动保存';
|
||||
toast.classList.add('aksrt-page-edit__toast--visible');
|
||||
setTimeout(function () {
|
||||
toast.classList.remove('aksrt-page-edit__toast--visible');
|
||||
}, 2000);
|
||||
} catch (e) {
|
||||
console.error('[AKSRT PageEdit] 保存草稿失败:', e);
|
||||
}
|
||||
};
|
||||
|
||||
PageEdit.prototype.restoreDraft = function () {
|
||||
try {
|
||||
var saved = localStorage.getItem(this.options.draftKey);
|
||||
if (!saved) return;
|
||||
|
||||
var data = JSON.parse(saved);
|
||||
var hasContent = false;
|
||||
|
||||
if (this.titleInput && data.title && !this.titleInput.value) {
|
||||
this.titleInput.value = data.title;
|
||||
hasContent = true;
|
||||
}
|
||||
if (this.contentTextarea && data.content && !this.contentTextarea.value) {
|
||||
this.contentTextarea.value = data.content;
|
||||
hasContent = true;
|
||||
}
|
||||
if (this.tagsInput && data.tags && !this.tagsInput.value) {
|
||||
this.tagsInput.value = data.tags;
|
||||
hasContent = true;
|
||||
}
|
||||
|
||||
if (hasContent) {
|
||||
this.lastSavedContent = saved;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[AKSRT PageEdit] 恢复草稿失败:', e);
|
||||
}
|
||||
};
|
||||
|
||||
PageEdit.prototype.clearDraft = function () {
|
||||
try {
|
||||
localStorage.removeItem(this.options.draftKey);
|
||||
} catch (e) {}
|
||||
};
|
||||
|
||||
PageEdit.prototype.hasUnsavedChanges = function () {
|
||||
if (!this.form) return false;
|
||||
|
||||
var data = {};
|
||||
if (this.titleInput) data.title = this.titleInput.value;
|
||||
if (this.contentTextarea) data.content = this.contentTextarea.value;
|
||||
if (this.tagsInput) data.tags = this.tagsInput.value;
|
||||
|
||||
return JSON.stringify(data) !== this.lastSavedContent;
|
||||
};
|
||||
|
||||
PageEdit.prototype.initShortcuts = function () {
|
||||
var self = this;
|
||||
|
||||
this.form.addEventListener('keydown', function (e) {
|
||||
// Ctrl+S / Cmd+S 保存草稿
|
||||
if ((e.ctrlKey || e.metaKey) && e.key === 's') {
|
||||
e.preventDefault();
|
||||
self.saveDraft();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
PageEdit.prototype.initTagInput = function () {
|
||||
if (!this.tagsInput) return;
|
||||
|
||||
// 回车键添加标签
|
||||
this.tagsInput.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 自动初始化
|
||||
function autoInit() {
|
||||
var form = document.querySelector('form[data-aksrt-edit]');
|
||||
if (form) {
|
||||
new PageEdit();
|
||||
}
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', autoInit);
|
||||
} else {
|
||||
autoInit();
|
||||
}
|
||||
|
||||
window.AksrtPageEdit = PageEdit;
|
||||
})();
|
||||
@@ -0,0 +1,454 @@
|
||||
/**
|
||||
* AKSRT Page Navigation — v3.0
|
||||
*
|
||||
* 功能:
|
||||
* - TOC 高亮 + 平滑滚动(文档阅读页)
|
||||
* - 文档导航搜索 + 结果接管(文档导航页)
|
||||
* - 分类切换 AJAX 加载 + 分页(文档导航页)
|
||||
* - 加载状态和分页控件
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var API_BASE = (window.aksrtData && window.aksrtData.restNonce)
|
||||
? (window.aksrtData.siteUrl || '') + '/wp-json/aksrt/v1'
|
||||
: '';
|
||||
var NONCE = (window.aksrtData && window.aksrtData.restNonce) || '';
|
||||
|
||||
var PAGE_NAVS = {
|
||||
tocItems: [],
|
||||
headings: [],
|
||||
scrollTimer: null,
|
||||
activeCategory: 0,
|
||||
currentPage: 1,
|
||||
totalPages: 1,
|
||||
searchQuery: '',
|
||||
ajaxInFlight: null,
|
||||
|
||||
init: function () {
|
||||
this.initTocHighlight();
|
||||
this.initSmoothScroll();
|
||||
this.initDocSearch();
|
||||
this.initCategoryChips();
|
||||
this.initPagination();
|
||||
},
|
||||
|
||||
/* ============================================================
|
||||
* TOC 高亮(文档阅读页)
|
||||
* ============================================================ */
|
||||
initTocHighlight: function () {
|
||||
var toc = document.querySelector('.aksrt-doc-toc');
|
||||
if (!toc) return;
|
||||
|
||||
this.tocItems = Array.from(toc.querySelectorAll('.aksrt-doc-toc__item a'));
|
||||
if (this.tocItems.length === 0) return;
|
||||
|
||||
this.headings = this.tocItems.map(function (link) {
|
||||
var id = link.getAttribute('href');
|
||||
if (id && id.startsWith('#')) {
|
||||
return document.getElementById(id.substring(1));
|
||||
}
|
||||
return null;
|
||||
}).filter(Boolean);
|
||||
|
||||
if (this.headings.length === 0) return;
|
||||
|
||||
var self = this;
|
||||
window.addEventListener('scroll', function () {
|
||||
if (self.scrollTimer) clearTimeout(self.scrollTimer);
|
||||
self.scrollTimer = setTimeout(function () { self.updateTocHighlight(); }, 50);
|
||||
}, { passive: true });
|
||||
|
||||
this.updateTocHighlight();
|
||||
},
|
||||
|
||||
updateTocHighlight: function () {
|
||||
var scrollY = window.scrollY + 100;
|
||||
var currentIndex = -1;
|
||||
|
||||
for (var i = this.headings.length - 1; i >= 0; i--) {
|
||||
if (this.headings[i].offsetTop <= scrollY) {
|
||||
currentIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.tocItems.forEach(function (link, index) {
|
||||
var li = link.parentElement;
|
||||
if (index === currentIndex) {
|
||||
li.classList.add('is-active');
|
||||
link.classList.add('is-active');
|
||||
} else {
|
||||
li.classList.remove('is-active');
|
||||
link.classList.remove('is-active');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/* ============================================================
|
||||
* 平滑滚动
|
||||
* ============================================================ */
|
||||
initSmoothScroll: function () {
|
||||
document.addEventListener('click', function (e) {
|
||||
var link = e.target.closest('a[href^="#"]');
|
||||
if (!link) return;
|
||||
|
||||
var id = link.getAttribute('href').substring(1);
|
||||
if (!id) return;
|
||||
|
||||
var target = document.getElementById(id);
|
||||
if (!target) return;
|
||||
|
||||
e.preventDefault();
|
||||
var offset = 80; // nav height
|
||||
var top = target.getBoundingClientRect().top + window.scrollY - offset;
|
||||
window.scrollTo({ top: top, behavior: 'smooth' });
|
||||
});
|
||||
},
|
||||
|
||||
/* ============================================================
|
||||
* 文档搜索(AJAX 接管)
|
||||
* ============================================================ */
|
||||
initDocSearch: function () {
|
||||
var searchInput = document.querySelector('.aksrt-doc-search__input');
|
||||
if (!searchInput) return;
|
||||
|
||||
var resultsContainer = document.querySelector('.aksrt-doc-search__results');
|
||||
var takeover = document.querySelector('.aksrt-doc-takeover');
|
||||
var self = this;
|
||||
|
||||
var debounceTimer = null;
|
||||
searchInput.addEventListener('input', function () {
|
||||
var query = searchInput.value.trim();
|
||||
if (debounceTimer) clearTimeout(debounceTimer);
|
||||
|
||||
if (query.length < 2) {
|
||||
self.clearSearch(resultsContainer, takeover);
|
||||
return;
|
||||
}
|
||||
|
||||
debounceTimer = setTimeout(function () {
|
||||
self.searchDocs(query, resultsContainer, takeover);
|
||||
}, 300);
|
||||
});
|
||||
|
||||
searchInput.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'Escape') {
|
||||
searchInput.value = '';
|
||||
self.clearSearch(resultsContainer, takeover);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
searchDocs: function (query, resultsContainer, takeover) {
|
||||
if (this.ajaxInFlight) {
|
||||
this.ajaxInFlight.abort();
|
||||
}
|
||||
|
||||
var self = this;
|
||||
this.showLoading(takeover || resultsContainer);
|
||||
|
||||
var url = API_BASE + '/docs/search?q=' + encodeURIComponent(query);
|
||||
this.ajaxInFlight = this.ajaxRequest(url, function (data) {
|
||||
self.hideLoading(takeover || resultsContainer);
|
||||
self.renderSearchResults(data, resultsContainer, takeover, query);
|
||||
}, function () {
|
||||
self.hideLoading(takeover || resultsContainer);
|
||||
});
|
||||
},
|
||||
|
||||
renderSearchResults: function (data, resultsContainer, takeover, query) {
|
||||
var items = data.items || data.data || [];
|
||||
if (items.length === 0) {
|
||||
if (resultsContainer) {
|
||||
resultsContainer.hidden = false;
|
||||
resultsContainer.innerHTML = '<div class="aksrt-doc-search__empty">未找到相关文档</div>';
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var html = '<div class="aksrt-doc-search__list">';
|
||||
items.forEach(function (item) {
|
||||
html += '<a class="aksrt-doc-search__item" href="' + this.escHtml(item.url) + '">';
|
||||
html += '<span class="aksrt-doc-search__item-title">' + this.highlightQuery(this.escHtml(item.title), query) + '</span>';
|
||||
if (item.excerpt) {
|
||||
html += '<span class="aksrt-doc-search__item-excerpt">' + this.highlightQuery(this.escHtml(item.excerpt), query) + '</span>';
|
||||
}
|
||||
html += '</a>';
|
||||
}.bind(this));
|
||||
html += '</div>';
|
||||
|
||||
if (takeover) {
|
||||
takeover.innerHTML = html;
|
||||
takeover.hidden = false;
|
||||
} else if (resultsContainer) {
|
||||
resultsContainer.innerHTML = html;
|
||||
resultsContainer.hidden = false;
|
||||
}
|
||||
},
|
||||
|
||||
highlightQuery: function (text, query) {
|
||||
if (!query) return text;
|
||||
var escaped = query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
return text.replace(new RegExp('(' + escaped + ')', 'gi'), '<mark>$1</mark>');
|
||||
},
|
||||
|
||||
clearSearch: function (resultsContainer, takeover) {
|
||||
if (takeover) {
|
||||
takeover.hidden = true;
|
||||
takeover.innerHTML = '';
|
||||
}
|
||||
if (resultsContainer) {
|
||||
resultsContainer.hidden = true;
|
||||
resultsContainer.innerHTML = '';
|
||||
}
|
||||
// 显示所有卡片
|
||||
var cards = document.querySelectorAll('.aksrt-doc-index-card');
|
||||
cards.forEach(function (card) { card.style.display = ''; });
|
||||
},
|
||||
|
||||
showLoading: function (container) {
|
||||
if (!container) return;
|
||||
var existing = container.querySelector('.aksrt-doc-loading');
|
||||
if (existing) return;
|
||||
|
||||
var loader = document.createElement('div');
|
||||
loader.className = 'aksrt-doc-loading';
|
||||
loader.innerHTML = '<div class="aksrt-doc-loading__spinner"></div><span>搜索中...</span>';
|
||||
container.appendChild(loader);
|
||||
},
|
||||
|
||||
hideLoading: function (container) {
|
||||
if (!container) return;
|
||||
var loader = container.querySelector('.aksrt-doc-loading');
|
||||
if (loader) loader.remove();
|
||||
},
|
||||
|
||||
/* ============================================================
|
||||
* 分类切换 — AJAX 加载 + 分页
|
||||
* ============================================================ */
|
||||
initCategoryChips: function () {
|
||||
var toolbar = document.querySelector('.aksrt-doc-toolbar');
|
||||
if (!toolbar) return;
|
||||
|
||||
var chips = toolbar.querySelectorAll('.aksrt-doc-toolbar__chip[data-cat-id]');
|
||||
if (chips.length === 0) return;
|
||||
|
||||
var self = this;
|
||||
chips.forEach(function (chip) {
|
||||
chip.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
var catId = parseInt(chip.getAttribute('data-cat-id') || '0', 10);
|
||||
|
||||
// 切换激活状态
|
||||
chips.forEach(function (c) { c.classList.remove('is-active'); });
|
||||
chip.classList.add('is-active');
|
||||
|
||||
self.activeCategory = catId;
|
||||
self.currentPage = 1;
|
||||
self.loadCategoryDocs(catId, 1);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
loadCategoryDocs: function (catId, page) {
|
||||
if (this.ajaxInFlight) {
|
||||
this.ajaxInFlight.abort();
|
||||
}
|
||||
|
||||
var self = this;
|
||||
var grid = document.querySelector('.aksrt-doc-grid');
|
||||
if (!grid) return;
|
||||
|
||||
// 显示加载状态
|
||||
grid.classList.add('is-loading');
|
||||
|
||||
var url = API_BASE + '/docs/list?cat_id=' + catId + '&page=' + page + '&per_page=12';
|
||||
this.ajaxInFlight = this.ajaxRequest(url, function (data) {
|
||||
grid.classList.remove('is-loading');
|
||||
self.renderCategoryDocs(data, grid);
|
||||
self.updatePagination(data.total || 0, data.pages || 1, page);
|
||||
self.updateMetaCount(data.total || 0);
|
||||
}, function () {
|
||||
grid.classList.remove('is-loading');
|
||||
});
|
||||
},
|
||||
|
||||
renderCategoryDocs: function (data, grid) {
|
||||
var items = data.items || data.data || [];
|
||||
if (items.length === 0) {
|
||||
grid.innerHTML = '<div class="aksrt-doc-empty">暂无文档</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
var html = '';
|
||||
items.forEach(function (item) {
|
||||
html += '<a class="aksrt-doc-index-card" href="' + this.escHtml(item.url) + '" data-cat-id="' + (item.cat_id || 0) + '">';
|
||||
if (item.thumbnail) {
|
||||
html += '<img class="aksrt-doc-index-card__thumb" src="' + this.escHtml(item.thumbnail) + '" alt="" loading="lazy">';
|
||||
}
|
||||
html += '<div class="aksrt-doc-index-card__body">';
|
||||
html += '<h3 class="aksrt-doc-index-card__title">' + this.escHtml(item.title) + '</h3>';
|
||||
if (item.excerpt) {
|
||||
html += '<p class="aksrt-doc-index-card__desc">' + this.escHtml(item.excerpt) + '</p>';
|
||||
}
|
||||
html += '<div class="aksrt-doc-index-card__meta">';
|
||||
if (item.child_count) html += '<span>' + item.child_count + ' 篇子文档</span>';
|
||||
if (item.date) html += '<span>' + this.escHtml(item.date) + '</span>';
|
||||
html += '</div></div></a>';
|
||||
}.bind(this));
|
||||
|
||||
grid.innerHTML = html;
|
||||
},
|
||||
|
||||
updateMetaCount: function (total) {
|
||||
var meta = document.querySelector('.aksrt-doc-toolbar__meta');
|
||||
if (meta) {
|
||||
meta.textContent = total + ' 篇文档';
|
||||
}
|
||||
},
|
||||
|
||||
/* ============================================================
|
||||
* 分页控件
|
||||
* ============================================================ */
|
||||
initPagination: function () {
|
||||
var self = this;
|
||||
var paginationContainer = document.querySelector('.aksrt-doc-pagination');
|
||||
if (!paginationContainer) return;
|
||||
|
||||
paginationContainer.addEventListener('click', function (e) {
|
||||
var btn = e.target.closest('[data-page]');
|
||||
if (!btn) return;
|
||||
|
||||
e.preventDefault();
|
||||
var page = parseInt(btn.getAttribute('data-page'), 10);
|
||||
if (page < 1 || page > self.totalPages || page === self.currentPage) return;
|
||||
|
||||
self.currentPage = page;
|
||||
self.loadCategoryDocs(self.activeCategory, page);
|
||||
|
||||
// 滚动到顶部
|
||||
var grid = document.querySelector('.aksrt-doc-grid');
|
||||
if (grid) {
|
||||
grid.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
updatePagination: function (total, totalPages, currentPage) {
|
||||
this.totalPages = totalPages;
|
||||
this.currentPage = currentPage;
|
||||
|
||||
var container = document.querySelector('.aksrt-doc-pagination');
|
||||
if (!container) return;
|
||||
|
||||
if (totalPages <= 1) {
|
||||
container.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
|
||||
var html = '<div class="aksrt-doc-pagination__inner">';
|
||||
|
||||
// 上一页
|
||||
if (currentPage > 1) {
|
||||
html += '<button class="aksrt-doc-pagination__btn" data-page="' + (currentPage - 1) + '"><i class="fas fa-chevron-left"></i></button>';
|
||||
}
|
||||
|
||||
// 页码
|
||||
var start = Math.max(1, currentPage - 2);
|
||||
var end = Math.min(totalPages, currentPage + 2);
|
||||
|
||||
if (start > 1) {
|
||||
html += '<button class="aksrt-doc-pagination__btn" data-page="1">1</button>';
|
||||
if (start > 2) html += '<span class="aksrt-doc-pagination__ellipsis">...</span>';
|
||||
}
|
||||
|
||||
for (var i = start; i <= end; i++) {
|
||||
html += '<button class="aksrt-doc-pagination__btn' + (i === currentPage ? ' is-active' : '') + '" data-page="' + i + '">' + i + '</button>';
|
||||
}
|
||||
|
||||
if (end < totalPages) {
|
||||
if (end < totalPages - 1) html += '<span class="aksrt-doc-pagination__ellipsis">...</span>';
|
||||
html += '<button class="aksrt-doc-pagination__btn" data-page="' + totalPages + '">' + totalPages + '</button>';
|
||||
}
|
||||
|
||||
// 下一页
|
||||
if (currentPage < totalPages) {
|
||||
html += '<button class="aksrt-doc-pagination__btn" data-page="' + (currentPage + 1) + '"><i class="fas fa-chevron-right"></i></button>';
|
||||
}
|
||||
|
||||
html += '</div>';
|
||||
container.innerHTML = html;
|
||||
},
|
||||
|
||||
/* ============================================================
|
||||
* 工具函数
|
||||
* ============================================================ */
|
||||
escHtml: function (str) {
|
||||
var div = document.createElement('div');
|
||||
div.appendChild(document.createTextNode(str || ''));
|
||||
return div.innerHTML;
|
||||
},
|
||||
|
||||
filterDocItems: function (query) {
|
||||
var cards = document.querySelectorAll('.aksrt-doc-index-card');
|
||||
if (cards.length > 0) {
|
||||
cards.forEach(function (card) {
|
||||
var title = card.querySelector('.aksrt-doc-index-card__title');
|
||||
var desc = card.querySelector('.aksrt-doc-index-card__desc');
|
||||
var text = (title ? title.textContent : '') + ' ' + (desc ? desc.textContent : '');
|
||||
if (query === '' || text.toLowerCase().indexOf(query) >= 0) {
|
||||
card.style.display = '';
|
||||
} else {
|
||||
card.style.display = 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var sidebarItems = document.querySelectorAll('.aksrt-doc-sidebar__item');
|
||||
if (sidebarItems.length > 0) {
|
||||
sidebarItems.forEach(function (item) {
|
||||
var link = item.querySelector('.aksrt-doc-sidebar__link');
|
||||
var text = link ? link.textContent : '';
|
||||
if (query === '' || text.toLowerCase().indexOf(query) >= 0) {
|
||||
item.style.display = '';
|
||||
} else {
|
||||
item.style.display = 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
ajaxRequest: function (url, onSuccess, onError) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', url, true);
|
||||
if (NONCE) {
|
||||
xhr.setRequestHeader('X-WP-Nonce', NONCE);
|
||||
}
|
||||
xhr.onreadystatechange = function () {
|
||||
if (xhr.readyState !== 4) return;
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
try {
|
||||
var data = JSON.parse(xhr.responseText);
|
||||
if (onSuccess) onSuccess(data);
|
||||
} catch (e) {
|
||||
if (onError) onError(e);
|
||||
}
|
||||
} else {
|
||||
if (onError) onError(new Error('HTTP ' + xhr.status));
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
return xhr;
|
||||
}
|
||||
};
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', function () { PAGE_NAVS.init(); });
|
||||
} else {
|
||||
PAGE_NAVS.init();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,264 @@
|
||||
/**
|
||||
* AKSRT Page Template
|
||||
*
|
||||
* Handles template-scoped content interactions: TOC, lightbox,
|
||||
* expandable article bodies, and one-shot query cleanup banners.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function slugifyHeading(text) {
|
||||
return 'heading-' + String(text || '')
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replace(/\s+/g, '-')
|
||||
.replace(/[^\w\u4e00-\u9fff-]/g, '');
|
||||
}
|
||||
|
||||
function initPostToc() {
|
||||
var content = document.querySelector('.wp-posts-content[data-nav="posts"][data-aksrt-toc="1"]');
|
||||
var tocWidget = document.querySelector('.posts-nav-box.toc-widget');
|
||||
var tocList = tocWidget ? tocWidget.querySelector('.toc-list') : null;
|
||||
var mobileToggle = document.querySelector('.toc-float-btn');
|
||||
var drawer = document.querySelector('.toc-drawer');
|
||||
var overlay = document.querySelector('.toc-drawer-overlay');
|
||||
var drawerList = drawer ? drawer.querySelector('.toc-list') : null;
|
||||
var closeBtn = drawer ? drawer.querySelector('.toc-drawer__close') : null;
|
||||
|
||||
if (!content || content.dataset.aksrtTocBound === '1') return;
|
||||
if (!tocList && !drawerList && !mobileToggle) return;
|
||||
|
||||
content.dataset.aksrtTocBound = '1';
|
||||
|
||||
var maxDepth = parseInt(content.dataset.aksrtTocDepth || '3', 10) || 3;
|
||||
|
||||
function getHeadings() {
|
||||
return Array.prototype.slice.call(content.querySelectorAll('h2, h3, h4')).filter(function (heading) {
|
||||
var level = parseInt((heading.tagName || 'H2').replace('H', ''), 10) || 2;
|
||||
return level <= maxDepth;
|
||||
});
|
||||
}
|
||||
|
||||
function buildToc(container) {
|
||||
if (!container) return false;
|
||||
|
||||
var headings = getHeadings();
|
||||
if (!headings.length) return false;
|
||||
|
||||
var html = '';
|
||||
headings.forEach(function (heading) {
|
||||
if (!heading.id) {
|
||||
heading.id = slugifyHeading(heading.textContent);
|
||||
}
|
||||
|
||||
var levelClass = '';
|
||||
if (heading.tagName === 'H3') {
|
||||
levelClass = 'toc-h3';
|
||||
} else if (heading.tagName === 'H4') {
|
||||
levelClass = 'toc-h4';
|
||||
}
|
||||
|
||||
html += '<li' + (levelClass ? ' class="' + levelClass + '"' : '') + '><a href="#' + heading.id + '">' + heading.textContent.trim() + '</a></li>';
|
||||
});
|
||||
|
||||
container.innerHTML = html;
|
||||
return true;
|
||||
}
|
||||
|
||||
var hasToc = buildToc(tocList);
|
||||
if (drawerList && drawerList !== tocList) {
|
||||
buildToc(drawerList);
|
||||
}
|
||||
|
||||
if (!hasToc) {
|
||||
if (tocWidget) tocWidget.remove();
|
||||
if (mobileToggle) mobileToggle.remove();
|
||||
if (drawer) drawer.remove();
|
||||
if (overlay) overlay.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
function closeDrawer() {
|
||||
if (drawer) drawer.classList.remove('is-open');
|
||||
if (overlay) overlay.classList.remove('is-open');
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
|
||||
function openDrawer() {
|
||||
if (drawer) drawer.classList.add('is-open');
|
||||
if (overlay) overlay.classList.add('is-open');
|
||||
document.body.style.overflow = 'hidden';
|
||||
}
|
||||
|
||||
function trackActiveHeading() {
|
||||
var headings = content.querySelectorAll('h2[id], h3[id], h4[id]');
|
||||
if (!headings.length) return;
|
||||
|
||||
var activeId = '';
|
||||
var fromTop = window.scrollY + 120;
|
||||
for (var i = headings.length - 1; i >= 0; i -= 1) {
|
||||
if (headings[i].offsetTop <= fromTop) {
|
||||
activeId = headings[i].id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
document.querySelectorAll('.toc-list a').forEach(function (link) {
|
||||
link.classList.toggle('is-active', link.getAttribute('href') === '#' + activeId);
|
||||
});
|
||||
}
|
||||
|
||||
document.querySelectorAll('.toc-list a').forEach(function (link) {
|
||||
link.addEventListener('click', function (event) {
|
||||
var target = document.querySelector(link.getAttribute('href'));
|
||||
if (!target) return;
|
||||
|
||||
event.preventDefault();
|
||||
target.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'start'
|
||||
});
|
||||
closeDrawer();
|
||||
});
|
||||
});
|
||||
|
||||
if (mobileToggle) mobileToggle.addEventListener('click', openDrawer);
|
||||
if (overlay) overlay.addEventListener('click', closeDrawer);
|
||||
if (closeBtn) closeBtn.addEventListener('click', closeDrawer);
|
||||
|
||||
window.addEventListener('scroll', trackActiveHeading, { passive: true });
|
||||
trackActiveHeading();
|
||||
}
|
||||
|
||||
function initLightbox() {
|
||||
var overlay = document.getElementById('lightbox-overlay');
|
||||
var content = document.querySelector(".entry-content[data-aksrt-lightbox='1']");
|
||||
if (!overlay || !content || overlay.dataset.aksrtLightboxBound === '1') return;
|
||||
|
||||
overlay.dataset.aksrtLightboxBound = '1';
|
||||
|
||||
var image = overlay.querySelector('.lightbox-img');
|
||||
var caption = overlay.querySelector('.lightbox-caption');
|
||||
var closeBtn = overlay.querySelector('.lightbox-close');
|
||||
|
||||
function close() {
|
||||
overlay.classList.remove('is-open');
|
||||
document.body.style.overflow = '';
|
||||
if (image) {
|
||||
image.src = '';
|
||||
image.alt = '';
|
||||
}
|
||||
}
|
||||
|
||||
content.querySelectorAll('img').forEach(function (img) {
|
||||
img.style.cursor = 'zoom-in';
|
||||
img.addEventListener('click', function () {
|
||||
if (!image) return;
|
||||
|
||||
image.src = img.src;
|
||||
image.alt = img.alt || '';
|
||||
|
||||
if (caption) {
|
||||
var figure = img.closest('figure');
|
||||
var figureCaption = figure ? figure.querySelector('figcaption') : null;
|
||||
caption.textContent = img.alt || (figureCaption ? figureCaption.textContent : '') || '';
|
||||
}
|
||||
|
||||
overlay.classList.add('is-open');
|
||||
document.body.style.overflow = 'hidden';
|
||||
});
|
||||
});
|
||||
|
||||
overlay.addEventListener('click', function (event) {
|
||||
if (event.target === overlay || event.target === closeBtn) {
|
||||
close();
|
||||
}
|
||||
});
|
||||
|
||||
if (closeBtn) {
|
||||
closeBtn.addEventListener('click', close);
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', function (event) {
|
||||
if (event.key === 'Escape' && overlay.classList.contains('is-open')) {
|
||||
close();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function initContentExpand() {
|
||||
var defaultMaxHeight = 800;
|
||||
|
||||
document.querySelectorAll('.entry-content[data-nav]').forEach(function (content) {
|
||||
if (content.dataset.aksrtExpandBound === '1') return;
|
||||
content.dataset.aksrtExpandBound = '1';
|
||||
|
||||
var customMax = parseInt(content.dataset.maxHeight || '0', 10);
|
||||
var limit = customMax > 0 ? customMax : defaultMaxHeight;
|
||||
if (content.scrollHeight <= limit) return;
|
||||
|
||||
content.classList.add('limit-height');
|
||||
content.style.maxHeight = limit + 'px';
|
||||
|
||||
var existingBtn = content.nextElementSibling;
|
||||
if (existingBtn && existingBtn.classList && existingBtn.classList.contains('content-expand-btn')) {
|
||||
return;
|
||||
}
|
||||
|
||||
var button = document.createElement('button');
|
||||
button.type = 'button';
|
||||
button.className = 'content-expand-btn';
|
||||
button.innerHTML = '<i class="fas fa-chevron-down" aria-hidden="true"></i> <span>展开阅读全文</span>';
|
||||
content.parentNode.insertBefore(button, content.nextSibling);
|
||||
|
||||
button.addEventListener('click', function () {
|
||||
var expanded = content.classList.contains('is-expanded');
|
||||
if (expanded) {
|
||||
content.classList.remove('is-expanded');
|
||||
content.style.maxHeight = limit + 'px';
|
||||
button.classList.remove('is-expanded');
|
||||
button.querySelector('span').textContent = '展开阅读全文';
|
||||
content.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'start'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
content.classList.add('is-expanded');
|
||||
content.style.maxHeight = content.scrollHeight + 'px';
|
||||
button.classList.add('is-expanded');
|
||||
button.querySelector('span').textContent = '收起';
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function initFlashQueryCleanup() {
|
||||
document.querySelectorAll('[data-aksrt-flash-query]').forEach(function (node) {
|
||||
var queryKey = node.getAttribute('data-aksrt-flash-query');
|
||||
if (!queryKey || !window.history || typeof window.history.replaceState !== 'function') return;
|
||||
|
||||
var url = new URL(window.location.href);
|
||||
if (!url.searchParams.has(queryKey)) return;
|
||||
|
||||
url.searchParams.delete(queryKey);
|
||||
window.history.replaceState({}, '', url.toString());
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
initPostToc();
|
||||
initLightbox();
|
||||
initContentExpand();
|
||||
initFlashQueryCleanup();
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Passive event listener polyfill
|
||||
*
|
||||
* Patches addEventListener so scroll-blocking events (touchstart, touchmove,
|
||||
* wheel, mousewheel) default to { passive: true } unless explicitly set to
|
||||
* false. Eliminates Chrome Violation warnings from third-party libraries.
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
var opts = Object.defineProperty({}, 'passive', {
|
||||
get: function () { window.__passiveSupported = true; }
|
||||
});
|
||||
window.addEventListener('test', null, opts);
|
||||
if (!window.__passiveSupported) return;
|
||||
|
||||
var orig = EventTarget.prototype.addEventListener;
|
||||
var passiveEvents = { touchstart: 1, touchmove: 1, wheel: 1, mousewheel: 1 };
|
||||
|
||||
EventTarget.prototype.addEventListener = function (type, listener, options) {
|
||||
if (passiveEvents[type] && typeof options !== 'object') {
|
||||
options = { passive: true, capture: options };
|
||||
}
|
||||
orig.call(this, type, listener, options);
|
||||
};
|
||||
})();
|
||||
@@ -0,0 +1,309 @@
|
||||
/**
|
||||
* AKSRT Post Share
|
||||
*
|
||||
* Handles share dropdowns, social share targets, copy link,
|
||||
* and WeChat bridge handoff with QR fallback.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function notify(message, type) {
|
||||
if (!message) return;
|
||||
if (typeof window.AksrtToast === 'function') {
|
||||
window.AksrtToast(message, type || 'info');
|
||||
return;
|
||||
}
|
||||
if (typeof window.showToast === 'function') {
|
||||
window.showToast(message, type || 'info');
|
||||
return;
|
||||
}
|
||||
if (typeof window.aksrtToast === 'function') {
|
||||
window.aksrtToast(message, type || 'info');
|
||||
return;
|
||||
}
|
||||
window.alert(message);
|
||||
}
|
||||
|
||||
function getMetaContent(selectors) {
|
||||
for (var i = 0; i < selectors.length; i += 1) {
|
||||
var node = document.querySelector(selectors[i]);
|
||||
var content = node ? node.getAttribute('content') : '';
|
||||
if (content) return content;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function getPlatform(node) {
|
||||
if (!node) return '';
|
||||
return node.getAttribute('data-share-platform') || node.getAttribute('data-platform') || '';
|
||||
}
|
||||
|
||||
function resolvePayload(node) {
|
||||
// Unified payload via the shared builder; fall back to local resolution
|
||||
// only if the builder script is unavailable.
|
||||
if (window.AksrtShareData && typeof window.AksrtShareData.resolve === 'function') {
|
||||
return window.AksrtShareData.resolve(node);
|
||||
}
|
||||
|
||||
var dropdown = document.getElementById('share-dropdown');
|
||||
var source = node && typeof node.closest === 'function'
|
||||
? node.closest('[data-share-url], [data-share-title], [data-share-desc], [data-share-image]')
|
||||
: null;
|
||||
var context = source || dropdown;
|
||||
|
||||
function readAttr(name) {
|
||||
return (node && node.getAttribute(name)) || (context && context.getAttribute(name)) || '';
|
||||
}
|
||||
|
||||
return {
|
||||
title: readAttr('data-share-title') || document.title,
|
||||
url: readAttr('data-share-url') || window.location.href,
|
||||
desc: readAttr('data-share-desc') || getMetaContent(['meta[property="og:description"]', 'meta[name="description"]']),
|
||||
text: readAttr('data-share-text') || '',
|
||||
image: readAttr('data-share-image') || getMetaContent(['meta[property="og:image"]']),
|
||||
qrcode: readAttr('data-share-qrcode') || ''
|
||||
};
|
||||
}
|
||||
|
||||
function openWindow(url) {
|
||||
if (!url) return;
|
||||
window.open(url, '_blank', 'width=640,height=560,scrollbars=yes,resizable=yes');
|
||||
}
|
||||
|
||||
function buildShareUrl(platform, payload) {
|
||||
switch (platform) {
|
||||
case 'weibo':
|
||||
return 'https://service.weibo.com/share/share.php?url=' + encodeURIComponent(payload.url) + '&title=' + encodeURIComponent(payload.title + (payload.text ? ' ' + payload.text : ''));
|
||||
case 'qq':
|
||||
return 'https://connect.qq.com/widget/shareqq/index.html?url=' + encodeURIComponent(payload.url) + '&title=' + encodeURIComponent(payload.title) + '&desc=' + encodeURIComponent(payload.desc || payload.text || '');
|
||||
case 'twitter':
|
||||
return 'https://x.com/intent/tweet?url=' + encodeURIComponent(payload.url) + '&text=' + encodeURIComponent(payload.title);
|
||||
case 'telegram':
|
||||
return 'https://t.me/share/url?url=' + encodeURIComponent(payload.url) + '&text=' + encodeURIComponent(payload.title);
|
||||
case 'linkedin':
|
||||
return 'https://www.linkedin.com/sharing/share-offsite/?url=' + encodeURIComponent(payload.url);
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function fallbackCopy(text) {
|
||||
var textarea = document.createElement('textarea');
|
||||
textarea.value = text;
|
||||
textarea.style.cssText = 'position:fixed;left:-9999px;top:-9999px;opacity:0;';
|
||||
textarea.setAttribute('readonly', '');
|
||||
document.body.appendChild(textarea);
|
||||
try {
|
||||
textarea.select();
|
||||
textarea.setSelectionRange(0, textarea.value.length);
|
||||
if (!document.execCommand('copy')) {
|
||||
throw new Error('copy command failed');
|
||||
}
|
||||
} finally {
|
||||
document.body.removeChild(textarea);
|
||||
}
|
||||
}
|
||||
|
||||
function copyLink(text) {
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
return navigator.clipboard.writeText(text).catch(function () {
|
||||
fallbackCopy(text);
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
fallbackCopy(text);
|
||||
return Promise.resolve();
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
|
||||
function initShareDropdown() {
|
||||
var trigger = document.getElementById('action-share-trigger');
|
||||
var dropdown = document.getElementById('share-dropdown');
|
||||
if (!trigger || !dropdown || dropdown.dataset.aksrtShareBound === '1') return;
|
||||
|
||||
dropdown.dataset.aksrtShareBound = '1';
|
||||
|
||||
var qrBox = document.getElementById('share-qrcode-box');
|
||||
var qrImage = document.getElementById('share-qrcode-image');
|
||||
|
||||
function closeDropdown() {
|
||||
dropdown.setAttribute('aria-hidden', 'true');
|
||||
trigger.setAttribute('aria-expanded', 'false');
|
||||
if (window.AksrtShare && typeof window.AksrtShare.hideQrFallback === 'function') {
|
||||
window.AksrtShare.hideQrFallback(qrBox);
|
||||
} else if (qrBox) {
|
||||
qrBox.classList.remove('is-visible');
|
||||
qrBox.setAttribute('aria-hidden', 'true');
|
||||
}
|
||||
}
|
||||
|
||||
function toggleDropdown() {
|
||||
var isOpen = dropdown.getAttribute('aria-hidden') === 'false';
|
||||
if (isOpen) {
|
||||
closeDropdown();
|
||||
return;
|
||||
}
|
||||
|
||||
dropdown.setAttribute('aria-hidden', 'false');
|
||||
trigger.setAttribute('aria-expanded', 'true');
|
||||
}
|
||||
|
||||
trigger.addEventListener('click', function (event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
toggleDropdown();
|
||||
});
|
||||
|
||||
document.addEventListener('click', function (event) {
|
||||
if (!trigger.contains(event.target) && !dropdown.contains(event.target)) {
|
||||
closeDropdown();
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('keydown', function (event) {
|
||||
if (event.key === 'Escape') {
|
||||
closeDropdown();
|
||||
}
|
||||
});
|
||||
|
||||
dropdown.addEventListener('click', function (event) {
|
||||
var item = event.target.closest('.share-item');
|
||||
if (!item) return;
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
handleShareAction(item, {
|
||||
qrBox: qrBox,
|
||||
qrImage: qrImage,
|
||||
closeDropdown: closeDropdown,
|
||||
withinDropdown: true
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function handleWeixinShare(node, payload, options) {
|
||||
options = options || {};
|
||||
|
||||
var share = window.AksrtShare;
|
||||
if (!share || typeof share.openWeixinShare !== 'function') {
|
||||
notify('微信分享模块未加载', 'error');
|
||||
return Promise.resolve({ mode: 'error' });
|
||||
}
|
||||
|
||||
if (
|
||||
options.qrBox &&
|
||||
options.qrBox.classList.contains('is-visible') &&
|
||||
(!share.isWeixinEnv || !share.isWeixinEnv())
|
||||
) {
|
||||
share.hideQrFallback(options.qrBox);
|
||||
return Promise.resolve({ mode: 'closed' });
|
||||
}
|
||||
|
||||
return share.openWeixinShare({
|
||||
title: payload.title,
|
||||
url: payload.url,
|
||||
desc: payload.desc || payload.text || '',
|
||||
image: payload.image,
|
||||
qrBox: options.qrBox || null,
|
||||
qrImage: options.qrImage || null
|
||||
}).then(function (result) {
|
||||
if (result && result.message) {
|
||||
notify(result.message, result.mode === 'error' ? 'error' : (result.mode === 'bridge' ? 'success' : 'info'));
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
function handleShareAction(node, options) {
|
||||
var platform = getPlatform(node);
|
||||
if (!platform) return Promise.resolve({ mode: 'noop' });
|
||||
|
||||
var payload = resolvePayload(node);
|
||||
if (!payload.url) return Promise.resolve({ mode: 'noop' });
|
||||
|
||||
if (platform === 'copy') {
|
||||
return copyLink(payload.url).then(function () {
|
||||
notify('链接已复制', 'success');
|
||||
if (options && typeof options.closeDropdown === 'function') {
|
||||
options.closeDropdown();
|
||||
}
|
||||
return { mode: 'copy' };
|
||||
}).catch(function () {
|
||||
notify('复制失败,请手动复制链接', 'error');
|
||||
return { mode: 'error' };
|
||||
});
|
||||
}
|
||||
|
||||
if (platform === 'wechat') {
|
||||
return handleWeixinShare(node, payload, options).then(function (result) {
|
||||
if (result && result.mode !== 'qr' && result.mode !== 'error' && options && typeof options.closeDropdown === 'function') {
|
||||
options.closeDropdown();
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
if (platform === 'poster') {
|
||||
if (window.AksrtPosterShare && typeof window.AksrtPosterShare.open === 'function') {
|
||||
window.AksrtPosterShare.open(payload);
|
||||
if (options && typeof options.closeDropdown === 'function') options.closeDropdown();
|
||||
return Promise.resolve({ mode: 'poster' });
|
||||
}
|
||||
notify('海报模块未加载', 'error');
|
||||
return Promise.resolve({ mode: 'error' });
|
||||
}
|
||||
|
||||
var shareUrl = buildShareUrl(platform, payload);
|
||||
if (!shareUrl) {
|
||||
return Promise.resolve({ mode: 'noop' });
|
||||
}
|
||||
|
||||
openWindow(shareUrl);
|
||||
if (options && typeof options.closeDropdown === 'function') {
|
||||
options.closeDropdown();
|
||||
}
|
||||
|
||||
return Promise.resolve({ mode: 'window' });
|
||||
}
|
||||
|
||||
function bindGenericShareButtons() {
|
||||
document.addEventListener('click', function (event) {
|
||||
var node = event.target.closest('[data-share-platform]');
|
||||
if (!node || node.closest('#share-dropdown')) return;
|
||||
|
||||
event.preventDefault();
|
||||
handleShareAction(node, {});
|
||||
});
|
||||
|
||||
document.addEventListener('click', function (event) {
|
||||
var node = event.target.closest('[data-share-copy]');
|
||||
if (!node) return;
|
||||
|
||||
event.preventDefault();
|
||||
var url = node.getAttribute('data-share-url') || window.location.href;
|
||||
copyLink(url).then(function () {
|
||||
notify('链接已复制', 'success');
|
||||
}).catch(function () {
|
||||
notify('复制失败,请手动复制链接', 'error');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
initShareDropdown();
|
||||
bindGenericShareButtons();
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,410 @@
|
||||
/**
|
||||
* AKSRT Poster Share — 海报分享
|
||||
*
|
||||
* 生成文章分享海报图片,支持下载和分享。
|
||||
* 使用 Canvas API 绘制,无需外部依赖。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* 初始化海报分享
|
||||
*
|
||||
* @param {Object} options 配置项
|
||||
*/
|
||||
function PosterShare(options) {
|
||||
this.options = Object.assign({
|
||||
triggerSelector: '[data-aksrt-poster]',
|
||||
title: '',
|
||||
excerpt: '',
|
||||
author: '',
|
||||
date: '',
|
||||
siteName: '',
|
||||
qrCodeUrl: '',
|
||||
width: 750,
|
||||
height: 1334,
|
||||
backgroundColor: '#ffffff',
|
||||
textColor: '#333333',
|
||||
accentColor: '#1890ff',
|
||||
}, options || {});
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
PosterShare.prototype.init = function () {
|
||||
var self = this;
|
||||
|
||||
document.querySelectorAll(this.options.triggerSelector).forEach(function (btn) {
|
||||
btn.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Unified payload first (title/excerpt/author/date/qr), then allow an
|
||||
// explicit data-aksrt-poster JSON blob to override individual fields.
|
||||
var resolved = (window.AksrtShareData && typeof window.AksrtShareData.resolve === 'function')
|
||||
? window.AksrtShareData.resolve(btn)
|
||||
: {};
|
||||
|
||||
var config = {};
|
||||
try {
|
||||
config = JSON.parse(btn.dataset.aksrtPoster || '{}');
|
||||
} catch (err) {}
|
||||
|
||||
var merged = Object.assign({}, self.options, {
|
||||
title: resolved.title || self.options.title,
|
||||
excerpt: resolved.desc || self.options.excerpt,
|
||||
author: resolved.author || self.options.author,
|
||||
date: resolved.date || self.options.date,
|
||||
siteName: resolved.siteName || self.options.siteName,
|
||||
qrCodeUrl: resolved.qrcode || self.options.qrCodeUrl
|
||||
}, config);
|
||||
self.generate(merged);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var WEEKDAYS = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
|
||||
var FONT_FAMILY = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
||||
|
||||
PosterShare.prototype.generate = function (config) {
|
||||
var self = this;
|
||||
config.width = config.width || 768;
|
||||
config.height = config.height || 1168;
|
||||
|
||||
var overlay = this.createOverlay();
|
||||
document.body.appendChild(overlay);
|
||||
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.width = config.width;
|
||||
canvas.height = config.height;
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
// Background
|
||||
ctx.fillStyle = config.backgroundColor;
|
||||
ctx.fillRect(0, 0, config.width, config.height);
|
||||
|
||||
var coverSources = [config.coverImg, config.banner, config.banner_default, config.banner_spare].filter(Boolean);
|
||||
|
||||
if (coverSources.length) {
|
||||
self.loadImageWithRetry(coverSources, 0, function (coverImg) {
|
||||
self.drawPosterContent(ctx, canvas, config, overlay, coverImg);
|
||||
}, function () {
|
||||
self.drawPosterContent(ctx, canvas, config, overlay, null);
|
||||
});
|
||||
} else {
|
||||
self.drawPosterContent(ctx, canvas, config, overlay, null);
|
||||
}
|
||||
};
|
||||
|
||||
PosterShare.prototype.loadImageWithRetry = function (sources, idx, onLoad, onFail) {
|
||||
if (idx >= sources.length) { onFail(); return; }
|
||||
var self = this;
|
||||
var retries = 0;
|
||||
var src = sources[idx];
|
||||
|
||||
function tryLoad() {
|
||||
var img = new Image();
|
||||
img.crossOrigin = 'anonymous';
|
||||
img.onload = function () { onLoad(img); };
|
||||
img.onerror = function () {
|
||||
retries++;
|
||||
if (retries < 3) { tryLoad(); }
|
||||
else { self.loadImageWithRetry(sources, idx + 1, onLoad, onFail); }
|
||||
};
|
||||
img.src = src;
|
||||
}
|
||||
tryLoad();
|
||||
};
|
||||
|
||||
PosterShare.prototype.drawPosterContent = function (ctx, canvas, config, overlay, coverImg) {
|
||||
var self = this;
|
||||
var W = config.width;
|
||||
var isProduct = config.isProduct;
|
||||
var y = 0;
|
||||
|
||||
// Cover image area (top)
|
||||
var coverH = isProduct ? W : Math.round(W * 0.52);
|
||||
if (coverImg) {
|
||||
var imgRatio = coverImg.width / coverImg.height;
|
||||
var drawW, drawH, drawX, drawY;
|
||||
if (imgRatio > W / coverH) {
|
||||
drawH = coverH; drawW = coverH * imgRatio;
|
||||
drawX = -(drawW - W) / 2; drawY = 0;
|
||||
} else {
|
||||
drawW = W; drawH = W / imgRatio;
|
||||
drawX = 0; drawY = -(drawH - coverH) / 2;
|
||||
}
|
||||
ctx.drawImage(coverImg, drawX, drawY, drawW, drawH);
|
||||
} else {
|
||||
ctx.fillStyle = config.accentColor;
|
||||
ctx.fillRect(0, 0, W, coverH);
|
||||
}
|
||||
|
||||
// Date/weekday badge (top-left)
|
||||
if (config.date) {
|
||||
var d = new Date(config.date);
|
||||
if (!isNaN(d.getTime())) {
|
||||
var weekday = WEEKDAYS[d.getDay()];
|
||||
var dateStr = (d.getMonth() + 1) + '/' + d.getDate();
|
||||
|
||||
ctx.fillStyle = 'rgba(0,0,0,0.55)';
|
||||
ctx.beginPath();
|
||||
ctx.roundRect ? ctx.roundRect(20, 20, 80, 65, 8) : ctx.rect(20, 20, 80, 65);
|
||||
ctx.fill();
|
||||
|
||||
ctx.fillStyle = '#fff';
|
||||
ctx.font = 'bold 20px ' + FONT_FAMILY;
|
||||
ctx.textAlign = 'center';
|
||||
ctx.fillText(weekday, 60, 47);
|
||||
ctx.font = '16px ' + FONT_FAMILY;
|
||||
ctx.fillText(dateStr, 60, 72);
|
||||
ctx.textAlign = 'left';
|
||||
}
|
||||
}
|
||||
|
||||
y = coverH + 36;
|
||||
|
||||
// Title with vertical accent line
|
||||
ctx.fillStyle = config.accentColor;
|
||||
ctx.fillRect(50, y - 6, 4, 44);
|
||||
|
||||
ctx.fillStyle = config.textColor;
|
||||
ctx.font = 'bold 32px ' + FONT_FAMILY;
|
||||
var titleLines = this.wrapText(ctx, config.title, W - 140);
|
||||
titleLines.slice(0, 3).forEach(function (line) {
|
||||
ctx.fillText(line, 66, y + 28);
|
||||
y += 44;
|
||||
});
|
||||
|
||||
y += 16;
|
||||
|
||||
// Product price section
|
||||
if (isProduct && config.price !== undefined) {
|
||||
ctx.font = 'bold 36px ' + FONT_FAMILY;
|
||||
ctx.fillStyle = '#e74c3c';
|
||||
var priceLabel = config.priceUnit === 'points' ? (config.price + ' 积分') : ('¥' + config.price);
|
||||
ctx.fillText(priceLabel, 60, y + 10);
|
||||
|
||||
if (config.originalPrice && config.originalPrice > config.price) {
|
||||
var priceW = ctx.measureText(priceLabel).width;
|
||||
ctx.font = '22px ' + FONT_FAMILY;
|
||||
ctx.fillStyle = '#999';
|
||||
var origText = '¥' + config.originalPrice;
|
||||
ctx.fillText(origText, 60 + priceW + 16, y + 10);
|
||||
var origW = ctx.measureText(origText).width;
|
||||
ctx.strokeStyle = '#999';
|
||||
ctx.lineWidth = 1;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(60 + priceW + 16, y + 5);
|
||||
ctx.lineTo(60 + priceW + 16 + origW, y + 5);
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
if (config.priceTag) {
|
||||
ctx.font = '18px ' + FONT_FAMILY;
|
||||
ctx.fillStyle = '#fff';
|
||||
var tagW = ctx.measureText(config.priceTag).width + 16;
|
||||
ctx.fillStyle = config.accentColor;
|
||||
ctx.beginPath();
|
||||
ctx.roundRect ? ctx.roundRect(W - 60 - tagW, y - 10, tagW, 30, 4) : ctx.rect(W - 60 - tagW, y - 10, tagW, 30);
|
||||
ctx.fill();
|
||||
ctx.fillStyle = '#fff';
|
||||
ctx.textAlign = 'center';
|
||||
ctx.fillText(config.priceTag, W - 60 - tagW / 2, y + 10);
|
||||
ctx.textAlign = 'left';
|
||||
}
|
||||
|
||||
y += 48;
|
||||
}
|
||||
|
||||
// Excerpt
|
||||
if (config.excerpt) {
|
||||
ctx.fillStyle = '#666';
|
||||
ctx.font = '22px ' + FONT_FAMILY;
|
||||
var excerptLines = this.wrapText(ctx, config.excerpt, W - 120);
|
||||
excerptLines.slice(0, 5).forEach(function (line) {
|
||||
ctx.fillText(line, 60, y + 4);
|
||||
y += 34;
|
||||
});
|
||||
if (excerptLines.length > 5) {
|
||||
ctx.fillText('...', 60, y + 4);
|
||||
y += 34;
|
||||
}
|
||||
}
|
||||
|
||||
y += 20;
|
||||
|
||||
// Author & date
|
||||
ctx.fillStyle = '#999';
|
||||
ctx.font = '18px ' + FONT_FAMILY;
|
||||
if (config.author) { ctx.fillText(config.author, 60, y); y += 26; }
|
||||
|
||||
// Bottom: site name + QR code
|
||||
var bottomY = config.height - 110;
|
||||
|
||||
ctx.strokeStyle = '#eee';
|
||||
ctx.lineWidth = 1;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(50, bottomY);
|
||||
ctx.lineTo(W - 50, bottomY);
|
||||
ctx.stroke();
|
||||
|
||||
if (config.siteName) {
|
||||
ctx.fillStyle = '#999';
|
||||
ctx.font = '18px ' + FONT_FAMILY;
|
||||
ctx.fillText(config.siteName, 60, bottomY + 36);
|
||||
}
|
||||
|
||||
if (config.qrCodeUrl) {
|
||||
var qrImg = new Image();
|
||||
qrImg.crossOrigin = 'anonymous';
|
||||
qrImg.onload = function () {
|
||||
var qrSize = 90;
|
||||
var qrX = W - 50 - qrSize;
|
||||
var qrY = bottomY + 6;
|
||||
ctx.drawImage(qrImg, qrX, qrY, qrSize, qrSize);
|
||||
|
||||
ctx.fillStyle = '#999';
|
||||
ctx.font = '13px ' + FONT_FAMILY;
|
||||
ctx.textAlign = 'center';
|
||||
ctx.fillText('扫码阅读', qrX + qrSize / 2, qrY + qrSize + 16);
|
||||
ctx.textAlign = 'left';
|
||||
|
||||
self.showPoster(canvas, overlay);
|
||||
};
|
||||
qrImg.onerror = function () { self.showPoster(canvas, overlay); };
|
||||
qrImg.src = config.qrCodeUrl;
|
||||
} else {
|
||||
self.showPoster(canvas, overlay);
|
||||
}
|
||||
};
|
||||
|
||||
PosterShare.prototype.showPoster = function (canvas, overlay) {
|
||||
// 创建海报容器
|
||||
var posterWrap = document.createElement('div');
|
||||
posterWrap.className = 'aksrt-poster-share__wrap';
|
||||
|
||||
var img = document.createElement('img');
|
||||
img.src = canvas.toDataURL('image/png');
|
||||
img.className = 'aksrt-poster-share__image';
|
||||
img.alt = '分享海报';
|
||||
posterWrap.appendChild(img);
|
||||
|
||||
// 操作按钮
|
||||
var actions = document.createElement('div');
|
||||
actions.className = 'aksrt-poster-share__actions';
|
||||
|
||||
var downloadBtn = document.createElement('button');
|
||||
downloadBtn.type = 'button';
|
||||
downloadBtn.className = 'aksrt-poster-share__btn';
|
||||
downloadBtn.innerHTML = '<i class="fas fa-download"></i> 保存图片';
|
||||
downloadBtn.addEventListener('click', function () {
|
||||
var link = document.createElement('a');
|
||||
var postId = (window.aksrtData && aksrtData.postId) || Date.now();
|
||||
link.download = 'poster_' + postId + '.png';
|
||||
link.href = canvas.toDataURL('image/png');
|
||||
link.click();
|
||||
});
|
||||
actions.appendChild(downloadBtn);
|
||||
|
||||
var closeBtn = document.createElement('button');
|
||||
closeBtn.type = 'button';
|
||||
closeBtn.className = 'aksrt-poster-share__btn aksrt-poster-share__btn--secondary';
|
||||
closeBtn.textContent = '关闭';
|
||||
closeBtn.addEventListener('click', function () {
|
||||
overlay.remove();
|
||||
});
|
||||
actions.appendChild(closeBtn);
|
||||
|
||||
posterWrap.appendChild(actions);
|
||||
|
||||
// 替换加载状态
|
||||
overlay.innerHTML = '';
|
||||
overlay.appendChild(posterWrap);
|
||||
};
|
||||
|
||||
PosterShare.prototype.createOverlay = function () {
|
||||
var overlay = document.createElement('div');
|
||||
overlay.className = 'aksrt-poster-share__overlay';
|
||||
overlay.innerHTML = '<div class="aksrt-poster-share__loading"><i class="fas fa-spinner fa-spin"></i> 生成海报中...</div>';
|
||||
overlay.addEventListener('click', function (e) {
|
||||
if (e.target === overlay) overlay.remove();
|
||||
});
|
||||
return overlay;
|
||||
};
|
||||
|
||||
PosterShare.prototype.wrapText = function (ctx, text, maxWidth) {
|
||||
var lines = [];
|
||||
var currentLine = '';
|
||||
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
var char = text[i];
|
||||
var testLine = currentLine + char;
|
||||
var metrics = ctx.measureText(testLine);
|
||||
|
||||
if (metrics.width > maxWidth && currentLine !== '') {
|
||||
lines.push(currentLine);
|
||||
currentLine = char;
|
||||
} else {
|
||||
currentLine = testLine;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentLine) {
|
||||
lines.push(currentLine);
|
||||
}
|
||||
|
||||
return lines;
|
||||
};
|
||||
|
||||
// 自动初始化
|
||||
function autoInit() {
|
||||
document.querySelectorAll('[data-aksrt-poster]').forEach(function (el) {
|
||||
if (el.dataset.posterInit) return;
|
||||
el.dataset.posterInit = '1';
|
||||
|
||||
var config = {};
|
||||
try {
|
||||
config = JSON.parse(el.dataset.aksrtPoster || '{}');
|
||||
} catch (e) {}
|
||||
|
||||
new PosterShare({ triggerSelector: '[data-aksrt-poster]' });
|
||||
});
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', autoInit);
|
||||
} else {
|
||||
autoInit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a poster directly from a unified share payload, without binding
|
||||
* to DOM triggers. Used by post-share.js for the "生成海报" share item.
|
||||
*
|
||||
* @param {Object} payload Canonical share payload (AksrtShareData shape).
|
||||
*/
|
||||
PosterShare.open = function (payload) {
|
||||
payload = payload || {};
|
||||
var inst = Object.create(PosterShare.prototype);
|
||||
inst.options = {
|
||||
width: 750,
|
||||
height: 1334,
|
||||
backgroundColor: '#ffffff',
|
||||
textColor: '#333333',
|
||||
accentColor: '#1890ff'
|
||||
};
|
||||
inst.generate(Object.assign({}, inst.options, {
|
||||
title: payload.title || document.title,
|
||||
excerpt: payload.excerpt || payload.desc || '',
|
||||
author: payload.author || '',
|
||||
date: payload.date || '',
|
||||
siteName: payload.siteName || '',
|
||||
qrCodeUrl: payload.qrCodeUrl || payload.qrcode || ''
|
||||
}));
|
||||
};
|
||||
|
||||
window.AksrtPosterShare = PosterShare;
|
||||
})();
|
||||
@@ -0,0 +1,226 @@
|
||||
/**
|
||||
* AKSRT Code Block Enhancements
|
||||
*
|
||||
* Integrates EnlighterJS for syntax highlighting and adds
|
||||
* copy-to-clipboard buttons and language labels to code blocks.
|
||||
* No jQuery dependency — pure vanilla JS.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var BASE_URI = (window.aksrtData && window.aksrtData.themeUri) || '';
|
||||
var STYLE_ID = 'aksrt-enlighter-css';
|
||||
var ENLIGHTER_LOADED = false;
|
||||
|
||||
function getHighlightSettings() {
|
||||
return (window.aksrtData && window.aksrtData.codeHighlight) || {};
|
||||
}
|
||||
|
||||
function isDarkTheme(value) {
|
||||
if (typeof value === 'boolean') return value;
|
||||
return document.documentElement.classList.contains('dark') ||
|
||||
document.documentElement.getAttribute('data-theme') === 'dark';
|
||||
}
|
||||
|
||||
function getThemeName(isDark) {
|
||||
var settings = getHighlightSettings();
|
||||
return isDarkTheme(isDark) ? (settings.darkTheme || 'monokai') : (settings.lightTheme || 'enlighter');
|
||||
}
|
||||
|
||||
function applyEnlighterTheme(isDark) {
|
||||
var settings = getHighlightSettings();
|
||||
if (settings.enabled === false) return;
|
||||
|
||||
var theme = getThemeName(isDark);
|
||||
document.querySelectorAll('.enlighter-default').forEach(function (el) {
|
||||
el.className = el.className.replace(/\benlighter-t-[\w-]+\b/g, '').replace(/\s+/g, ' ').trim();
|
||||
el.classList.add('enlighter-t-' + theme);
|
||||
});
|
||||
}
|
||||
|
||||
window.AksrtPrecodeApplyTheme = applyEnlighterTheme;
|
||||
|
||||
// ── Copy Button Styles ──
|
||||
|
||||
var COPY_STYLE_ID = 'aksrt-precode-style';
|
||||
|
||||
function injectCopyStyle() {
|
||||
if (document.getElementById(COPY_STYLE_ID)) return;
|
||||
var style = document.createElement('style');
|
||||
style.id = COPY_STYLE_ID;
|
||||
style.textContent =
|
||||
'.aksrt-code-copy{position:absolute;top:6px;right:8px;border:none;background:rgba(255,255,255,0.08);color:#a6adc8;cursor:pointer;padding:3px 10px;border-radius:6px;font-size:12px;z-index:10;transition:all 0.2s;backdrop-filter:blur(4px);}' +
|
||||
'.aksrt-code-copy:hover{background:rgba(255,255,255,0.15);color:#cdd6f4;}' +
|
||||
'.aksrt-code-copy.is-copied{color:#a6e3a1;}' +
|
||||
'.enlighter-default{position:relative;}' +
|
||||
'.enlighter-default .aksrt-code-copy{top:4px;right:4px;}' +
|
||||
'pre{position:relative;}' +
|
||||
'pre .aksrt-code-copy{top:8px;right:8px;}';
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
|
||||
// ── EnlighterJS CSS Injection ──
|
||||
|
||||
function injectEnlighterCSS() {
|
||||
if (document.getElementById(STYLE_ID)) return;
|
||||
var link = document.createElement('link');
|
||||
link.id = STYLE_ID;
|
||||
link.rel = 'stylesheet';
|
||||
link.href = BASE_URI + '/assets/js/enlighter/enlighterjs.min.css';
|
||||
document.head.appendChild(link);
|
||||
}
|
||||
|
||||
// ── EnlighterJS Loader ──
|
||||
|
||||
function loadEnlighterJS(callback) {
|
||||
if (ENLIGHTER_LOADED && window.EnlighterJS) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
injectEnlighterCSS();
|
||||
|
||||
var script = document.createElement('script');
|
||||
script.src = BASE_URI + '/assets/js/enlighter/enlighterjs.min.js';
|
||||
script.onload = function () {
|
||||
ENLIGHTER_LOADED = true;
|
||||
callback();
|
||||
};
|
||||
script.onerror = function () {
|
||||
// Fallback: just add copy buttons without highlighting
|
||||
addCopyButtonsPlain();
|
||||
};
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
|
||||
// ── Copy to Clipboard ──
|
||||
|
||||
function copyToClipboard(text, btn) {
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
navigator.clipboard.writeText(text).then(function () {
|
||||
showCopied(btn);
|
||||
});
|
||||
} else {
|
||||
var ta = document.createElement('textarea');
|
||||
ta.value = text;
|
||||
ta.style.cssText = 'position:fixed;left:-9999px;';
|
||||
document.body.appendChild(ta);
|
||||
ta.select();
|
||||
try { document.execCommand('copy'); showCopied(btn); } catch (e) { /* ignore */ }
|
||||
document.body.removeChild(ta);
|
||||
}
|
||||
}
|
||||
|
||||
function showCopied(btn) {
|
||||
btn.textContent = '已复制';
|
||||
btn.classList.add('is-copied');
|
||||
setTimeout(function () {
|
||||
btn.textContent = '复制';
|
||||
btn.classList.remove('is-copied');
|
||||
}, 1500);
|
||||
}
|
||||
|
||||
function createCopyButton(text) {
|
||||
var btn = document.createElement('button');
|
||||
btn.className = 'aksrt-code-copy';
|
||||
btn.textContent = '复制';
|
||||
btn.type = 'button';
|
||||
btn.addEventListener('click', function () {
|
||||
copyToClipboard(text, btn);
|
||||
});
|
||||
return btn;
|
||||
}
|
||||
|
||||
// ── EnlighterJS Integration ──
|
||||
|
||||
function initEnlighter() {
|
||||
if (!window.EnlighterJS) return;
|
||||
|
||||
// Get settings from aksrtData or use defaults
|
||||
var settings = getHighlightSettings();
|
||||
if (settings.enabled === false) return; // 后台关闭代码高亮
|
||||
|
||||
var lineNumbers = settings.lineNumbers === true;
|
||||
var showButtons = settings.showButtons !== false;
|
||||
var maxHeight = settings.maxHeight || 400;
|
||||
|
||||
var currentTheme = getThemeName();
|
||||
|
||||
// Find all code blocks that haven't been processed
|
||||
var blocks = document.querySelectorAll('pre > code:not(.enlighter-origin)');
|
||||
if (blocks.length === 0) return;
|
||||
|
||||
// Process each block
|
||||
blocks.forEach(function (code) {
|
||||
var pre = code.parentElement;
|
||||
if (!pre || pre.dataset.aksrtEnhanced) return;
|
||||
|
||||
// Get raw text before EnlighterJS processes it
|
||||
var rawText = code.textContent;
|
||||
|
||||
// Apply EnlighterJS
|
||||
try {
|
||||
EnlighterJS.enlight(code, {
|
||||
theme: currentTheme,
|
||||
linenumbers: lineNumbers,
|
||||
indent: 2,
|
||||
textOverflow: 'scroll',
|
||||
rawcodeDbclick: true,
|
||||
rawButton: showButtons,
|
||||
infoButton: showButtons,
|
||||
windowButton: showButtons
|
||||
});
|
||||
} catch (e) {
|
||||
// If EnlighterJS fails, keep the plain block
|
||||
}
|
||||
|
||||
// Add copy button after EnlighterJS processing
|
||||
var container = pre.querySelector('.enlighter-default') || pre;
|
||||
container.appendChild(createCopyButton(rawText));
|
||||
pre.dataset.aksrtEnhanced = '1';
|
||||
|
||||
// Apply max-height
|
||||
if (maxHeight > 0) {
|
||||
pre.style.maxHeight = maxHeight + 'px';
|
||||
pre.style.overflow = 'auto';
|
||||
}
|
||||
});
|
||||
|
||||
applyEnlighterTheme();
|
||||
}
|
||||
|
||||
// ── Fallback: Plain code blocks with copy buttons ──
|
||||
|
||||
function addCopyButtonsPlain() {
|
||||
var blocks = document.querySelectorAll('pre > code');
|
||||
blocks.forEach(function (code) {
|
||||
var pre = code.parentElement;
|
||||
if (!pre || pre.dataset.aksrtEnhanced) return;
|
||||
pre.style.position = 'relative';
|
||||
pre.appendChild(createCopyButton(code.textContent));
|
||||
pre.dataset.aksrtEnhanced = '1';
|
||||
});
|
||||
}
|
||||
|
||||
// ── Main Init ──
|
||||
|
||||
function init() {
|
||||
injectCopyStyle();
|
||||
|
||||
// Check if there are any code blocks on the page
|
||||
var blocks = document.querySelectorAll('pre > code');
|
||||
if (blocks.length === 0) return;
|
||||
|
||||
// Load EnlighterJS and initialize
|
||||
loadEnlighterJS(initEnlighter);
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* AKSRT Product Archive — 商品归档页交互
|
||||
*
|
||||
* 处理商品分类/标签归档页的筛选、排序和加载更多。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var grid = document.getElementById('aksrt-product-grid');
|
||||
if (!grid) return;
|
||||
|
||||
// 商品卡片懒加载图片观察器
|
||||
if ('IntersectionObserver' in window) {
|
||||
var imgObserver = new IntersectionObserver(function (entries) {
|
||||
entries.forEach(function (entry) {
|
||||
if (entry.isIntersecting) {
|
||||
var img = entry.target;
|
||||
if (img.dataset.src) {
|
||||
img.src = img.dataset.src;
|
||||
img.removeAttribute('data-src');
|
||||
}
|
||||
imgObserver.unobserve(img);
|
||||
}
|
||||
});
|
||||
}, { rootMargin: '200px' });
|
||||
|
||||
grid.querySelectorAll('img[data-src]').forEach(function (img) {
|
||||
imgObserver.observe(img);
|
||||
});
|
||||
}
|
||||
|
||||
// 商品卡片 hover 效果增强
|
||||
grid.querySelectorAll('.aksrt-product-card').forEach(function (card) {
|
||||
card.addEventListener('mouseenter', function () {
|
||||
this.classList.add('aksrt-product-card--hover');
|
||||
});
|
||||
card.addEventListener('mouseleave', function () {
|
||||
this.classList.remove('aksrt-product-card--hover');
|
||||
});
|
||||
});
|
||||
})();
|
||||
@@ -0,0 +1,241 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function updateCart(product, quantity, replace) {
|
||||
var key = "aksrt_cart";
|
||||
var current;
|
||||
|
||||
try {
|
||||
current = JSON.parse(localStorage.getItem(key) || "[]");
|
||||
if (!Array.isArray(current)) {
|
||||
current = [];
|
||||
}
|
||||
} catch (error) {
|
||||
current = [];
|
||||
}
|
||||
|
||||
var index = current.findIndex(function (item) {
|
||||
return Number(item.product_id || item.id || 0) === Number(product.product_id);
|
||||
});
|
||||
|
||||
if (index >= 0) {
|
||||
current[index].qty = replace ? quantity : Number(current[index].qty || 1) + quantity;
|
||||
} else {
|
||||
current.push({
|
||||
product_id: product.product_id,
|
||||
id: product.product_id,
|
||||
title: product.title,
|
||||
image: product.image,
|
||||
price: product.price,
|
||||
qty: quantity
|
||||
});
|
||||
}
|
||||
|
||||
localStorage.setItem(key, JSON.stringify(current));
|
||||
}
|
||||
|
||||
var productPage = document.querySelector("[data-aksrt-product-page]");
|
||||
if (productPage) {
|
||||
var quantityInput = productPage.querySelector("[data-aksrt-quantity]");
|
||||
var productId = Number(productPage.getAttribute("data-product-id") || 0);
|
||||
var titleEl = productPage.querySelector(".aksrt-product-page__title");
|
||||
var imageEl = productPage.querySelector(".aksrt-product-page__primary-image img");
|
||||
var priceEl = productPage.querySelector(".aksrt-product-page__price");
|
||||
var couponEl = productPage.querySelector("[data-aksrt-product-coupon]");
|
||||
|
||||
productPage.addEventListener("click", function (event) {
|
||||
var qtyBtn = event.target.closest("[data-aksrt-qty-action]");
|
||||
if (qtyBtn && quantityInput) {
|
||||
var action = qtyBtn.getAttribute("data-aksrt-qty-action");
|
||||
var current = Number(quantityInput.value || 1);
|
||||
var max = Number(quantityInput.getAttribute("max") || 999);
|
||||
quantityInput.value = action === "inc" ? Math.min(max, current + 1) : Math.max(1, current - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.target.closest("[data-aksrt-add-cart]")) {
|
||||
updateCart({
|
||||
product_id: productId,
|
||||
title: titleEl ? titleEl.textContent.trim() : "商品",
|
||||
image: imageEl ? imageEl.getAttribute("src") : "",
|
||||
price: Number((priceEl ? priceEl.textContent : "0").replace(/[^\d.]/g, ""))
|
||||
}, Number(quantityInput ? quantityInput.value : 1), false);
|
||||
if (typeof window.aksrtToast === 'function') { window.aksrtToast("已加入购物车。", 'success'); }
|
||||
else { window.alert("已加入购物车。"); }
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.target.closest("[data-aksrt-buy-now]")) {
|
||||
updateCart({
|
||||
product_id: productId,
|
||||
title: titleEl ? titleEl.textContent.trim() : "商品",
|
||||
image: imageEl ? imageEl.getAttribute("src") : "",
|
||||
price: Number((priceEl ? priceEl.textContent : "0").replace(/[^\d.]/g, ""))
|
||||
}, Number(quantityInput ? quantityInput.value : 1), true);
|
||||
|
||||
var cartUrl = new URL(aksrtData.cartUrl || window.location.href, window.location.origin);
|
||||
if (couponEl && couponEl.value) {
|
||||
cartUrl.searchParams.set("coupon", couponEl.value);
|
||||
}
|
||||
window.location.href = cartUrl.toString();
|
||||
}
|
||||
});
|
||||
|
||||
productPage.addEventListener("click", function (event) {
|
||||
var thumb = event.target.closest("[data-aksrt-product-thumb]");
|
||||
var primaryImage = productPage.querySelector(".aksrt-product-page__primary-image img");
|
||||
if (thumb && primaryImage) {
|
||||
primaryImage.setAttribute("src", thumb.getAttribute("data-aksrt-product-thumb"));
|
||||
}
|
||||
});
|
||||
|
||||
// SKU 规格选择器
|
||||
var skuSelector = productPage.querySelector("[data-aksrt-sku-selector]");
|
||||
if (skuSelector) {
|
||||
var selectedSpecs = {};
|
||||
var skuInfo = productPage.querySelector("[data-aksrt-sku-info]");
|
||||
var skuPrice = skuInfo ? skuInfo.querySelector(".aksrt-product-page__sku-price") : null;
|
||||
var skuStock = skuInfo ? skuInfo.querySelector(".aksrt-product-page__sku-stock") : null;
|
||||
var skus = [];
|
||||
|
||||
try {
|
||||
var skuData = skuSelector.getAttribute("data-aksrt-skus");
|
||||
if (skuData) skus = JSON.parse(skuData);
|
||||
} catch (e) { /* ignore */ }
|
||||
|
||||
skuSelector.addEventListener("click", function (event) {
|
||||
var btn = event.target.closest("[data-aksrt-spec]");
|
||||
if (!btn) return;
|
||||
|
||||
var specIndex = btn.getAttribute("data-aksrt-spec");
|
||||
var specVal = btn.getAttribute("data-aksrt-spec-val");
|
||||
|
||||
// 切换选中状态
|
||||
var siblings = skuSelector.querySelectorAll('[data-aksrt-spec="' + specIndex + '"]');
|
||||
siblings.forEach(function (s) { s.classList.remove("is-active"); });
|
||||
btn.classList.add("is-active");
|
||||
|
||||
selectedSpecs[specIndex] = specVal;
|
||||
|
||||
// 查找匹配的 SKU
|
||||
var matchedSku = findMatchingSku(skus, selectedSpecs);
|
||||
if (matchedSku && skuInfo) {
|
||||
skuInfo.hidden = false;
|
||||
if (skuPrice) skuPrice.textContent = "¥" + Number(matchedSku.price || 0).toFixed(2);
|
||||
if (skuStock) skuStock.textContent = "库存: " + (matchedSku.stock || 0);
|
||||
|
||||
// 更新主价格显示
|
||||
if (priceEl) priceEl.textContent = "¥" + Number(matchedSku.price || 0).toFixed(2);
|
||||
|
||||
// 更新库存限制
|
||||
if (quantityInput) {
|
||||
quantityInput.setAttribute("max", String(matchedSku.stock || 999));
|
||||
if (Number(quantityInput.value) > (matchedSku.stock || 999)) {
|
||||
quantityInput.value = matchedSku.stock || 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 更新主图
|
||||
if (matchedSku.image && primaryImage) {
|
||||
primaryImage.setAttribute("src", matchedSku.image);
|
||||
}
|
||||
} else if (skuInfo) {
|
||||
skuInfo.hidden = true;
|
||||
}
|
||||
});
|
||||
|
||||
function findMatchingSku(skus, specs) {
|
||||
if (!skus.length) return null;
|
||||
var specKeys = Object.keys(specs);
|
||||
if (specKeys.length === 0) return null;
|
||||
|
||||
return skus.find(function (sku) {
|
||||
if (!sku.specs) return false;
|
||||
return specKeys.every(function (key) {
|
||||
return sku.specs[key] === specs[key];
|
||||
});
|
||||
}) || null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var editor = document.querySelector("[data-aksrt-product-editor]");
|
||||
if (!editor || !window.aksrtData) {
|
||||
return;
|
||||
}
|
||||
|
||||
var form = editor.querySelector("[data-aksrt-product-form]");
|
||||
var messageEl = editor.querySelector("[data-aksrt-product-editor-message]");
|
||||
|
||||
function selectedMultiValues(select) {
|
||||
if (!select) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return Array.prototype.slice.call(select.options)
|
||||
.filter(function (option) {
|
||||
return option.selected;
|
||||
})
|
||||
.map(function (option) {
|
||||
return Number(option.value || 0);
|
||||
})
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
form.addEventListener("submit", function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
var formData = new FormData(form);
|
||||
var productId = Number(editor.getAttribute("data-product-id") || 0);
|
||||
var gallery = String(formData.get("gallery") || "")
|
||||
.split(/\r?\n/)
|
||||
.map(function (line) { return line.trim(); })
|
||||
.filter(Boolean);
|
||||
|
||||
var payload = {
|
||||
title: String(formData.get("title") || "").trim(),
|
||||
price: Number(formData.get("price") || 0),
|
||||
stock: Number(formData.get("stock") || 0),
|
||||
excerpt: String(formData.get("excerpt") || ""),
|
||||
content: String(formData.get("content") || ""),
|
||||
status: String(formData.get("status") || "draft"),
|
||||
categories: selectedMultiValues(form.querySelector('select[name="categories[]"]')),
|
||||
tags: String(formData.get("tags") || "")
|
||||
.split(",")
|
||||
.map(function (tag) { return tag.trim(); })
|
||||
.filter(Boolean),
|
||||
image: String(formData.get("image") || "").trim(),
|
||||
gallery: gallery,
|
||||
shipping_mode: String(formData.get("shipping_mode") || "express"),
|
||||
shipping_fee: Number(formData.get("shipping_fee") || 0),
|
||||
after_sale_policy: String(formData.get("after_sale_policy") || ""),
|
||||
support_refund: formData.get("support_refund") === "1"
|
||||
};
|
||||
|
||||
var path = productId > 0 ? "/shop/frontend/products/" + productId : "/shop/frontend/products";
|
||||
messageEl.textContent = "正在保存商品...";
|
||||
|
||||
fetch("/wp-json/aksrt/v1" + path, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-WP-Nonce": aksrtData.restNonce
|
||||
},
|
||||
body: JSON.stringify(payload)
|
||||
})
|
||||
.then(function (response) { return response.json(); })
|
||||
.then(function (result) {
|
||||
if (!result.success) {
|
||||
messageEl.textContent = result.message || "保存失败。";
|
||||
return;
|
||||
}
|
||||
|
||||
var centerUrl = aksrtData.userCenterUrl || "/";
|
||||
messageEl.textContent = "商品已保存,正在返回用户中心...";
|
||||
window.location.href = centerUrl;
|
||||
})
|
||||
.catch(function () {
|
||||
messageEl.textContent = "网络错误,请稍后重试。";
|
||||
});
|
||||
});
|
||||
})();
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
/*! kjua v0.9.0 - https://larsjung.de/kjua/ */
|
||||
!function(t,r){"object"==typeof exports&&"object"==typeof module?module.exports=r():"function"==typeof define&&define.amd?define("kjua",[],r):"object"==typeof exports?exports.kjua=r():t.kjua=r()}("undefined"!=typeof self?self:this,function(){return n={},o.m=e=[function(t,r,e){function n(t){var r=Object.assign({},o,t),e=i(r.text,r.ecLevel,r.minVersion,r.quiet);return"svg"===r.render?u(e,r):a(e,r,"image"===r.render)}var o=e(1),i=e(2),a=e(4),u=e(8);t.exports=n;try{jQuery.fn.kjua=function(e){return this.each(function(t,r){return r.appendChild(n(e))})}}catch(t){}},function(t,r){t.exports={render:"image",crisp:!0,minVersion:1,ecLevel:"L",size:200,ratio:null,fill:"#333",back:"#fff",text:"no text",rounded:0,quiet:0,mode:"plain",mSize:30,mPosX:50,mPosY:50,label:"no label",fontname:"sans",fontcolor:"#333",image:null}},function(t,r,e){function u(t){return(u="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var f=/code length overflow/i,c=e(3);c.stringToBytes=c.stringToBytesFuncs["UTF-8"];t.exports=function(t,r,e,n){var o,i=3<arguments.length&&void 0!==n?n:0,a=function(t,r,e){for(var n=2<arguments.length&&void 0!==e?e:1,o=n=Math.max(1,n);o<=40;o+=1)try{var i=function(){var e=c(o,r);e.addData(t),e.make();var n=e.getModuleCount();return{v:{text:t,level:r,version:o,module_count:n,is_dark:function(t,r){return 0<=t&&t<n&&0<=r&&r<n&&e.isDark(t,r)}}}}();if("object"===u(i))return i.v}catch(t){if(!(o<40&&f.test(t)))throw new Error(t)}return null}(0<arguments.length&&void 0!==t?t:"",1<arguments.length&&void 0!==r?r:"L",2<arguments.length&&void 0!==e?e:1);return a&&(o=a.is_dark,a.module_count+=2*i,a.is_dark=function(t,r){return o(t-i,r-i)}),a}},function(t,r,e){var n,o,i,a=function(){function i(t,r){function a(t,r){l=function(t){for(var r=new Array(t),e=0;e<t;e+=1){r[e]=new Array(t);for(var n=0;n<t;n+=1)r[e][n]=null}return r}(s=4*u+17),e(0,0),e(s-7,0),e(0,s-7),i(),o(),d(t,r),7<=u&&g(t),null==n&&(n=p(u,f,c)),v(n,r)}var u=t,f=w[r],l=null,s=0,n=null,c=[],h={},e=function(t,r){for(var e=-1;e<=7;e+=1)if(!(t+e<=-1||s<=t+e))for(var n=-1;n<=7;n+=1)r+n<=-1||s<=r+n||(l[t+e][r+n]=0<=e&&e<=6&&(0==n||6==n)||0<=n&&n<=6&&(0==e||6==e)||2<=e&&e<=4&&2<=n&&n<=4)},o=function(){for(var t=8;t<s-8;t+=1)null==l[t][6]&&(l[t][6]=t%2==0);for(var r=8;r<s-8;r+=1)null==l[6][r]&&(l[6][r]=r%2==0)},i=function(){for(var t=m.getPatternPosition(u),r=0;r<t.length;r+=1)for(var e=0;e<t.length;e+=1){var n=t[r],o=t[e];if(null==l[n][o])for(var i=-2;i<=2;i+=1)for(var a=-2;a<=2;a+=1)l[n+i][o+a]=-2==i||2==i||-2==a||2==a||0==i&&0==a}},g=function(t){for(var r=m.getBCHTypeNumber(u),e=0;e<18;e+=1){var n=!t&&1==(r>>e&1);l[Math.floor(e/3)][e%3+s-8-3]=n}for(e=0;e<18;e+=1){n=!t&&1==(r>>e&1);l[e%3+s-8-3][Math.floor(e/3)]=n}},d=function(t,r){for(var e=f<<3|r,n=m.getBCHTypeInfo(e),o=0;o<15;o+=1){var i=!t&&1==(n>>o&1);o<6?l[o][8]=i:o<8?l[o+1][8]=i:l[s-15+o][8]=i}for(o=0;o<15;o+=1){i=!t&&1==(n>>o&1);o<8?l[8][s-o-1]=i:o<9?l[8][15-o-1+1]=i:l[8][15-o-1]=i}l[s-8][8]=!t},v=function(t,r){for(var e=-1,n=s-1,o=7,i=0,a=m.getMaskFunction(r),u=s-1;0<u;u-=2)for(6==u&&--u;;){for(var f,c=0;c<2;c+=1){null==l[n][u-c]&&(f=!1,i<t.length&&(f=1==(t[i]>>>o&1)),a(n,u-c)&&(f=!f),l[n][u-c]=f,-1==--o&&(i+=1,o=7))}if((n+=e)<0||s<=n){n-=e,e=-e;break}}},p=function(t,r,e){for(var n=S.getRSBlocks(t,r),o=M(),i=0;i<e.length;i+=1){var a=e[i];o.put(a.getMode(),4),o.put(a.getLength(),m.getLengthInBits(a.getMode(),t)),a.write(o)}for(var u=0,i=0;i<n.length;i+=1)u+=n[i].dataCount;if(o.getLengthInBits()>8*u)throw"code length overflow. ("+o.getLengthInBits()+">"+8*u+")";for(o.getLengthInBits()+4<=8*u&&o.put(0,4);o.getLengthInBits()%8!=0;)o.putBit(!1);for(;!(o.getLengthInBits()>=8*u||(o.put(236,8),o.getLengthInBits()>=8*u));)o.put(17,8);return function(t,r){for(var e=0,n=0,o=0,i=new Array(r.length),a=new Array(r.length),u=0;u<r.length;u+=1){var f=r[u].dataCount,c=r[u].totalCount-f,n=Math.max(n,f),o=Math.max(o,c);i[u]=new Array(f);for(var l=0;l<i[u].length;l+=1)i[u][l]=255&t.getBuffer()[l+e];e+=f;var s=m.getErrorCorrectPolynomial(c),g=b(i[u],s.getLength()-1).mod(s);a[u]=new Array(s.getLength()-1);for(l=0;l<a[u].length;l+=1){var h=l+g.getLength()-a[u].length;a[u][l]=0<=h?g.getAt(h):0}}for(var d=0,l=0;l<r.length;l+=1)d+=r[l].totalCount;for(var v=new Array(d),p=0,l=0;l<n;l+=1)for(u=0;u<r.length;u+=1)l<i[u].length&&(v[p]=i[u][l],p+=1);for(l=0;l<o;l+=1)for(u=0;u<r.length;u+=1)l<a[u].length&&(v[p]=a[u][l],p+=1);return v}(o,n)};h.addData=function(t,r){var e=null;switch(r=r||"Byte"){case"Numeric":e=A(t);break;case"Alphanumeric":e=L(t);break;case"Byte":e=D(t);break;case"Kanji":e=_(t);break;default:throw"mode:"+r}c.push(e),n=null},h.isDark=function(t,r){if(t<0||s<=t||r<0||s<=r)throw t+","+r;return l[t][r]},h.getModuleCount=function(){return s},h.make=function(){if(u<1){for(var t=1;t<40;t++){for(var r=S.getRSBlocks(t,f),e=M(),n=0;n<c.length;n++){var o=c[n];e.put(o.getMode(),4),e.put(o.gLine truncated
|
||||
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* AKSRT Rehydrate System
|
||||
*
|
||||
* Centralized component initialization and re-initialization system.
|
||||
* Components register their init functions, and rehydrate() is called
|
||||
* to initialize or re-initialize them on a given root element.
|
||||
*
|
||||
* Usage:
|
||||
* AksrtFrontend.register('name', initFn); // Register a component
|
||||
* AksrtFrontend.rehydrate(root, 'init'); // Initialize all components
|
||||
*
|
||||
* @package AKSRT
|
||||
* @since 5.0.0
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var _registry = [];
|
||||
var _initialized = [];
|
||||
|
||||
window.AksrtFrontend = {
|
||||
|
||||
/**
|
||||
* Register a component's init function.
|
||||
*
|
||||
* @param {string} name Unique component name
|
||||
* @param {Function} initFn Function(root, reason) - root defaults to document
|
||||
*/
|
||||
register: function (name, initFn) {
|
||||
if (typeof name !== 'string' || typeof initFn !== 'function') return;
|
||||
// Prevent duplicate registrations
|
||||
for (var i = 0; i < _registry.length; i++) {
|
||||
if (_registry[i].name === name) {
|
||||
_registry[i].initFn = initFn;
|
||||
return;
|
||||
}
|
||||
}
|
||||
_registry.push({ name: name, initFn: initFn });
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize or re-initialize all registered components on a root element.
|
||||
*
|
||||
* @param {Element|Document} root The root DOM element to search within
|
||||
* @param {string} reason Why rehydrate is called:
|
||||
* 'init' = initial page load
|
||||
* 'ajax' = after AJAX content injection
|
||||
* 'modal' = after modal content loads
|
||||
* Custom string for other triggers
|
||||
*/
|
||||
rehydrate: function (root, reason) {
|
||||
root = root || document;
|
||||
reason = reason || 'init';
|
||||
|
||||
for (var i = 0; i < _registry.length; i++) {
|
||||
var entry = _registry[i];
|
||||
try {
|
||||
entry.initFn(root, reason);
|
||||
} catch (err) {
|
||||
console.error('[AKSRT Rehydrate] Error initializing "' + entry.name + '":', err);
|
||||
}
|
||||
}
|
||||
|
||||
// Dispatch event so external scripts can hook in
|
||||
try {
|
||||
root.dispatchEvent(new CustomEvent('aksrt:rehydrated', {
|
||||
bubbles: true,
|
||||
detail: { reason: reason }
|
||||
}));
|
||||
} catch (e) { /* IE fallback */ }
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the list of registered component names (for debugging).
|
||||
*/
|
||||
getRegistered: function () {
|
||||
return _registry.map(function (r) { return r.name; });
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,174 @@
|
||||
/**
|
||||
* AKSRT Report — 前台举报提交
|
||||
*
|
||||
* 监听 [data-aksrt-report] 按钮点击,弹出举报表单并提交。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var API_ROOT = (window.aksrtData && window.aksrtData.apiUrl) || '/wp-json/aksrt/v1';
|
||||
var NONCE = (window.aksrtData && window.aksrtData.restNonce) || '';
|
||||
|
||||
function getReportCategories() {
|
||||
// Default categories; can be overridden by server-rendered config
|
||||
if (window.aksrtReportCategories && Array.isArray(window.aksrtReportCategories)) {
|
||||
return window.aksrtReportCategories;
|
||||
}
|
||||
return [
|
||||
{ value: 'spam', label: '垃圾信息' },
|
||||
{ value: 'abuse', label: '人身攻击' },
|
||||
{ value: 'copyright', label: '版权投诉' },
|
||||
{ value: 'other', label: '其他' },
|
||||
];
|
||||
}
|
||||
|
||||
function createReportModal(data) {
|
||||
// Remove existing modal if any
|
||||
var existing = document.getElementById('aksrt-report-modal');
|
||||
if (existing) existing.remove();
|
||||
|
||||
var categories = getReportCategories();
|
||||
|
||||
var overlay = document.createElement('div');
|
||||
overlay.id = 'aksrt-report-modal';
|
||||
overlay.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.5);z-index:9999;display:flex;align-items:center;justify-content:center;';
|
||||
|
||||
var modal = document.createElement('div');
|
||||
modal.style.cssText = 'background:#fff;border-radius:8px;padding:24px;max-width:420px;width:90%;box-shadow:0 4px 20px rgba(0,0,0,0.15);';
|
||||
|
||||
var title = document.createElement('h3');
|
||||
title.textContent = '提交举报';
|
||||
title.style.cssText = 'margin:0 0 16px;font-size:16px;font-weight:600;';
|
||||
modal.appendChild(title);
|
||||
|
||||
// Category select
|
||||
var catLabel = document.createElement('label');
|
||||
catLabel.textContent = '举报分类';
|
||||
catLabel.style.cssText = 'display:block;margin-bottom:4px;font-size:13px;color:#555;';
|
||||
modal.appendChild(catLabel);
|
||||
|
||||
var catSelect = document.createElement('select');
|
||||
catSelect.style.cssText = 'width:100%;padding:8px;border:1px solid #ddd;border-radius:4px;margin-bottom:12px;';
|
||||
categories.forEach(function (cat) {
|
||||
var opt = document.createElement('option');
|
||||
opt.value = cat.value;
|
||||
opt.textContent = cat.label;
|
||||
catSelect.appendChild(opt);
|
||||
});
|
||||
modal.appendChild(catSelect);
|
||||
|
||||
// Reason textarea
|
||||
var reasonLabel = document.createElement('label');
|
||||
reasonLabel.textContent = '举报原因';
|
||||
reasonLabel.style.cssText = 'display:block;margin-bottom:4px;font-size:13px;color:#555;';
|
||||
modal.appendChild(reasonLabel);
|
||||
|
||||
var reasonInput = document.createElement('textarea');
|
||||
reasonInput.placeholder = '请详细描述举报原因…';
|
||||
reasonInput.style.cssText = 'width:100%;height:80px;padding:8px;border:1px solid #ddd;border-radius:4px;resize:vertical;margin-bottom:16px;box-sizing:border-box;';
|
||||
modal.appendChild(reasonInput);
|
||||
|
||||
// Buttons
|
||||
var btnRow = document.createElement('div');
|
||||
btnRow.style.cssText = 'display:flex;gap:8px;justify-content:flex-end;';
|
||||
|
||||
var cancelBtn = document.createElement('button');
|
||||
cancelBtn.type = 'button';
|
||||
cancelBtn.textContent = '取消';
|
||||
cancelBtn.style.cssText = 'padding:8px 16px;border:1px solid #ddd;border-radius:4px;background:#fff;cursor:pointer;';
|
||||
cancelBtn.onclick = function () { overlay.remove(); };
|
||||
btnRow.appendChild(cancelBtn);
|
||||
|
||||
var submitBtn = document.createElement('button');
|
||||
submitBtn.type = 'button';
|
||||
submitBtn.textContent = '提交举报';
|
||||
submitBtn.style.cssText = 'padding:8px 16px;border:none;border-radius:4px;background:#e74c3c;color:#fff;cursor:pointer;';
|
||||
submitBtn.onclick = function () {
|
||||
var reason = reasonInput.value.trim();
|
||||
if (!reason) {
|
||||
reasonInput.style.borderColor = '#e74c3c';
|
||||
reasonInput.focus();
|
||||
return;
|
||||
}
|
||||
submitBtn.disabled = true;
|
||||
submitBtn.textContent = '提交中…';
|
||||
|
||||
fetch(API_ROOT + '/report/submit', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-WP-Nonce': NONCE,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
target_type: data.target_type,
|
||||
target_id: data.target_id,
|
||||
category: catSelect.value,
|
||||
reason: reason,
|
||||
}),
|
||||
})
|
||||
.then(function (res) { return res.json(); })
|
||||
.then(function (result) {
|
||||
overlay.remove();
|
||||
if (result.success) {
|
||||
showToast(result.message || '举报已提交');
|
||||
} else {
|
||||
showToast(result.message || '提交失败', 'error');
|
||||
}
|
||||
})
|
||||
.catch(function () {
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.textContent = '提交举报';
|
||||
showToast('网络错误,请重试', 'error');
|
||||
});
|
||||
};
|
||||
btnRow.appendChild(submitBtn);
|
||||
modal.appendChild(btnRow);
|
||||
|
||||
overlay.appendChild(modal);
|
||||
overlay.addEventListener('click', function (e) {
|
||||
if (e.target === overlay) overlay.remove();
|
||||
});
|
||||
|
||||
document.body.appendChild(overlay);
|
||||
reasonInput.focus();
|
||||
}
|
||||
|
||||
function showToast(msg, type) {
|
||||
var toast = document.createElement('div');
|
||||
toast.textContent = msg;
|
||||
toast.style.cssText = 'position:fixed;top:20px;left:50%;transform:translateX(-50%);padding:12px 24px;border-radius:6px;color:#fff;font-size:14px;z-index:10000;transition:opacity 0.3s;';
|
||||
toast.style.background = type === 'error' ? '#e74c3c' : '#27ae60';
|
||||
document.body.appendChild(toast);
|
||||
setTimeout(function () {
|
||||
toast.style.opacity = '0';
|
||||
setTimeout(function () { toast.remove(); }, 300);
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
function initReportButtons() {
|
||||
document.addEventListener('click', function (e) {
|
||||
var btn = e.target.closest('[data-aksrt-report]');
|
||||
if (!btn) return;
|
||||
e.preventDefault();
|
||||
|
||||
try {
|
||||
var data = JSON.parse(btn.getAttribute('data-aksrt-report'));
|
||||
if (data && data.target_type && data.target_id) {
|
||||
createReportModal(data);
|
||||
}
|
||||
} catch {
|
||||
// invalid data attribute
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Auto-init on DOMContentLoaded
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initReportButtons);
|
||||
} else {
|
||||
initReportButtons();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* Reward (打赏) — dedicated module.
|
||||
*
|
||||
* Handles the reward modal: amount selection, custom amount input,
|
||||
* QR code display, and open/close interaction.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
;(function () {
|
||||
'use strict';
|
||||
|
||||
function initReward() {
|
||||
var btn = document.getElementById('action-reward');
|
||||
if (!btn) return;
|
||||
|
||||
var modal = document.getElementById('reward-modal');
|
||||
if (!modal) return;
|
||||
|
||||
var closeBtn = modal.querySelector('.reward-modal__close');
|
||||
var overlay = modal.querySelector('.reward-modal__overlay');
|
||||
var amountBtns = modal.querySelectorAll('.reward-amounts__btn');
|
||||
var customWrap = modal.querySelector('.reward-custom');
|
||||
var customInput = modal ? modal.querySelector('.reward-custom__input') : null;
|
||||
var customConfirm = modal ? modal.querySelector('.reward-custom__confirm') : null;
|
||||
var selectedAmount = 0;
|
||||
|
||||
/* ---- open / close ---- */
|
||||
function openReward() {
|
||||
modal.classList.add('is-open');
|
||||
document.body.style.overflow = 'hidden';
|
||||
}
|
||||
|
||||
function closeReward() {
|
||||
modal.classList.remove('is-open');
|
||||
document.body.style.overflow = '';
|
||||
// reset selection
|
||||
selectedAmount = 0;
|
||||
amountBtns.forEach(function (b) { b.classList.remove('is-active'); });
|
||||
if (customInput) customInput.value = '';
|
||||
}
|
||||
|
||||
btn.addEventListener('click', openReward);
|
||||
if (closeBtn) closeBtn.addEventListener('click', closeReward);
|
||||
if (overlay) overlay.addEventListener('click', closeReward);
|
||||
|
||||
document.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'Escape' && modal.classList.contains('is-open')) closeReward();
|
||||
});
|
||||
|
||||
/* ---- amount selection ---- */
|
||||
amountBtns.forEach(function (b) {
|
||||
b.addEventListener('click', function () {
|
||||
amountBtns.forEach(function (x) { x.classList.remove('is-active'); });
|
||||
b.classList.add('is-active');
|
||||
selectedAmount = parseInt(b.dataset.amount || '0', 10);
|
||||
// clear custom input when preset is chosen
|
||||
if (customInput) customInput.value = '';
|
||||
});
|
||||
});
|
||||
|
||||
/* ---- custom amount ---- */
|
||||
if (customInput) {
|
||||
customInput.addEventListener('focus', function () {
|
||||
amountBtns.forEach(function (x) { x.classList.remove('is-active'); });
|
||||
selectedAmount = 0;
|
||||
});
|
||||
customInput.addEventListener('input', function () {
|
||||
// strip non-digits
|
||||
customInput.value = customInput.value.replace(/[^\d]/g, '');
|
||||
});
|
||||
}
|
||||
|
||||
if (customConfirm) {
|
||||
customConfirm.addEventListener('click', function () {
|
||||
var val = customInput ? parseInt(customInput.value, 10) : 0;
|
||||
if (val > 0) {
|
||||
selectedAmount = val;
|
||||
amountBtns.forEach(function (x) { x.classList.remove('is-active'); });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- register with AksrtFrontend lifecycle ---- */
|
||||
if (window.AksrtFrontend && typeof window.AksrtFrontend.register === 'function') {
|
||||
window.AksrtFrontend.register('aksrt-reward', function () {
|
||||
initReward();
|
||||
});
|
||||
} else {
|
||||
// fallback: run on DOMContentLoaded
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initReward);
|
||||
} else {
|
||||
initReward();
|
||||
}
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,682 @@
|
||||
/**
|
||||
* 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 || {};
|
||||
|
||||
/* ==================== 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]');
|
||||
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;
|
||||
|
||||
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]) : defaultTab;
|
||||
if (name === 'signin') return 'credits';
|
||||
if (name === 'invite') return 'settings';
|
||||
return 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() {
|
||||
var name = this.getAttribute('data-tab');
|
||||
switchTo(name);
|
||||
updateUrl(name);
|
||||
});
|
||||
});
|
||||
|
||||
sidebarBtns.forEach(function(btn) {
|
||||
btn.addEventListener('click', function() {
|
||||
var name = this.getAttribute('data-tab');
|
||||
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 || '删除') + '">×</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 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' };
|
||||
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();
|
||||
initUnfavorite();
|
||||
initNotifications();
|
||||
initSettings();
|
||||
});
|
||||
} else {
|
||||
initDashboardNavigation();
|
||||
initProfileForm();
|
||||
initUnfavorite();
|
||||
initNotifications();
|
||||
initSettings();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* AKSRT User Home — 公开用户主页专属脚本
|
||||
*
|
||||
* 负责公开主页 Tab 切换和 URL 同步。
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function initUserHomeTabs() {
|
||||
var tabContainer = document.querySelector('.dashboard--public .dashboard-tabs');
|
||||
if (!tabContainer) return;
|
||||
|
||||
var tabs = tabContainer.querySelectorAll('[data-tab]');
|
||||
var panels = {};
|
||||
var defaultTab = tabs.length ? tabs[0].getAttribute('data-tab') : 'posts';
|
||||
|
||||
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 switchTo(name) {
|
||||
if (!panels[name]) name = defaultTab;
|
||||
|
||||
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;
|
||||
});
|
||||
}
|
||||
|
||||
function tabFromUrl() {
|
||||
var m = window.location.search.match(/[?&]tab=([^&]+)/);
|
||||
return m ? decodeURIComponent(m[1]) : defaultTab;
|
||||
}
|
||||
|
||||
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() {
|
||||
var name = this.getAttribute('data-tab');
|
||||
switchTo(name);
|
||||
updateUrl(name);
|
||||
});
|
||||
});
|
||||
|
||||
switchTo(tabFromUrl());
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initUserHomeTabs);
|
||||
} else {
|
||||
initUserHomeTabs();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,163 @@
|
||||
/**
|
||||
* AKSRT Section Navs — Article TOC / Scrollspy
|
||||
*
|
||||
* Auto-generates a table of contents from h1~h4 headings within
|
||||
* [data-nav] content areas. Scrollspy highlights the current section.
|
||||
* Collapsible sub-items when the TOC is tall.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var HEADING_SEL = 'h1, h2, h3, h4';
|
||||
var MIN_HEADINGS = 2;
|
||||
var SCROLL_OFFSET = 105;
|
||||
var MAX_HEIGHT_COLLAPSE = 380;
|
||||
|
||||
function initSectionNavs() {
|
||||
var navContainer = document.querySelector('[data-nav]');
|
||||
if (!navContainer) return;
|
||||
|
||||
var headings = navContainer.querySelectorAll(HEADING_SEL);
|
||||
if (headings.length < MIN_HEADINGS) return;
|
||||
|
||||
var tocContainer = document.querySelector('.posts-nav-lists, .aksrt-section-nav');
|
||||
if (!tocContainer) {
|
||||
tocContainer = document.createElement('nav');
|
||||
tocContainer.className = 'aksrt-section-nav';
|
||||
tocContainer.setAttribute('aria-label', '文章目录');
|
||||
var sidebar = document.querySelector('.content-layout__aside, .sidebar, .widget-area');
|
||||
if (sidebar) {
|
||||
sidebar.insertBefore(tocContainer, sidebar.firstChild);
|
||||
} else {
|
||||
navContainer.parentNode.insertBefore(tocContainer, navContainer);
|
||||
}
|
||||
}
|
||||
|
||||
var list = document.createElement('ul');
|
||||
list.className = 'aksrt-section-nav__list';
|
||||
|
||||
var items = [];
|
||||
headings.forEach(function (heading, i) {
|
||||
if (!heading.id) {
|
||||
heading.id = 'section-nav-' + i;
|
||||
}
|
||||
|
||||
var level = parseInt(heading.tagName.charAt(1), 10);
|
||||
var li = document.createElement('li');
|
||||
li.className = 'aksrt-section-nav__item aksrt-section-nav__item--h' + level;
|
||||
|
||||
var link = document.createElement('a');
|
||||
link.href = '#' + heading.id;
|
||||
link.textContent = heading.textContent.trim();
|
||||
link.className = 'aksrt-section-nav__link';
|
||||
|
||||
link.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
smoothScrollTo(heading);
|
||||
|
||||
// Expand collapsed panels containing the target
|
||||
var panel = heading.closest('[data-collapse], .collapse');
|
||||
if (panel) {
|
||||
panel.classList.add('show', 'is-open');
|
||||
var readMore = panel.previousElementSibling;
|
||||
if (readMore && readMore.classList.contains('read-more-open')) readMore.click();
|
||||
}
|
||||
});
|
||||
|
||||
li.appendChild(link);
|
||||
list.appendChild(li);
|
||||
items.push({ el: heading, link: link, li: li, level: level });
|
||||
});
|
||||
|
||||
tocContainer.innerHTML = '';
|
||||
tocContainer.appendChild(list);
|
||||
|
||||
// Collapse sub-items if TOC is tall
|
||||
if (tocContainer.scrollHeight > MAX_HEIGHT_COLLAPSE) {
|
||||
collapseSubItems(list, items);
|
||||
}
|
||||
|
||||
// Scrollspy
|
||||
var ticking = false;
|
||||
function onScroll() {
|
||||
if (ticking) return;
|
||||
ticking = true;
|
||||
requestAnimationFrame(function () {
|
||||
ticking = false;
|
||||
var scrollTop = window.pageYOffset + SCROLL_OFFSET;
|
||||
var activeIdx = 0;
|
||||
for (var i = items.length - 1; i >= 0; i--) {
|
||||
if (items[i].el.offsetTop <= scrollTop) {
|
||||
activeIdx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
items.forEach(function (item, idx) {
|
||||
item.link.classList.toggle('is-active', idx === activeIdx);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', onScroll, { passive: true });
|
||||
onScroll();
|
||||
|
||||
// URL hash auto-scroll
|
||||
if (window.location.hash) {
|
||||
var target = document.querySelector(window.location.hash);
|
||||
if (target) setTimeout(function () { smoothScrollTo(target); }, 100);
|
||||
}
|
||||
}
|
||||
|
||||
function smoothScrollTo(el) {
|
||||
if (window.aksrt && aksrt.scrollTopTo) {
|
||||
aksrt.scrollTopTo(el);
|
||||
} else {
|
||||
var top = el.getBoundingClientRect().top + window.pageYOffset - SCROLL_OFFSET;
|
||||
window.scrollTo({ top: Math.max(0, top), behavior: 'smooth' });
|
||||
}
|
||||
}
|
||||
|
||||
function collapseSubItems(list, items) {
|
||||
var parentStack = [];
|
||||
items.forEach(function (item) {
|
||||
while (parentStack.length && parentStack[parentStack.length - 1].level >= item.level) {
|
||||
parentStack.pop();
|
||||
}
|
||||
|
||||
if (item.level >= 3 && parentStack.length) {
|
||||
item.li.classList.add('yc');
|
||||
// Add collapse toggle to parent if not already there
|
||||
var parentLi = parentStack[parentStack.length - 1].li;
|
||||
if (!parentLi.querySelector('.nav-toggle-collapse')) {
|
||||
var toggle = document.createElement('span');
|
||||
toggle.className = 'nav-toggle-collapse';
|
||||
toggle.innerHTML = '<i class="fas fa-chevron-right"></i>';
|
||||
toggle.addEventListener('click', function (e) {
|
||||
e.stopPropagation();
|
||||
toggle.classList.toggle('fa-rotate-90');
|
||||
var next = parentLi.nextElementSibling;
|
||||
while (next && next.classList.contains('yc')) {
|
||||
next.classList.toggle('yc-open');
|
||||
next = next.nextElementSibling;
|
||||
}
|
||||
});
|
||||
parentLi.appendChild(toggle);
|
||||
}
|
||||
}
|
||||
|
||||
parentStack.push(item);
|
||||
});
|
||||
}
|
||||
|
||||
if (window.AksrtFrontend) {
|
||||
AksrtFrontend.register('aksrt-section-navs', function () { initSectionNavs(); });
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initSectionNavs);
|
||||
} else {
|
||||
initSectionNavs();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* AKSRT Share Data Builder
|
||||
*
|
||||
* Single source of truth for share payloads. Every share surface
|
||||
* (dropdown links, copy, WeChat bridge, poster) resolves its data through
|
||||
* window.AksrtShareData so no script assembles title/url/cover/qrcode on its
|
||||
* own.
|
||||
*
|
||||
* Canonical payload shape:
|
||||
* { title, url, desc, text, image, qrcode, author, date, siteName }
|
||||
*
|
||||
* Data is read from the nearest [data-share-*] context (falling back to
|
||||
* #share-dropdown), then to OpenGraph/meta tags and document defaults.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function metaContent(selectors) {
|
||||
for (var i = 0; i < selectors.length; i += 1) {
|
||||
var node = document.querySelector(selectors[i]);
|
||||
var content = node ? node.getAttribute('content') : '';
|
||||
if (content) return content;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function siteName() {
|
||||
return (
|
||||
metaContent(['meta[property="og:site_name"]']) ||
|
||||
(document.querySelector('.site-title, .logo-text, .site-nav__logo') || {}).textContent ||
|
||||
document.title ||
|
||||
''
|
||||
).trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the element that carries the share data attributes for a node.
|
||||
*/
|
||||
function context(node) {
|
||||
var source = node && typeof node.closest === 'function'
|
||||
? node.closest('[data-share-url], [data-share-title], [data-share-desc], [data-share-image], [data-aksrt-poster]')
|
||||
: null;
|
||||
return source || document.getElementById('share-dropdown');
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a QR data URL for a link, reusing the WeChat share encoder
|
||||
* when available. Returns '' if no encoder is loaded.
|
||||
*/
|
||||
function qrcode(url) {
|
||||
if (window.AksrtShare && typeof window.AksrtShare.buildQrDataUrl === 'function' && url) {
|
||||
return window.AksrtShare.buildQrDataUrl(url, 200) || '';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a canonical share payload for a triggering node.
|
||||
*
|
||||
* @param {Element} node Triggering element (button/link).
|
||||
* @param {Object} [overrides] Optional explicit overrides.
|
||||
* @returns {Object}
|
||||
*/
|
||||
function resolve(node, overrides) {
|
||||
var ctx = context(node);
|
||||
|
||||
function attr(name) {
|
||||
return (node && node.getAttribute && node.getAttribute(name)) ||
|
||||
(ctx && ctx.getAttribute && ctx.getAttribute(name)) || '';
|
||||
}
|
||||
|
||||
var url = attr('data-share-url') || window.location.href;
|
||||
var payload = {
|
||||
title: attr('data-share-title') || document.title,
|
||||
url: url,
|
||||
desc: attr('data-share-desc') || metaContent(['meta[property="og:description"]', 'meta[name="description"]']),
|
||||
text: attr('data-share-text') || '',
|
||||
image: attr('data-share-image') || metaContent(['meta[property="og:image"]']),
|
||||
qrcode: attr('data-share-qrcode') || '',
|
||||
author: attr('data-share-author') || '',
|
||||
date: attr('data-share-date') || '',
|
||||
siteName: attr('data-share-site') || siteName()
|
||||
};
|
||||
|
||||
if (!payload.qrcode) {
|
||||
payload.qrcode = qrcode(payload.url);
|
||||
}
|
||||
|
||||
if (overrides && typeof overrides === 'object') {
|
||||
Object.keys(overrides).forEach(function (key) {
|
||||
if (overrides[key] !== undefined && overrides[key] !== null && overrides[key] !== '') {
|
||||
payload[key] = overrides[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
window.AksrtShareData = {
|
||||
resolve: resolve,
|
||||
qrcode: qrcode,
|
||||
siteName: siteName
|
||||
};
|
||||
})();
|
||||
@@ -0,0 +1,390 @@
|
||||
/**
|
||||
* AKSRT Sign/Register — 统一认证交互脚本
|
||||
*
|
||||
* 对齐 zibll 的 sign-register.js:
|
||||
* - 短信验证码倒计时(60 秒 + 服务端 remaining_time)
|
||||
* - 手机号注册/登录表单交互
|
||||
* - 人机验证联动
|
||||
* - 密码可见性切换
|
||||
* - 协议勾选校验
|
||||
*/
|
||||
;(() => {
|
||||
'use strict'
|
||||
|
||||
const COUNTDOWN_KEY = 'aksrt_sms_cooldown'
|
||||
const DEFAULT_COOLDOWN = 60
|
||||
const REST_BASE = '/wp-json/aksrt/v1'
|
||||
|
||||
/**
|
||||
* 初始化所有认证页面
|
||||
*/
|
||||
function initAuthPages() {
|
||||
initSmsButtons()
|
||||
initPasswordToggles()
|
||||
initAgreementChecks()
|
||||
initFormValidation()
|
||||
initPhoneAuthTabs()
|
||||
}
|
||||
|
||||
/* =================================================================
|
||||
* SMS 验证码发送 + 倒计时
|
||||
* ================================================================= */
|
||||
|
||||
function initSmsButtons() {
|
||||
document.querySelectorAll('[data-aksrt-sms-trigger]').forEach(btn => {
|
||||
const cooldown = parseInt(btn.dataset.cooldown || DEFAULT_COOLDOWN, 10)
|
||||
|
||||
// 恢复页面刷新后的倒计时
|
||||
const stored = sessionStorage.getItem(COUNTDOWN_KEY)
|
||||
if (stored) {
|
||||
const remaining = Math.ceil((parseInt(stored, 10) - Date.now()) / 1000)
|
||||
if (remaining > 0) {
|
||||
startCountdown(btn, remaining)
|
||||
}
|
||||
}
|
||||
|
||||
btn.addEventListener('click', e => {
|
||||
e.preventDefault()
|
||||
if (btn.disabled) return
|
||||
sendSmsCode(btn, cooldown)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function sendSmsCode(btn, cooldown) {
|
||||
const phoneInput = document.querySelector(btn.dataset.aksrtSmsPhone || '[data-aksrt-phone-input]')
|
||||
const phone = phoneInput ? phoneInput.value.trim() : ''
|
||||
|
||||
if (!/^1[3-9]\d{9}$/.test(phone)) {
|
||||
showToast('请输入正确的手机号', 'warning')
|
||||
if (phoneInput) phoneInput.focus()
|
||||
return
|
||||
}
|
||||
|
||||
// 人机验证联动
|
||||
const captchaState = window.AKSRTCaptchaState
|
||||
const scene = btn.dataset.aksrtSmsScene || 'register'
|
||||
if (captchaState && captchaState.scenes && captchaState.scenes[scene]) {
|
||||
captchaState.scenes[scene].verify(() => {
|
||||
doSendSms(btn, phone, cooldown)
|
||||
})
|
||||
} else {
|
||||
doSendSms(btn, phone, cooldown)
|
||||
}
|
||||
}
|
||||
|
||||
function doSendSms(btn, phone, cooldown) {
|
||||
btn.disabled = true
|
||||
const original = btn.textContent
|
||||
btn.textContent = '发送中...'
|
||||
|
||||
// 收集人机验证字段
|
||||
const form = btn.closest('form')
|
||||
const captchaData = collectCaptchaFields(form)
|
||||
|
||||
fetch(REST_BASE + '/auth/send-sms-code', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ phone, ...captchaData }),
|
||||
})
|
||||
.then(r => r.json().then(data => ({ ok: r.ok, data })))
|
||||
.then(({ ok, data }) => {
|
||||
if (ok && data.success) {
|
||||
showToast(data.message || '验证码已发送', 'success')
|
||||
const seconds = (data.data && data.data.remaining_time) || cooldown
|
||||
sessionStorage.setItem(COUNTDOWN_KEY, String(Date.now() + seconds * 1000))
|
||||
startCountdown(btn, seconds)
|
||||
} else {
|
||||
const msg = (data.data && data.data.message) || data.message || '发送失败'
|
||||
showToast(msg, 'error')
|
||||
const remaining = data.data && data.data.remaining_time
|
||||
if (remaining && remaining > 0) {
|
||||
sessionStorage.setItem(COUNTDOWN_KEY, String(Date.now() + remaining * 1000))
|
||||
startCountdown(btn, remaining)
|
||||
} else {
|
||||
btn.disabled = false
|
||||
btn.textContent = original
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
showToast('网络错误,请重试', 'error')
|
||||
btn.disabled = false
|
||||
btn.textContent = original
|
||||
})
|
||||
}
|
||||
|
||||
function startCountdown(btn, seconds) {
|
||||
let remaining = Math.max(1, Math.floor(seconds))
|
||||
btn.disabled = true
|
||||
btn.textContent = remaining + 's'
|
||||
const timer = setInterval(() => {
|
||||
remaining--
|
||||
if (remaining <= 0) {
|
||||
clearInterval(timer)
|
||||
btn.disabled = false
|
||||
btn.textContent = '获取验证码'
|
||||
sessionStorage.removeItem(COUNTDOWN_KEY)
|
||||
} else {
|
||||
btn.textContent = remaining + 's'
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
/* =================================================================
|
||||
* 手机号注册/登录表单
|
||||
* ================================================================= */
|
||||
|
||||
function initPhoneAuthTabs() {
|
||||
document.querySelectorAll('[data-aksrt-auth-tab]').forEach(tab => {
|
||||
tab.addEventListener('click', e => {
|
||||
e.preventDefault()
|
||||
const target = tab.dataset.aksrtAuthTab
|
||||
switchAuthTab(target)
|
||||
})
|
||||
})
|
||||
|
||||
// 手机号注册表单
|
||||
const phoneRegForm = document.getElementById('aksrt-phone-register-form')
|
||||
if (phoneRegForm) {
|
||||
phoneRegForm.addEventListener('submit', e => {
|
||||
e.preventDefault()
|
||||
handlePhoneRegister(phoneRegForm)
|
||||
})
|
||||
}
|
||||
|
||||
// 手机号登录表单
|
||||
const phoneLoginForm = document.getElementById('aksrt-phone-login-form')
|
||||
if (phoneLoginForm) {
|
||||
phoneLoginForm.addEventListener('submit', e => {
|
||||
e.preventDefault()
|
||||
handlePhoneLogin(phoneLoginForm)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function switchAuthTab(tabName) {
|
||||
document.querySelectorAll('[data-auth-panel]').forEach(panel => {
|
||||
panel.style.display = panel.dataset.authPanel === tabName ? '' : 'none'
|
||||
})
|
||||
document.querySelectorAll('[data-aksrt-auth-tab]').forEach(tab => {
|
||||
tab.classList.toggle('is-active', tab.dataset.aksrtAuthTab === tabName)
|
||||
})
|
||||
}
|
||||
|
||||
function handlePhoneRegister(form) {
|
||||
const phone = form.querySelector('[name="phone"]')?.value?.trim()
|
||||
const code = form.querySelector('[name="code"]')?.value?.trim()
|
||||
const password = form.querySelector('[name="password"]')?.value
|
||||
const confirm = form.querySelector('[name="password_confirm"]')?.value
|
||||
const inviteCode = form.querySelector('[name="invite_code"]')?.value?.trim()
|
||||
|
||||
if (!phone || !code || !password) {
|
||||
showToast('请填写完整信息', 'warning')
|
||||
return
|
||||
}
|
||||
if (password !== confirm) {
|
||||
showToast('两次密码不一致', 'warning')
|
||||
return
|
||||
}
|
||||
if (password.length < 6) {
|
||||
showToast('密码至少 6 位', 'warning')
|
||||
return
|
||||
}
|
||||
|
||||
const submitBtn = form.querySelector('[type="submit"]')
|
||||
if (submitBtn) {
|
||||
submitBtn.disabled = true
|
||||
submitBtn.textContent = '注册中...'
|
||||
}
|
||||
|
||||
const captchaData = collectCaptchaFields(form)
|
||||
|
||||
fetch(REST_BASE + '/auth/phone-register', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ phone, code, password, invite_code: inviteCode, ...captchaData }),
|
||||
})
|
||||
.then(r => r.json().then(data => ({ ok: r.ok, data })))
|
||||
.then(({ ok, data }) => {
|
||||
if (ok && data.success) {
|
||||
showToast(data.message || '注册成功', 'success')
|
||||
setTimeout(() => {
|
||||
window.location.href = data.data?.redirect || '/'
|
||||
}, 500)
|
||||
} else {
|
||||
showToast(data.message || '注册失败', 'error')
|
||||
if (submitBtn) {
|
||||
submitBtn.disabled = false
|
||||
submitBtn.textContent = '注册'
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
showToast('网络错误', 'error')
|
||||
if (submitBtn) {
|
||||
submitBtn.disabled = false
|
||||
submitBtn.textContent = '注册'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function handlePhoneLogin(form) {
|
||||
const phone = form.querySelector('[name="phone"]')?.value?.trim()
|
||||
const password = form.querySelector('[name="password"]')?.value
|
||||
const loginMode = form.querySelector('[name="login_mode"]')?.value || 'password'
|
||||
|
||||
if (!phone) {
|
||||
showToast('请输入手机号', 'warning')
|
||||
return
|
||||
}
|
||||
|
||||
const submitBtn = form.querySelector('[type="submit"]')
|
||||
if (submitBtn) {
|
||||
submitBtn.disabled = true
|
||||
submitBtn.textContent = '登录中...'
|
||||
}
|
||||
|
||||
let endpoint, body
|
||||
if (loginMode === 'code') {
|
||||
const code = form.querySelector('[name="code"]')?.value?.trim()
|
||||
if (!code) {
|
||||
showToast('请输入验证码', 'warning')
|
||||
if (submitBtn) { submitBtn.disabled = false; submitBtn.textContent = '登录' }
|
||||
return
|
||||
}
|
||||
endpoint = '/auth/phone-code-login'
|
||||
body = { phone, code }
|
||||
} else {
|
||||
if (!password) {
|
||||
showToast('请输入密码', 'warning')
|
||||
if (submitBtn) { submitBtn.disabled = false; submitBtn.textContent = '登录' }
|
||||
return
|
||||
}
|
||||
endpoint = '/auth/phone-login'
|
||||
body = { phone, password }
|
||||
}
|
||||
|
||||
fetch(REST_BASE + endpoint, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(body),
|
||||
})
|
||||
.then(r => r.json().then(data => ({ ok: r.ok, data })))
|
||||
.then(({ ok, data }) => {
|
||||
if (ok && data.success) {
|
||||
showToast('登录成功', 'success')
|
||||
setTimeout(() => {
|
||||
window.location.href = data.data?.redirect || '/'
|
||||
}, 500)
|
||||
} else {
|
||||
showToast(data.message || '登录失败', 'error')
|
||||
if (submitBtn) {
|
||||
submitBtn.disabled = false
|
||||
submitBtn.textContent = '登录'
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
showToast('网络错误', 'error')
|
||||
if (submitBtn) {
|
||||
submitBtn.disabled = false
|
||||
submitBtn.textContent = '登录'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/* =================================================================
|
||||
* 辅助功能
|
||||
* ================================================================= */
|
||||
|
||||
function collectCaptchaFields(form) {
|
||||
if (!form) return {}
|
||||
const fields = {}
|
||||
const names = [
|
||||
'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'
|
||||
]
|
||||
names.forEach(name => {
|
||||
const el = form.querySelector('[name="' + name + '"]')
|
||||
if (el && el.value) fields[name] = el.value
|
||||
})
|
||||
return fields
|
||||
}
|
||||
|
||||
function initPasswordToggles() {
|
||||
document.querySelectorAll('[data-aksrt-password-toggle]').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
const input = btn.closest('.input-wrap')?.querySelector('input')
|
||||
if (!input) return
|
||||
const isPassword = input.type === 'password'
|
||||
input.type = isPassword ? 'text' : 'password'
|
||||
const icon = btn.querySelector('i, svg')
|
||||
if (icon) {
|
||||
if (icon.tagName === 'I') {
|
||||
icon.className = isPassword ? 'fas fa-eye-slash' : 'fas fa-eye'
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function initAgreementChecks() {
|
||||
document.querySelectorAll('form[data-aksrt-auth-form]').forEach(form => {
|
||||
const checkbox = form.querySelector('[data-aksrt-agreement]')
|
||||
const submitBtn = form.querySelector('[type="submit"]')
|
||||
if (checkbox && submitBtn) {
|
||||
const update = () => { submitBtn.disabled = !checkbox.checked }
|
||||
checkbox.addEventListener('change', update)
|
||||
update()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function initFormValidation() {
|
||||
document.querySelectorAll('form[data-aksrt-auth-form]').forEach(form => {
|
||||
form.addEventListener('submit', e => {
|
||||
const password = form.querySelector('[name="password"]')
|
||||
const confirm = form.querySelector('[name="password_confirm"]')
|
||||
if (password && confirm && password.value !== confirm.value) {
|
||||
e.preventDefault()
|
||||
showToast('两次密码不一致', 'warning')
|
||||
confirm.focus()
|
||||
return
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function showToast(message, type) {
|
||||
if (typeof window.aksrtShowToast === 'function') {
|
||||
window.aksrtShowToast(message, type)
|
||||
return
|
||||
}
|
||||
const toast = document.createElement('div')
|
||||
toast.className = 'aksrt-auth-toast aksrt-auth-toast--' + (type || 'info')
|
||||
toast.textContent = message
|
||||
document.body.appendChild(toast)
|
||||
setTimeout(() => toast.classList.add('aksrt-auth-toast--show'), 10)
|
||||
setTimeout(() => {
|
||||
toast.classList.remove('aksrt-auth-toast--show')
|
||||
setTimeout(() => toast.remove(), 300)
|
||||
}, 3000)
|
||||
}
|
||||
|
||||
// 初始化
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initAuthPages)
|
||||
} else {
|
||||
initAuthPages()
|
||||
}
|
||||
|
||||
// 暴露给外部
|
||||
window.AKSRTSignRegister = {
|
||||
init: initAuthPages,
|
||||
sendSmsCode,
|
||||
switchAuthTab,
|
||||
showToast,
|
||||
}
|
||||
})()
|
||||
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* AKSRT Site Notice — Popup notice with cookie-based frequency control
|
||||
*
|
||||
* Identity-based policy check is done server-side (PHP).
|
||||
* JS only handles: show/hide animation, cookie dismissal, expiry.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var el = document.getElementById('aksrt-site-notice');
|
||||
if (!el) return;
|
||||
|
||||
// 弹窗周期(小时),0=永不过期
|
||||
var expiresHours = parseInt(el.dataset.expires || '24', 10) || 0;
|
||||
var cookieName = 'aksrt_notice_seen';
|
||||
|
||||
function getCookie(name) {
|
||||
var match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
|
||||
return match ? decodeURIComponent(match[2]) : null;
|
||||
}
|
||||
|
||||
function setCookie(name, value, days) {
|
||||
var expires = '';
|
||||
if (days) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime() + days * 86400000);
|
||||
expires = '; expires=' + date.toUTCString();
|
||||
}
|
||||
document.cookie = name + '=' + encodeURIComponent(value) + expires + '; path=/; SameSite=Lax';
|
||||
}
|
||||
|
||||
function shouldShow() {
|
||||
if (expiresHours === 0) return true; // 永不过期,总是显示
|
||||
var seen = getCookie(cookieName);
|
||||
if (!seen) return true;
|
||||
var seenTs = parseInt(seen, 10);
|
||||
if (!seenTs || seenTs <= 0) return true;
|
||||
var now = Math.floor(Date.now() / 1000);
|
||||
return (now - seenTs) >= (expiresHours * 3600);
|
||||
}
|
||||
|
||||
function dismiss() {
|
||||
// 写入当前时间戳
|
||||
var days = expiresHours > 0 ? Math.ceil(expiresHours / 24) : 365;
|
||||
setCookie(cookieName, String(Math.floor(Date.now() / 1000)), days);
|
||||
close();
|
||||
}
|
||||
|
||||
function close() {
|
||||
el.style.opacity = '0';
|
||||
setTimeout(function () {
|
||||
el.style.display = 'none';
|
||||
}, 300);
|
||||
}
|
||||
|
||||
function show() {
|
||||
el.style.display = '';
|
||||
el.style.opacity = '0';
|
||||
requestAnimationFrame(function () {
|
||||
el.style.transition = 'opacity 0.3s';
|
||||
el.style.opacity = '1';
|
||||
});
|
||||
}
|
||||
|
||||
// Bind events
|
||||
var closeBtn = el.querySelector('.aksrt-site-notice__close');
|
||||
var overlay = el.querySelector('.aksrt-site-notice__overlay');
|
||||
// 所有 dismiss 按钮(包括 data-dismiss="notice" 的按钮和链接)
|
||||
var dismissBtns = el.querySelectorAll('[data-dismiss="notice"]');
|
||||
|
||||
if (closeBtn) closeBtn.addEventListener('click', dismiss);
|
||||
if (overlay) overlay.addEventListener('click', dismiss);
|
||||
for (var i = 0; i < dismissBtns.length; i++) {
|
||||
dismissBtns[i].addEventListener('click', dismiss);
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'Escape' && el.style.display !== 'none') {
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
// Show on load if needed
|
||||
if (shouldShow()) {
|
||||
// Delay slightly so it doesn't flash on fast navigations
|
||||
setTimeout(show, 500);
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,406 @@
|
||||
/**
|
||||
* AKSRT Slider CAPTCHA
|
||||
*
|
||||
* Canvas-based slider puzzle CAPTCHA verification.
|
||||
* No jQuery dependency — pure vanilla JS.
|
||||
*
|
||||
* Usage:
|
||||
* var captcha = new AksrtSliderCaptcha(container, {
|
||||
* onSuccess: function(token) { ... },
|
||||
* onFail: function() { ... },
|
||||
* setSrc: function(callback) { callback(imageUrl); }
|
||||
* });
|
||||
* captcha.reset();
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var DEFAULTS = {
|
||||
width: 280,
|
||||
height: 170,
|
||||
sliderL: 42,
|
||||
sliderR: 9,
|
||||
offset: 8,
|
||||
barText: '向右拖动滑块完成验证',
|
||||
successText: '验证成功',
|
||||
failText: '验证失败,请重试',
|
||||
loadingText: '加载中...',
|
||||
maxLoadCount: 3,
|
||||
onSuccess: function () {},
|
||||
onFail: function () {},
|
||||
setSrc: function (callback) { callback(''); },
|
||||
};
|
||||
|
||||
function AksrtSliderCaptcha(element, options) {
|
||||
this.el = typeof element === 'string' ? document.querySelector(element) : element;
|
||||
if (!this.el) return;
|
||||
this.options = {};
|
||||
for (var k in DEFAULTS) this.options[k] = DEFAULTS[k];
|
||||
if (options) { for (var k in options) this.options[k] = options[k]; }
|
||||
this.loadCount = 0;
|
||||
this.init();
|
||||
}
|
||||
|
||||
AksrtSliderCaptcha.prototype.init = function () {
|
||||
this.el.style.position = 'relative';
|
||||
this.el.style.width = this.options.width + 'px';
|
||||
this.el.style.margin = '0 auto';
|
||||
this.el.innerHTML = '';
|
||||
this.initDOM();
|
||||
this.initImg();
|
||||
};
|
||||
|
||||
AksrtSliderCaptcha.prototype.initDOM = function () {
|
||||
var o = this.options;
|
||||
|
||||
// Canvas container
|
||||
this.canvasWrap = document.createElement('div');
|
||||
this.canvasWrap.className = 'aksrt-captcha__canvas-wrap';
|
||||
this.canvasWrap.style.cssText = 'position:relative;overflow:hidden;border-radius:8px;background:#f0f0f0;';
|
||||
|
||||
this.canvas = document.createElement('canvas');
|
||||
this.canvas.width = o.width;
|
||||
this.canvas.height = o.height;
|
||||
this.canvasCtx = this.canvas.getContext('2d');
|
||||
|
||||
this.block = document.createElement('canvas');
|
||||
this.block.width = o.width;
|
||||
this.block.height = o.height;
|
||||
this.blockCtx = this.block.getContext('2d');
|
||||
|
||||
this.canvasWrap.appendChild(this.canvas);
|
||||
this.canvasWrap.appendChild(this.block);
|
||||
|
||||
// Refresh button
|
||||
this.refreshBtn = document.createElement('div');
|
||||
this.refreshBtn.className = 'aksrt-captcha__refresh';
|
||||
this.refreshBtn.innerHTML = '↻';
|
||||
this.refreshBtn.style.cssText = 'position:absolute;top:6px;right:6px;cursor:pointer;font-size:18px;color:#fff;background:rgba(0,0,0,0.3);border-radius:50%;width:28px;height:28px;display:flex;align-items:center;justify-content:center;z-index:5;';
|
||||
this.canvasWrap.appendChild(this.refreshBtn);
|
||||
|
||||
// Slider bar
|
||||
this.sliderBar = document.createElement('div');
|
||||
this.sliderBar.className = 'aksrt-captcha__bar';
|
||||
this.sliderBar.style.cssText = 'position:relative;height:40px;border-radius:20px;background:#e8e8e8;margin-top:10px;user-select:none;';
|
||||
|
||||
this.sliderMask = document.createElement('div');
|
||||
this.sliderMask.className = 'aksrt-captcha__mask';
|
||||
this.sliderMask.style.cssText = 'position:absolute;top:0;left:0;height:100%;border-radius:20px;background:linear-gradient(90deg,#1890ff,#36cfc9);width:0;transition:background 0.3s;';
|
||||
|
||||
this.slider = document.createElement('div');
|
||||
this.slider.className = 'aksrt-captcha__slider';
|
||||
this.slider.style.cssText = 'position:absolute;top:0;left:0;width:44px;height:40px;border-radius:20px;background:#fff;box-shadow:0 2px 8px rgba(0,0,0,0.15);cursor:grab;display:flex;align-items:center;justify-content:center;font-size:18px;z-index:2;transition:box-shadow 0.2s;';
|
||||
this.slider.innerHTML = '❯';
|
||||
|
||||
this.text = document.createElement('div');
|
||||
this.text.className = 'aksrt-captcha__text';
|
||||
this.text.style.cssText = 'position:absolute;top:0;left:0;width:100%;height:100%;display:flex;align-items:center;justify-content:center;color:#999;font-size:14px;pointer-events:none;';
|
||||
this.text.textContent = o.barText;
|
||||
|
||||
this.sliderBar.appendChild(this.sliderMask);
|
||||
this.sliderBar.appendChild(this.slider);
|
||||
this.sliderBar.appendChild(this.text);
|
||||
|
||||
this.el.appendChild(this.canvasWrap);
|
||||
this.el.appendChild(this.sliderBar);
|
||||
|
||||
this.bindEvents();
|
||||
};
|
||||
|
||||
AksrtSliderCaptcha.prototype.initImg = function () {
|
||||
var self = this;
|
||||
this.loadCount++;
|
||||
if (this.loadCount > this.options.maxLoadCount) {
|
||||
this.text.textContent = '加载失败';
|
||||
return;
|
||||
}
|
||||
|
||||
this.text.textContent = this.options.loadingText;
|
||||
this.slider.style.display = 'none';
|
||||
|
||||
this.options.setSrc(function (src) {
|
||||
if (!src) {
|
||||
self.text.textContent = '验证服务不可用';
|
||||
return;
|
||||
}
|
||||
var img = new Image();
|
||||
img.crossOrigin = 'anonymous';
|
||||
img.onload = function () {
|
||||
self.bgImg = img;
|
||||
self.drawBg();
|
||||
self.drawBlock();
|
||||
self.slider.style.display = '';
|
||||
self.text.textContent = self.options.barText;
|
||||
};
|
||||
img.onerror = function () {
|
||||
self.initImg();
|
||||
};
|
||||
img.src = src;
|
||||
});
|
||||
};
|
||||
|
||||
AksrtSliderCaptcha.prototype.drawBg = function () {
|
||||
var o = this.options;
|
||||
this.canvasCtx.drawImage(this.bgImg, 0, 0, o.width, o.height);
|
||||
this.canvasCtx.globalAlpha = 0.6;
|
||||
this.canvasCtx.fillStyle = '#000';
|
||||
this.canvasCtx.fillRect(0, 0, o.width, o.height);
|
||||
this.canvasCtx.globalAlpha = 1;
|
||||
};
|
||||
|
||||
AksrtSliderCaptcha.prototype.drawBlock = function () {
|
||||
var o = this.options;
|
||||
var x = o.sliderL + Math.random() * (o.width - o.sliderL * 2 - 20);
|
||||
var y = 10 + Math.random() * (o.height - o.sliderL - 20);
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
|
||||
var ctx = this.blockCtx;
|
||||
ctx.clearRect(0, 0, o.width, o.height);
|
||||
|
||||
// Draw the puzzle piece shape
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x, y);
|
||||
ctx.lineTo(x + o.sliderL / 2, y);
|
||||
ctx.arc(x + o.sliderL / 2, y - o.sliderR, o.sliderR, 0.5 * Math.PI, 2.5 * Math.PI, false);
|
||||
ctx.lineTo(x + o.sliderL, y);
|
||||
ctx.lineTo(x + o.sliderL, y + o.sliderL / 2);
|
||||
ctx.arc(x + o.sliderL + o.sliderR, y + o.sliderL / 2, o.sliderR, Math.PI, 0, false);
|
||||
ctx.lineTo(x + o.sliderL, y + o.sliderL);
|
||||
ctx.lineTo(x, y + o.sliderL);
|
||||
ctx.closePath();
|
||||
|
||||
ctx.fillStyle = 'rgba(255,255,255,0.8)';
|
||||
ctx.fill();
|
||||
ctx.strokeStyle = 'rgba(255,255,255,0.5)';
|
||||
ctx.lineWidth = 2;
|
||||
ctx.stroke();
|
||||
|
||||
// Clip and draw image portion
|
||||
ctx.save();
|
||||
ctx.clip();
|
||||
ctx.drawImage(this.bgImg, 0, 0, o.width, o.height);
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
AksrtSliderCaptcha.prototype.bindEvents = function () {
|
||||
var self = this;
|
||||
var o = this.options;
|
||||
var dragging = false;
|
||||
var startX = 0;
|
||||
var currentX = 0;
|
||||
var maxMove = o.width - o.sliderL - 10;
|
||||
var trail = []; // y-axis trail for behavior verification
|
||||
|
||||
function onStart(e) {
|
||||
e.preventDefault();
|
||||
dragging = true;
|
||||
trail = [];
|
||||
startX = (e.touches ? e.touches[0].clientX : e.clientX) || 0;
|
||||
self.slider.style.cursor = 'grabbing';
|
||||
self.slider.style.boxShadow = '0 4px 12px rgba(0,0,0,0.25)';
|
||||
}
|
||||
|
||||
function onMove(e) {
|
||||
if (!dragging) return;
|
||||
e.preventDefault();
|
||||
var clientX = e.touches ? e.touches[0].clientX : e.clientX;
|
||||
var clientY = e.touches ? e.touches[0].clientY : e.clientY;
|
||||
currentX = Math.max(0, Math.min(maxMove, clientX - startX));
|
||||
trail.push(Math.round(clientY));
|
||||
self.slider.style.left = currentX + 'px';
|
||||
self.sliderMask.style.width = (currentX + 22) + 'px';
|
||||
self.block.style.left = currentX + 'px';
|
||||
}
|
||||
|
||||
function onEnd() {
|
||||
if (!dragging) return;
|
||||
dragging = false;
|
||||
self.slider.style.cursor = 'grab';
|
||||
self.slider.style.boxShadow = '0 2px 8px rgba(0,0,0,0.15)';
|
||||
|
||||
var positionOk = Math.abs(currentX - self.x) < o.offset;
|
||||
var behaviorOk = verifyTrail(trail);
|
||||
|
||||
if (positionOk && behaviorOk) {
|
||||
self.onSuccess(trail, currentX);
|
||||
} else {
|
||||
self.onFail();
|
||||
}
|
||||
}
|
||||
|
||||
this.slider.addEventListener('mousedown', onStart);
|
||||
this.slider.addEventListener('touchstart', onStart, { passive: false });
|
||||
document.addEventListener('mousemove', onMove);
|
||||
document.addEventListener('touchmove', onMove, { passive: false });
|
||||
document.addEventListener('mouseup', onEnd);
|
||||
document.addEventListener('touchend', onEnd);
|
||||
|
||||
this.refreshBtn.addEventListener('click', function () {
|
||||
self.reset();
|
||||
});
|
||||
};
|
||||
|
||||
// Trail behavior verification: stddev of y-axis must be > 0 (not a robot straight line)
|
||||
function verifyTrail(trail) {
|
||||
if (!trail || trail.length < 5) return false;
|
||||
var sum = 0;
|
||||
for (var i = 0; i < trail.length; i++) sum += trail[i];
|
||||
var avg = sum / trail.length;
|
||||
var variance = 0;
|
||||
for (var j = 0; j < trail.length; j++) variance += (trail[j] - avg) * (trail[j] - avg);
|
||||
var stddev = Math.sqrt(variance / trail.length);
|
||||
return stddev > 0;
|
||||
}
|
||||
|
||||
// Encode trail + position for server verification
|
||||
function encodePayload(trail, spliced) {
|
||||
var str = JSON.stringify({ t: trail, s: Math.round(spliced), ts: Date.now() });
|
||||
try { return btoa(str); } catch (e) { return str; }
|
||||
}
|
||||
|
||||
AksrtSliderCaptcha.prototype.onSuccess = function (trail, spliced) {
|
||||
var self = this;
|
||||
var o = this.options;
|
||||
this.sliderBar.classList.add('sliderContainer_success');
|
||||
this.sliderMask.style.background = '#52c41a';
|
||||
this.text.textContent = o.successText;
|
||||
this.text.style.color = '#52c41a';
|
||||
this.slider.innerHTML = '✓';
|
||||
this.slider.style.color = '#52c41a';
|
||||
this.slider.style.cursor = 'default';
|
||||
|
||||
var payload = encodePayload(trail || [], spliced || 0);
|
||||
|
||||
// Server token verification if endpoint configured
|
||||
if (o.serverVerify) {
|
||||
var ajaxUrl = (window.aksrtData && aksrtData.ajaxUrl) || '/wp-admin/admin-ajax.php';
|
||||
var params = new URLSearchParams();
|
||||
params.set('action', 'aksrt_captcha_verify');
|
||||
if (window.aksrtData && aksrtData.nonce) params.set('nonce', aksrtData.nonce);
|
||||
params.set('payload', payload);
|
||||
if (o.scene) params.set('scene', o.scene);
|
||||
|
||||
fetch(ajaxUrl, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
|
||||
credentials: 'same-origin',
|
||||
body: params.toString()
|
||||
})
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (json) {
|
||||
if (json && json.success && json.data && json.data.token) {
|
||||
if (typeof o.onSuccess === 'function') o.onSuccess(json.data.token);
|
||||
} else {
|
||||
self.onFail();
|
||||
}
|
||||
})
|
||||
.catch(function () { self.onFail(); });
|
||||
} else {
|
||||
if (typeof o.onSuccess === 'function') {
|
||||
setTimeout(function () { o.onSuccess(payload); }, 300);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
AksrtSliderCaptcha.prototype.onFail = function () {
|
||||
var self = this;
|
||||
var o = this.options;
|
||||
this.sliderBar.classList.add('sliderContainer_fail');
|
||||
this.sliderMask.style.background = '#ff4d4f';
|
||||
this.text.textContent = o.failText;
|
||||
this.text.style.color = '#ff4d4f';
|
||||
this.slider.style.color = '#ff4d4f';
|
||||
|
||||
if (typeof o.onFail === 'function') o.onFail();
|
||||
|
||||
setTimeout(function () {
|
||||
self.sliderBar.classList.remove('sliderContainer_fail');
|
||||
self.reset();
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
AksrtSliderCaptcha.prototype.reset = function () {
|
||||
this.slider.style.left = '0px';
|
||||
this.sliderMask.style.width = '0px';
|
||||
this.block.style.left = '0px';
|
||||
this.sliderMask.style.background = 'linear-gradient(90deg,#1890ff,#36cfc9)';
|
||||
this.text.style.color = '#999';
|
||||
this.text.textContent = this.options.loadingText;
|
||||
this.slider.innerHTML = '❯';
|
||||
this.slider.style.color = '';
|
||||
this.slider.style.cursor = 'grab';
|
||||
this.loadCount = 0;
|
||||
this.initImg();
|
||||
};
|
||||
|
||||
// ── Modal wrapper ──
|
||||
|
||||
function SliderCaptchaModal(options) {
|
||||
var overlay = document.createElement('div');
|
||||
overlay.className = 'aksrt-captcha-modal-overlay';
|
||||
var dialog = document.createElement('div');
|
||||
dialog.className = 'aksrt-captcha-modal-dialog';
|
||||
overlay.appendChild(dialog);
|
||||
document.body.appendChild(overlay);
|
||||
|
||||
var origSuccess = options.onSuccess;
|
||||
options.onSuccess = function (token) {
|
||||
overlay.classList.remove('is-open');
|
||||
setTimeout(function () { overlay.remove(); }, 300);
|
||||
if (typeof origSuccess === 'function') origSuccess(token);
|
||||
};
|
||||
|
||||
if (!options.setSrc) {
|
||||
options.setSrc = function (cb) {
|
||||
cb('https://picsum.photos/' + (options.width || 280) + '/' + (options.height || 170) + '?random=' + Date.now());
|
||||
};
|
||||
}
|
||||
|
||||
var captcha = new AksrtSliderCaptcha(dialog, options);
|
||||
|
||||
requestAnimationFrame(function () { overlay.classList.add('is-open'); });
|
||||
|
||||
overlay.addEventListener('click', function (e) {
|
||||
if (e.target === overlay) {
|
||||
overlay.classList.remove('is-open');
|
||||
setTimeout(function () { overlay.remove(); }, 300);
|
||||
}
|
||||
});
|
||||
|
||||
return { el: overlay, captcha: captcha };
|
||||
}
|
||||
|
||||
// ── Public API ──
|
||||
|
||||
window.AksrtSliderCaptcha = AksrtSliderCaptcha;
|
||||
window.SliderCaptchaModal = SliderCaptchaModal;
|
||||
|
||||
// ── CSS ──
|
||||
|
||||
var STYLE_ID = 'aksrt-slider-captcha-style';
|
||||
|
||||
function injectStyle() {
|
||||
if (document.getElementById(STYLE_ID)) return;
|
||||
var style = document.createElement('style');
|
||||
style.id = STYLE_ID;
|
||||
style.textContent =
|
||||
'.aksrt-captcha__canvas-wrap{position:relative;overflow:hidden;border-radius:8px;background:#f0f0f0;}' +
|
||||
'.aksrt-captcha__canvas-wrap canvas{display:block;}' +
|
||||
'.aksrt-captcha__canvas-wrap canvas:last-child{position:absolute;top:0;left:0;pointer-events:none;}' +
|
||||
'.aksrt-captcha__bar{position:relative;height:40px;border-radius:20px;background:#e8e8e8;margin-top:10px;user-select:none;}' +
|
||||
'.aksrt-captcha__mask{position:absolute;top:0;left:0;height:100%;border-radius:20px;background:linear-gradient(90deg,#1890ff,#36cfc9);width:0;transition:background 0.3s;}' +
|
||||
'.aksrt-captcha__slider{position:absolute;top:0;left:0;width:44px;height:40px;border-radius:20px;background:#fff;box-shadow:0 2px 8px rgba(0,0,0,0.15);cursor:grab;display:flex;align-items:center;justify-content:center;font-size:18px;z-index:2;transition:box-shadow 0.2s;}' +
|
||||
'.aksrt-captcha__text{position:absolute;top:0;left:0;width:100%;height:100%;display:flex;align-items:center;justify-content:center;color:#999;font-size:14px;pointer-events:none;}';
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', injectStyle);
|
||||
} else {
|
||||
injectStyle();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* AKSRT SVG Icon Helper
|
||||
*
|
||||
* Provides utilities for injecting SVG icons from the zib_svgs data array.
|
||||
* Depends on svg-icon.js being loaded first (which defines zib_svgs).
|
||||
*
|
||||
* Usage:
|
||||
* aksrtSvgIcon('like') → returns SVG HTML string
|
||||
* aksrtInjectIcons() → replaces all <i data-svg="name"> in DOM
|
||||
* aksrtInjectIcons(container) → replaces within a specific container
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Get SVG HTML string by icon name.
|
||||
* @param {string} name Icon key (e.g. 'like', 'view', 'comment')
|
||||
* @param {string} [extraClass] Optional CSS class to add to the SVG element
|
||||
* @returns {string} SVG HTML or empty string
|
||||
*/
|
||||
function aksrtSvgIcon(name, extraClass) {
|
||||
if (!window.zib_svgs || !window.zib_svgs[name]) return '';
|
||||
var cls = 'aksrt-svg-icon' + (extraClass ? ' ' + extraClass : '');
|
||||
return '<svg class="' + cls + '" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" aria-hidden="true">' +
|
||||
window.zib_svgs[name] +
|
||||
'</svg>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject SVG icons into the DOM by replacing <i data-svg="name"> elements.
|
||||
* @param {Element} [container=document.body] Container to search within
|
||||
*/
|
||||
function aksrtInjectIcons(container) {
|
||||
container = container || document.body;
|
||||
var elements = container.querySelectorAll('i[data-svg]');
|
||||
elements.forEach(function (el) {
|
||||
var name = el.getAttribute('data-svg');
|
||||
if (!name || !window.zib_svgs || !window.zib_svgs[name]) return;
|
||||
|
||||
var wrapper = document.createElement('span');
|
||||
wrapper.className = el.className.replace(/fa[sbrl]?\s*/g, '').trim();
|
||||
wrapper.setAttribute('data-svg', name);
|
||||
wrapper.innerHTML = aksrtSvgIcon(name);
|
||||
|
||||
// Copy inline styles
|
||||
if (el.style.cssText) {
|
||||
wrapper.style.cssText = el.style.cssText;
|
||||
}
|
||||
|
||||
el.parentNode.replaceChild(wrapper, el);
|
||||
});
|
||||
}
|
||||
|
||||
// ── Default icon styles ──
|
||||
|
||||
var STYLE_ID = 'aksrt-svg-icon-style';
|
||||
|
||||
function injectStyle() {
|
||||
if (document.getElementById(STYLE_ID)) return;
|
||||
var style = document.createElement('style');
|
||||
style.id = STYLE_ID;
|
||||
style.textContent =
|
||||
'.aksrt-svg-icon{display:inline-block;vertical-align:-0.125em;width:1em;height:1em;flex-shrink:0;}' +
|
||||
'[data-svg]{display:inline-flex;align-items:center;justify-content:center;}';
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
|
||||
// ── Public API ──
|
||||
|
||||
window.aksrtSvgIcon = aksrtSvgIcon;
|
||||
window.aksrtInjectIcons = aksrtInjectIcons;
|
||||
|
||||
// ── Auto-init ──
|
||||
|
||||
function init() {
|
||||
injectStyle();
|
||||
// Auto-inject icons on page load
|
||||
aksrtInjectIcons();
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* @Author: Qinver
|
||||
* @Url: zibll.com
|
||||
* @Date: 2021-04-11 21:36:20
|
||||
* @LastEditTime : 2026-04-29 21:18:10
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
var zib_svgs = [];
|
||||
zib_svgs['like'] = '<path d="M914.8609675 357.03388929a127.72961679 127.72961679 0 0 0-103.22061319-41.94810354l-200.07831191 3.29928854 21.68104159-77.29762723c19.79573404-85.78151462-20.03139801-168.02807537-94.26539927-195.36504236a126.07997321 126.07997321 0 0 0-161.90082481 74.46966663L291.0596813 353.73459937h-151.06030332a58.91587557 58.91587557 0 0 0-58.91587559 58.91587557v471.32700047a58.91587557 58.91587557 0 0 0 58.91587559 58.91587557h638.41242277a105.57724866 105.57724866 0 0 0 104.63459419-88.60947662l64.80746217-388.60911182a128.2009447 128.2009447 0 0 0-32.99288961-108.64087325zM275.97721821 872.19430084h-124.19466567V424.4336495h124.19466567z m602.12024323-418.06705027L813.52566185 843.44335425A35.34952507 35.34952507 0 0 1 778.41180075 872.19430084H351.38953789l-4.47760696-445.16835192a109.81919168 109.81919168 0 0 1 6.59857847-37.94182448L443.53396703 144.70107491a55.14525911 55.14525911 0 0 1 70.69905015-32.75722702 92.85141965 92.85141965 0 0 1 50.66765214 111.70449921l-47.13269963 166.84975833 296.93601058-4.71326954a58.68021163 58.68021163 0 0 1 62.4508267 68.34241468z"></path>';
|
||||
zib_svgs['view'] = '<path d="M512 146.285714c248.758857 0 457.142857 156.013714 512 365.714286-54.857143 209.700571-263.314286 365.714286-512 365.714286S54.857143 721.700571 0 512c54.784-209.700571 263.241143-365.714286 512-365.714286z m0 73.142857C312.027429 219.428571 139.849143 335.36 80.749714 498.395429L76.141714 512l4.608 13.677714c57.197714 157.696 220.306286 271.36 412.013715 278.528L512 804.571429c199.972571 0 372.150857-115.931429 431.250286-278.966858L947.785143 512l-4.534857-13.604571c-57.197714-157.769143-220.306286-271.433143-412.013715-278.674286L512 219.428571z"></path><path d="M511.5 689.8c-97.9 0-180.7-82.7-180.7-180.7s82.7-180.7 180.7-180.7 180.7 82.7 180.7 180.7-82.8 180.7-180.7 180.7z m0-279.6c-54.5 0-98.9 44.4-98.9 98.9 0 54.5 44.4 98.9 98.9 98.9 25.9 0 49.9-10.3 67.7-28.9 17.8-18.6 27.5-43.4 27.5-70 0.1-55.4-41.8-98.9-95.2-98.9z"></path>';
|
||||
zib_svgs['comment'] = '<path d="M176 193c-17.673 0-32 14.327-32 32v481c0 17.673 14.327 32 32 32h27c51.915 0 94 42.085 94 94v45.5a1.94 1.94 0 0 0 3.293 1.388l117.045-114.176A94 94 0 0 1 482.976 738H848c17.673 0 32-14.327 32-32V225c0-17.673-14.327-32-32-32H176z m0-80h672c61.856 0 112 50.144 112 112v481c0 61.856-50.144 112-112 112H482.976a14 14 0 0 0-9.776 3.978L356.156 936.154c-32.394 31.6-84.271 30.956-115.87-1.437A81.94 81.94 0 0 1 217 877.5V832c0-7.732-6.268-14-14-14h-27c-61.856 0-112-50.144-112-112V225c0-61.856 50.144-112 112-112z m336 438c-35.346 0-64-28.654-64-64 0-35.346 28.654-64 64-64 35.346 0 64 28.654 64 64 0 35.346-28.654 64-64 64z m228 0c-35.346 0-64-28.654-64-64 0-35.346 28.654-64 64-64 35.346 0 64 28.654 64 64 0 35.346-28.654 64-64 64z m-456 0c-35.346 0-64-28.654-64-64 0-35.346 28.654-64 64-64 35.346 0 64 28.654 64 64 0 35.346-28.654 64-64 64z" p-id="24020"></path>';
|
||||
zib_svgs['time'] = '<path d="M528.384 76.223488c-236.78976 0-428.736512 191.945728-428.736512 428.736512S291.59424 933.695488 528.384 933.695488s428.736512-191.945728 428.736512-428.736512S765.17376 76.223488 528.384 76.223488zM528.384 838.42048c-184.152064 0-333.461504-149.331968-333.461504-333.461504 0-184.152064 149.30944-333.461504 333.461504-333.461504 184.128512 0 333.461504 149.30944 333.461504 333.461504C861.84448 689.088512 712.512512 838.42048 528.384 838.42048z" p-id="2512"></path><path d="M576.02048 314.409984c26.331136 0 47.637504 21.32992 47.637504 47.637504l0 190.548992c0 26.331136-21.307392 47.637504-47.637504 47.637504-26.30656 0-47.637504-21.307392-47.637504-47.637504L528.382976 362.047488C528.384 335.739904 549.71392 314.409984 576.02048 314.409984z" p-id="2513"></path><path d="M385.471488 504.96 576.02048 504.96c26.331136 0 47.637504 21.32992 47.637504 47.637504 0 26.331136-21.307392 47.637504-47.637504 47.637504L385.471488 600.235008c-26.307584 0-47.637504-21.307392-47.637504-47.637504C337.833984 526.28992 359.163904 504.96 385.471488 504.96z"></path>';
|
||||
zib_svgs['search'] = '<path d="M 996.26316,943.61526 830.22989,765.68709 c 67.40454,-81.77757 104.08054,-185.36249 104.08054,-291.42553 0,-252.76704 -206.1786,-459.441261 -459.93688,-459.441261 -253.75828,0 -459.441259,206.674221 -459.441259,459.936881 0,253.75828 192.561269,460.98509 446.473049,460.27349 153.23305,-0.42945 134.00728,-52.00124 131.45592,-67.11493 -9.87159,-23.79618 -37.79763,-19.27093 -52.07042,-17.39744 -41.1251,11.26508 -27.6041,12.83513 -86.88072,13.78294 C 250.48388,867.55395 91.258023,686.88324 91.258024,475.2528 91.258025,263.62236 262.74312,91.641654 474.37355,91.641654 c 211.63044,0 383.61115,171.980706 383.61115,383.611146 0,99.12433 -38.16286,194.77931 -107.05427,266.14882 -6.93871,7.43433 -10.40805,16.85114 -10.90368,27.2592 0,10.40805 4.4606,19.82486 11.3993,26.76356 0.49562,0.49563 188.83184,201.71802 188.83184,201.71802 14.37304,14.8686 38.16287,15.8599 53.52713,1.4869 7.43428,-6.93875 11.89488,-16.35555 12.39058,-26.26799 0.9912,-11.39929 -2.9738,-20.81611 -9.91244,-28.74605 z" style="stroke:currentColor;stroke-width:20;"></path>';
|
||||
zib_svgs['tags'] = '<path d="M541.2 632.8c-91.1 0-171.8 41.5-223.3 105.5l231.8 231.8c28.1 28.1 73.8 28.1 101.9 0l155.7-155.7c-37.9-105.6-142.6-181.6-266.1-181.6z" fill="#4EEAAB"></path><path d="M970.2 549.8l-496-496a71.91 71.91 0 0 0-50.9-21.1c-2.4 0-4.9 0.1-7.3 0.4L126.9 62.6C92.9 66 66 92.9 62.6 126.9L33.1 416a71.99 71.99 0 0 0 20.7 58.2l495.9 495.9c14.1 14.1 32.5 21.1 50.9 21.1s36.9-7 50.9-21.1L970 651.6c28.3-28.1 28.3-73.7 0.2-101.8zM600.7 912.5l-491-491 28.8-283 283-28.8 491 491-311.8 311.8z"></path><path d="M310.8 210.4c-49.5 0-89.6 40.1-89.6 89.6s40.1 89.6 89.6 89.6 89.6-40.1 89.6-89.6-40.1-89.6-89.6-89.6z m0 102.4c-7.1 0-12.8-5.7-12.8-12.8 0-7.1 5.7-12.8 12.8-12.8 7.1 0 12.8 5.7 12.8 12.8 0 7.1-5.7 12.8-12.8 12.8z"></path>';
|
||||
zib_svgs['right'] = '<path d="M294.4 908.8 684.8 512 294.4 115.2c-25.6-25.6-25.6-70.4 0-96 25.6-25.6 70.4-25.6 96 0L832 460.8c12.8 12.8 19.2 32 19.2 51.2S844.8 544 832 563.2l-441.6 441.6c-25.6 25.6-70.4 25.6-96 0C262.4 979.2 262.4 934.4 294.4 908.8z" p-id="1915" data-spm-anchor-id="a313x.7781069.0.i2"></path>';
|
||||
zib_svgs['left'] = '<path d="M704 908.8 307.2 512 704 115.2c25.6-25.6 25.6-70.4 0-96-25.6-25.6-70.4-25.6-96 0L166.4 460.8C147.2 480 140.8 492.8 140.8 512s6.4 32 19.2 51.2l441.6 441.6c25.6 25.6 70.4 25.6 96 0C729.6 979.2 729.6 934.4 704 908.8z" p-id="2034" data-spm-anchor-id="a313x.7781069.0.i4"></path>';
|
||||
zib_svgs['reply'] = '<path d="M415.937331 320 415.937331 96 20.001331 438.176C-6.718669 461.28-6.622669 498.784 20.033331 521.824L415.937331 864 415.937331 640C639.937331 640 847.937331 688 1023.937331 928 943.937331 480 607.937331 320 415.937331 320" p-id="4051" data-spm-anchor-id="a313x.7781069.0.i0"></path>';
|
||||
zib_svgs['circle'] = '<path d="M908.548 205.661L582.454 20.479c-21.959-12.5-46.417-18.694-70.876-18.694-24.458 0-48.917 6.194-70.875 18.693L114.591 205.661c-44.496 25.298-71.976 72.312-71.976 123.281v367.902c0 50.932 27.48 97.982 71.976 123.242l326.112 185.223C462.661 1017.77 487.12 1024 511.578 1024c24.459 0 48.917-6.23 70.876-18.691l326.094-185.223c44.514-25.26 71.975-72.311 71.975-123.242V328.942c-0.001-50.969-27.461-97.983-71.975-123.281zM548.257 945.83a74.699 74.699 0 0 1-36.679 9.664 74.6 74.6 0 0 1-36.679-9.664L235.427 809.826c15.597-8.58 31.623-14.551 45.26-15.709 16.53-1.418 39.645-7.162 64.123-13.246 9.179-2.313 18.414-4.588 27.145-6.604 51.547-11.902 68.749-22.723 77.199-29.85a34.271 34.271 0 0 0 12.202-26.865c-0.504-22.5-8.209-44.402-22.425-63.619-2.258-3.955-5.317-7.424-8.993-10.223-46.827-35.635-74.793-97.236-74.793-164.734 0-106.64 70.503-193.393 157.162-193.393 86.64 0 157.123 86.64 157.123 193.204 0 67.35-27.966 128.803-74.793 164.438-2.238 1.68-4.328 3.768-6.101 5.969-16.306 20.41-24.794 42.76-25.297 66.379a34.32 34.32 0 0 0 12.014 26.717c7.594 6.455 23.173 15.484 76.66 27.908 32.237 7.539 69.475 14.031 90.52 15.822 17.816 1.566 37.76 8.357 55.503 17.982L548.257 945.83z m363.35-248.986c0 26.268-14.273 50.744-37.257 63.805l-9.981 5.672c-0.337-0.299-0.466-0.709-0.803-0.971-32.312-26.342-75.37-44.104-115.184-47.537-17.574-1.529-52.275-7.686-80.745-14.326-11.978-2.762-21.249-5.225-28.282-7.24 0.355-0.559 0.728-1.117 1.138-1.715 61.361-48.844 97.87-129.027 97.87-215.743 0-144.324-101.415-261.709-226.057-261.709-124.68 0-226.077 117.46-226.077 261.898 0 86.49 36.193 166.525 97.087 215.406a52.32 52.32 0 0 1 3.283 5c-7.239 2.313-17.071 5.111-30.242 8.133-9.123 2.127-18.73 4.516-28.264 6.902-19.832 4.926-42.293 10.484-53.32 11.455-34.477 2.947-73.281 20.297-105.8 46.193l-20.186-11.418c-22.965-13.061-37.256-37.537-37.256-63.805V328.942c0-26.306 14.291-50.745 37.256-63.804l326.112-185.22a74.608 74.608 0 0 1 36.679-9.664 74.701 74.701 0 0 1 36.679 9.664l326.094 185.22c22.983 13.06 37.257 37.499 37.257 63.804v367.902z" p-id="6675"></path>';
|
||||
zib_svgs['add'] = '<path d="M861.541 469.516h-307.058v-307.058c0-23.464-19.020-42.484-42.484-42.484-23.463 0-42.484 19.020-42.484 42.484v307.058h-307.058c-23.464 0-42.484 19.020-42.484 42.484 0 23.463 19.020 42.484 42.484 42.484h307.058v307.058c0 23.463 19.020 42.484 42.484 42.484 23.463 0 42.484-19.021 42.484-42.484v-307.058h307.058c23.463 0 42.484-19.020 42.484-42.484-0.001-23.463-19.022-42.484-42.485-42.484z"></path>';
|
||||
zib_svgs['minus'] = '<path d="M560 560h-384a48 48 0 0 1 0-96h672a48 48 0 1 1 0 96h-288z"></path>';
|
||||
zib_svgs['add-ring'] = '<path d="M512 1024C229.229714 1024 0 794.770286 0 512S229.229714 0 512 0s512 229.229714 512 512-229.229714 512-512 512z m0-928C282.258286 96 96 282.258286 96 512S282.258286 928 512 928 928 741.741714 928 512 741.741714 96 512 96z m208.018286 463.981714h-160v160.036572a48.018286 48.018286 0 0 1-96.036572 0v-160.036572H303.981714a47.981714 47.981714 0 0 1 0-95.963428h160V304.018286a48.018286 48.018286 0 0 1 96.036572 0v160h160a47.981714 47.981714 0 0 1 0 95.963428z"></path>';
|
||||
zib_svgs['post'] = '<path d="M260.737 62c-89.263 0-157.827 78.218-157.827 168.382v573.463c0 90.246 67.909 158.154 158.073 158.154h491.809c90 0 168.3-68.237 168.3-158.727v-490.746l-250.527-250.527h-409.827zM260.982 880.182c-45 0-76.254-31.337-76.254-76.337v-573.463c0-44.754 31.663-86.563 76.009-86.563h333.082v168.054c0 46.554 31.827 77.4 77.4 77.4h168.054v414c0 45.327-41.646 76.909-86.482 76.909h-491.809zM716.546 716.546c22.593 0 40.909-18.316 40.909-40.909 0-22.593-18.316-40.909-40.909-40.909h-409.091c-22.593 0-40.909 18.316-40.909 40.909 0 22.593 18.316 40.909 40.909 40.909h409.091zM716.546 552.909c22.593 0 40.909-18.316 40.909-40.909s-18.316-40.909-40.909-40.909h-409.091c-22.593 0-40.909 18.316-40.909 40.909 0 22.593 18.316 40.909 40.909 40.909h409.091zM471.091 389.273c22.593 0 40.909-18.316 40.909-40.909s-18.316-40.909-40.909-40.909h-163.637c-22.593 0-40.909 18.316-40.909 40.909s18.316 40.909 40.909 40.909h163.637z"></path>';
|
||||
zib_svgs['favorite'] = '<g style="transform: scale(1.05);transform-origin: center;-webkit-transform-origin: center;-webkit-transform: scale(1.05);"><path d="M950.4 508c43.2-41.6 44-110.4 2.4-153.6-16.8-16.8-38.4-28-62.4-32l-176.8-25.6c-11.2-1.6-21.6-8.8-26.4-19.2L608 116.8c-26.4-53.6-92-76-145.6-49.6-21.6 10.4-38.4 28-49.6 49.6l-79.2 160.8c-4.8 10.4-15.2 17.6-26.4 19.2l-176.8 25.6c-59.2 8.8-100.8 64-92 123.2 3.2 24 14.4 45.6 32 62.4l128 124.8c8 8 12 20 10.4 31.2l-30.4 176.8c-10.4 59.2 29.6 115.2 88 125.6 24 4 48 0 69.6-11.2L492.8 872c10.4-5.6 22.4-5.6 32.8 0l158.4 83.2c52.8 28 119.2 7.2 146.4-45.6 11.2-20.8 15.2-45.6 11.2-68.8L812 664c-1.6-11.2 1.6-23.2 10.4-31.2l128-124.8z m-179.2 72c-25.6 24.8-37.6 60.8-31.2 96l30.4 176.8c3.2 19.2-9.6 37.6-28.8 40.8-8 1.6-15.2 0-22.4-3.2L560 807.2c-32-16.8-69.6-16.8-100.8 0l-158.4 83.2c-17.6 8.8-38.4 2.4-48-15.2-4-7.2-4.8-14.4-3.2-22.4L280 676c6.4-35.2-5.6-71.2-31.2-96L120 455.2c-14.4-13.6-14.4-36-0.8-50.4 5.6-5.6 12.8-9.6 20-10.4l176.8-25.6c35.2-4.8 65.6-27.2 81.6-59.2l79.2-160.8c8.8-17.6 29.6-24.8 47.2-16 7.2 3.2 12.8 8.8 16 16l79.2 160.8c16 32 46.4 54.4 81.6 59.2l176.8 25.6c19.2 3.2 32.8 20.8 29.6 40-0.8 8-4.8 15.2-10.4 20L771.2 580z"></path><path d="M355.2 646.4c0 20 16 36 36 36h236.8c20 0 36-16 36-36s-16-36-36-36H391.2c-20 0-36 16-36 36z" style="opacity:.6;"></path></g>';
|
||||
zib_svgs['menu'] = '<path d="M230.60033 921.5c-28.3 0.3-51.4-22.4-51.7-50.6-0.3-28.3 22.4-51.4 50.6-51.7H972.80033c28.3 0.3 50.9 23.5 50.6 51.7-0.3 27.8-22.8 50.3-50.6 50.6H230.60033zM51.40033 563.2C23.10033 563.2 0.20033 540.3 0.20033 512c0-28.3 22.9-51.2 51.2-51.2h921.4c28.3 0 51.2 22.9 51.2 51.2 0 28.3-22.9 51.2-51.2 51.2H51.40033z m0-358.3c-28.3 0.1-51.3-22.7-51.4-51-0.1-28.3 22.7-51.3 51-51.4h921.9c28.3 0.1 51.1 23.1 51 51.4-0.1 28.1-22.9 50.8-51 51H51.40033z"></path>';
|
||||
zib_svgs['d-qq'] = '<path d="M889.6 782.933c-12.8 2.134-42.667-25.6-61.867-76.8-14.933 57.6-42.666 104.534-81.066 140.8 46.933 12.8 76.8 34.134 76.8 61.867 0 40.533-66.134 72.533-147.2 72.533-61.867 0-113.067-17.066-136.534-44.8H512c-10.667 0-21.333 0-32-2.133-21.333 27.733-74.667 44.8-136.533 44.8-81.067 0-147.2-32-147.2-72.533 0-27.734 34.133-51.2 81.066-64C241.067 806.4 211.2 759.467 196.267 704c-21.334 51.2-49.067 78.933-61.867 78.933-17.067-2.133-34.133-53.333-25.6-134.4 6.4-51.2 34.133-119.466 64-138.666v-19.2c4.267-49.067 12.8-93.867 34.133-96-2.133-17.067-4.266-36.267-4.266-53.334C204.8 177.067 347.733 42.667 512 42.667s307.2 134.4 307.2 298.666c0 19.2-2.133 36.267-4.267 53.334 17.067 0 32 44.8 36.267 96v19.2c29.867 25.6 57.6 87.466 61.867 136.533 12.8 83.2-4.267 134.4-23.467 136.533z"></path>';
|
||||
zib_svgs['d-weibo'] = '<path d="M996.243 460.502c0 0.03 0 0.091 0 0.152-6.479 19.983-27.916 30.943-47.838 24.465-19.983-6.48-30.944-27.917-24.464-47.959l-0.062-0.03c19.862-61.524 7.267-131.707-38.996-183.179-46.325-51.472-114.632-71.152-177.729-57.709-20.529 4.391-40.755-8.75-45.114-29.308-4.359-20.558 8.721-40.814 29.248-45.205l0 0c88.713-18.923 184.874 8.69 250.031 81.144C1006.477 275.265 1024.037 373.939 996.243 460.502zM733.072 318.107l0-0.03c-17.621 3.845-35.001-7.479-38.756-25.16-3.814-17.712 7.509-35.182 25.131-38.937 43.236-9.235 90.105 4.178 121.775 39.451 31.791 35.304 40.269 83.354 26.705 125.531-5.571 17.258-23.98 26.644-41.177 21.133-17.198-5.571-26.585-24.101-21.014-41.298l-0.061 0c6.661-20.648 2.482-44.145-13.02-61.403C777.156 320.166 754.205 313.657 733.072 318.107zM524.853 378.239c100.976-42.419 189.143-44.932 221.359 1.241 17.138 24.585 15.501 59.071-0.303 99.038-7.327 18.408 2.24 21.285 16.229 25.493C818.999 521.693 882.4 564.506 882.4 639.896c0 124.865-179.545 282.065-449.348 282.065-205.825 0-416.224-100.036-416.224-264.564 0-86.049 54.348-185.51 147.936-279.4 124.955-125.288 270.681-182.362 325.483-127.348 24.191 24.192 26.522 66.186 10.991 116.266C493.123 392.136 524.853 378.178 524.853 378.239zM395.024 471.373c-164.225 16.289-288.787 117.173-278.099 225.263 10.658 108.151 152.447 182.634 316.672 166.346 164.256-16.29 288.756-117.113 278.099-225.326C701.037 529.564 559.279 455.083 395.024 471.373zM327.384 816.535C248.42 790.98 214.994 712.804 249.57 642.318c33.941-69.033 122.291-108.091 200.437-87.684 80.902 20.951 122.17 97.493 89.108 171.794C505.597 802.486 409.194 842.998 327.384 816.535zM371.982 668.479c-25.433-10.658-58.315 0.303-73.997 25.008-15.896 24.768-8.418 54.319 16.834 65.824 25.614 11.747 59.616 0.605 75.512-24.828C405.923 708.808 397.718 679.5 371.982 668.479zM434.687 642.441c-9.779-3.877-21.981 0.785-27.703 10.414-5.542 9.689-2.482 20.71 7.295 24.768 9.962 4.117 22.648-0.666 28.4-10.477C448.161 657.216 444.588 646.074 434.687 642.441z" p-id="3731" data-spm-anchor-id="a313x.7781069.0.i4"></path>';
|
||||
zib_svgs['d-wechat'] = '<path d="M670.564352 367.904768c10.274816 0 20.453376 0.751616 30.539776 1.878016-27.439104-127.772672-164.050944-222.703616-319.975424-222.703616-174.32576 0-317.126656 118.816768-317.126656 269.703168 0 87.095296 47.511552 158.611456 126.900224 214.081536L159.1808 726.26176l110.860288-55.59296c39.66976 7.856128 71.503872 15.9232 111.087616 15.9232 9.955328 0 19.820544-0.49152 29.607936-1.255424-6.201344-21.202944-9.787392-43.411456-9.787392-66.445312-0.002048-138.555392 118.976512-250.986496 269.615104-250.986496z m-170.512384-85.981184c23.877632 0 39.694336 15.712256 39.694336 39.571456 0 23.769088-15.816704 39.696384-39.694336 39.696384-23.775232 0-47.622144-15.925248-47.622144-39.696384 0-23.86944 23.851008-39.571456 47.622144-39.571456z m-221.949952 79.265792c-23.764992 0-47.753216-15.925248-47.753216-39.70048 0-23.863296 23.988224-39.56736 47.753216-39.56736 23.771136 0 39.58784 15.702016 39.58784 39.56736 0 23.775232-15.816704 39.70048-39.58784 39.70048z" p-id="2048"></path><path d="M960 615.069696c0-126.785536-126.871552-230.127616-269.365248-230.127616-150.888448 0-269.727744 103.340032-269.727744 230.127616 0 127.008768 118.837248 230.135808 269.727744 230.135808 31.578112 0 63.4368-7.964672 95.15008-15.919104l86.984704 47.634432-23.846912-79.251456c63.65184-47.755264 111.077376-111.079424 111.077376-182.59968z m-356.818944-39.677952c-15.792128 0-31.721472-15.70816-31.721472-31.735808 0-15.798272 15.929344-31.709184 31.721472-31.709184 23.988224 0 39.696384 15.910912 39.696384 31.709184 0 16.027648-15.70816 31.735808-39.696384 31.735808z m174.434304 0c-15.67744 0-31.496192-15.70816-31.496192-31.735808 0-15.798272 15.818752-31.709184 31.496192-31.709184 23.771136 0 39.696384 15.910912 39.696384 31.709184 0 16.027648-15.925248 31.735808-39.696384 31.735808z"></path>';
|
||||
zib_svgs['d-email'] = '<path d="M512.012 630.535L927.56 284.31c-2.251-0.41-4.274-1.348-6.61-1.348H103.074c-2.288 0-4.323 0.927-6.574 1.348l415.512 346.226z m446.122-310.391c0-3.9-1.072-7.513-2.252-11.066L661.313 554.602l295.014 295.075c0.759-2.974 1.807-5.84 1.807-9.055V320.144z m-889.98-11.102c-1.144 3.577-2.288 7.14-2.288 11.102V840.61c0 3.25 1.12 6.105 1.855 9.079L362.83 554.59 68.154 309.042z" p-id="2793"></path><path d="M632.583 578.493l-108.698 90.539c-3.408 2.902-7.622 4.299-11.873 4.299-4.214 0-8.453-1.397-11.897-4.3l-108.601-90.49L94.079 875.963c2.926 0.77 5.828 1.842 8.995 1.842h817.888c3.227 0 6.129-1.06 9.115-1.842l-297.494-297.47z"></path>';
|
||||
zib_svgs['user'] = '<path d="M603.136 505.856c-7.168 2.048-13.312 5.12-19.456 7.168-20.48 8.192-38.912 14.336-70.656 14.336-31.744 0-49.152-7.168-70.656-14.336-6.144-2.048-13.312-5.12-20.48-7.168-21.504-7.168-45.056 4.096-52.224 25.6-6.144 22.528 5.12 45.056 26.624 52.224 6.144 2.048 11.264 4.096 16.384 6.144 23.552 9.216 53.248 20.48 99.328 20.48 46.08 0 75.776-11.264 99.328-20.48 5.12-2.048 11.264-4.096 16.384-6.144 21.504-7.168 32.768-30.72 25.6-52.224-6.144-20.48-28.672-32.768-50.176-25.6z"></path><path d="M921.6 418.816c0-226.304-183.296-409.6-409.6-409.6s-409.6 183.296-409.6 409.6c0 174.08 109.568 322.56 263.168 381.952-48.128 40.96-78.848 102.4-78.848 171.008 0 22.528 18.432 40.96 40.96 40.96s40.96-18.432 40.96-40.96c0-78.848 64.512-143.36 143.36-143.36s143.36 64.512 143.36 143.36c0 22.528 18.432 40.96 40.96 40.96s40.96-18.432 40.96-40.96c0-68.608-30.72-129.024-78.848-171.008 153.6-59.392 263.168-207.872 263.168-381.952z m-409.6 327.68c-180.224 0-327.68-147.456-327.68-327.68s147.456-327.68 327.68-327.68 327.68 147.456 327.68 327.68-147.456 327.68-327.68 327.68z"></path>';
|
||||
zib_svgs['theme'] = '<path d="M512 33.408c288.832 0 480 227.008 480 428.16 0 126.528-84.864 225.6-186.048 264.576-23.36 8.96-52.224 14.464-86.016 17.28-31.68 2.56-63.104 2.752-99.392 1.472l-20.672-0.64c-6.4 0-21.248 16.256-21.248 42.88 0 10.496 0.384 11.456 6.08 17.472l3.392 3.584c18.176 19.648 26.496 41.28 26.496 79.68 0 45.184-23.232 76.16-59.328 91.712-19.52 8.384-38.4 11.072-52.736 10.88-291.776 0-470.528-237.12-470.528-480C32 269.568 215.936 33.472 512 33.472z m87.872 646.784c3.2 0 29.76 1.024 23.04 0.768 33.92 1.152 63.104 1.024 91.712-1.28 28.224-2.432 51.584-6.784 68.288-13.248 78.528-30.272 145.088-107.904 145.088-204.8 0-168.064-165.184-364.224-416-364.224-256.704 0-416 204.416-416 413.12 0 210.752 154.688 416 406.848 416 6.464 0 17.216-1.472 27.008-5.76 13.952-5.952 20.736-14.976 20.736-32.896 0-22.4-2.304-28.48-9.472-36.224l-3.008-3.2c-16.192-17.152-23.488-33.28-23.488-61.376 0-60.672 42.112-106.88 85.248-106.88zM238.912 512a77.76 77.76 0 1 1-0.064-155.52 77.76 77.76 0 0 1 0 155.52z m146.688-192.512a77.76 77.76 0 1 1-0.064-155.52 77.76 77.76 0 0 1 0.064 155.52z m249.472 0a77.824 77.824 0 1 1 0.064-155.648 77.824 77.824 0 0 1 0 155.648zM783.232 512a77.824 77.824 0 1 1 0-155.648 77.824 77.824 0 0 1 0 155.648z"></path>';
|
||||
zib_svgs['signout'] = '<path d="M630.093 487.772L450.318 314.694c-14.382-13.851-35.955-13.851-50.336 0-14.382 13.842-14.382 34.614 0 48.465l118.647 114.228H173.461c-21.573 0-35.955 13.842-35.955 34.614s14.382 34.614 35.955 34.614h345.168L399.99 660.843c-14.382 13.851-14.382 34.623 0 48.465 7.192 6.93 14.382 10.386 25.164 10.386 10.792 0 17.982-3.465 25.173-10.386l179.775-176.535s0-3.465 3.6-3.465c10.782-10.386 10.782-31.149-3.6-41.535z"></path><path d="M170.99 269.693c21.573 0 35.955-13.851 35.955-34.614v-69.237c0-20.763 14.382-34.614 35.955-34.614h611.235c21.573 0 35.955 13.851 35.955 34.614v692.317c0 20.763-14.382 34.614-35.955 34.614H242.9c-21.573 0-35.955-13.851-35.955-34.614v-69.237c0-20.764-14.382-34.614-35.955-34.614s-35.955 13.851-35.955 34.614v69.237c0 58.842 46.736 103.842 107.865 103.842h611.235c61.119 0 107.865-45 107.865-103.842V165.842C962 107 915.253 62 854.135 62H242.9c-61.128 0-107.865 45-107.865 103.842v69.237c0 20.764 14.382 34.614 35.955 34.614z"></path>';
|
||||
zib_svgs['set'] = '<path d="M973.4144 422.4c-6.9632-36.352-26.112-58.88-61.44-71.5776-60.928-21.8112-81.92-60.1088-70.4512-125.2352 6.656-37.5808-2.1504-68.1984-31.3344-93.9008-39.5264-35.0208-82.944-62.976-131.8912-83.0464-39.1168-16.0768-72.3968-11.776-104.0384 17.7152-41.3696 38.6048-83.8656 43.1104-124.1088 6.5536-47.0016-42.5984-92.4672-41.5744-142.5408-10.9568-28.4672 17.408-56.7296 35.1232-84.8896 52.9408-44.032 27.7504-60.5184 65.4336-52.4288 118.4768 9.6256 63.2832-8.192 90.624-66.56 115.9168-32.8704 14.2336-57.0368 36.2496-63.3856 71.7824-10.1376 55.7056-12.6976 111.8208-3.072 168.7552 7.5776 44.4416 26.5216 73.8304 71.68 88.064 51.2 16.1792 75.0592 63.7952 64.6144 117.0432-1.9456 9.9328-3.3792 19.968-3.072 18.2272-2.1504 36.864 8.4992 57.1392 25.8048 73.8304 45.568 44.032 98.5088 76.0832 158.6176 96.5632 29.184 9.9328 54.4768 1.9456 77.7216-15.1552 73.728-54.4768 82.3296-54.5792 158.4128 2.56 25.1904 18.944 51.4048 24.9856 81.408 11.8784 52.224-22.8352 100.7616-51.712 144.1792-88.6784 26.4192-22.528 36.7616-50.4832 30.4128-85.504-13.2096-72.192 2.6624-102.7072 67.4816-131.1744 34.7136-15.2576 56.2176-40.0384 62.2592-77.6192 9.5232-59.2896 7.9872-118.3744-3.3792-177.4592zM850.7392 620.7488c-69.8368 33.6896-95.1296 100.352-85.1968 175.7184 3.7888 28.672-4.3008 43.52-25.8048 56.7296-13.6192 8.3968-27.2384 16.6912-40.2432 26.0096-33.28 23.8592-61.1328 30.1056-99.1232-0.512-56.7296-45.7728-137.5232-40.8576-193.024 7.0656-23.7568 20.48-42.3936 19.7632-65.6384 6.5536-17.6128-10.0352-35.1232-20.3776-52.3264-31.1296-28.7744-17.8176-43.7248-36.864-35.7376-77.4144 13.6192-69.12-37.6832-149.8112-106.9056-176.9472-25.1904-9.8304-33.5872-24.7808-34.816-47.616-1.3312-24.6784-1.7408-49.3568-1.1264-74.0352 0.7168-33.4848 10.4448-56.5248 46.6944-73.3184 68.608-31.5392 100.4544-92.672 91.8528-167.6288-4.608-40.3456 9.4208-62.7712 41.6768-80.2816 14.0288-7.5776 27.7504-15.872 40.96-24.7808 28.0576-18.944 49.7664-20.2752 79.6672 4.7104 58.88 49.152 143.36 46.1824 200.192-4.5056 22.528-20.0704 39.0144-18.0224 60.5184-5.632 13.824 7.9872 28.16 15.0528 41.6768 23.552 32.8704 20.8896 53.3504 42.1888 46.7968 90.3168-9.0112 65.8432 20.5824 129.7408 81.1008 156.4672 59.0848 26.112 65.024 65.4336 61.3376 119.6032 5.9392 42.8032-4.5056 73.8304-52.5312 97.0752z"></path><path d="M507.1872 321.024c-100.2496-1.4336-187.5968 87.4496-187.392 190.7712 0.2048 103.6288 87.6544 192.3072 187.6992 190.3616 98.9184-1.8432 184.1152-90.112 184.0128-190.6688 0-99.9424-86.2208-189.0304-184.32-190.464z m-3.2768 299.008c-58.6752-1.2288-107.2128-52.3264-105.2672-110.8992 2.048-59.2896 51.3024-105.472 111.104-104.0384 56.6272 1.4336 104.0384 50.688 103.3216 107.4176-0.7168 58.368-52.0192 108.7488-109.1584 107.52z"></path>';
|
||||
zib_svgs['signup'] = '<path d="M722.6 645.295c17.497-26.999 9.793-63.072-17.206-80.567a433.17 433.17 0 0 0-69.045-36.377c69.66-51.387 114.937-134.006 114.937-227.013 0-155.467-126.483-281.951-281.951-281.951S187.384 145.87 187.384 301.338c0 92.95 45.223 175.527 114.811 226.919-51.763 21.557-99.309 53.261-140.153 94.103-82.08 82.08-127.284 191.213-127.284 307.292 0 32.174 26.082 58.254 58.254 58.254s58.254-26.08 58.254-58.254c0-175.385 142.685-318.068 318.068-318.068 61.579 0 121.298 17.606 172.699 50.915 27.002 17.498 63.074 9.793 80.567-17.206zM469.334 135.897c91.225 0 165.442 74.218 165.442 165.442s-74.218 165.442-165.442 165.442c-91.225 0-165.442-74.217-165.442-165.442s74.218-165.442 165.442-165.442zM926.63 743.197h-66.992v-66.992c0-32.174-26.08-58.254-58.254-58.254s-58.254 26.08-58.254 58.254v66.992h-66.992c-32.174 0-58.254 26.08-58.254 58.254s26.08 58.254 58.254 58.254h66.992v66.992c0 32.174 26.08 58.254 58.254 58.254s58.254-26.08 58.254-58.254v-66.992h66.992c32.174 0 58.254-26.08 58.254-58.254s-26.08-58.254-58.254-58.254z"></path>';
|
||||
zib_svgs['user_rp'] = '<path d="M523.56129 558.245161c-45.419355 0-82.580645 37.16129-82.580645 82.580645 0 33.032258 18.993548 61.109677 47.070968 74.322581v90.83871c0 19.819355 15.690323 35.509677 35.509677 35.509677s35.509677-15.690323 35.509678-35.509677v-90.83871c28.077419-13.212903 47.070968-41.290323 47.070967-74.322581-0.825806-45.419355-37.16129-82.580645-82.580645-82.580645z m341.058065-164.335484H157.729032c-38.812903 0-71.019355 31.380645-71.019355 71.019355v471.535484c0 38.812903 31.380645 71.019355 71.019355 71.019355h706.890323c38.812903 0 71.019355-31.380645 71.019355-71.019355V464.103226c0-38.812903-32.206452-70.193548-71.019355-70.193549z m0 494.658065c0 38.812903-8.258065 47.070968-47.070968 47.070968H204.8c-38.812903 0-47.070968-8.258065-47.070968-47.070968V511.174194c0-38.812903 8.258065-47.070968 47.070968-47.070968H817.548387c38.812903 0 47.070968 8.258065 47.070968 47.070968v377.393548zM177.548387 358.4c19.819355 0 35.509677-15.690323 36.335484-35.509677C246.090323 187.458065 366.658065 87.535484 512 87.535484c113.135484 0 211.406452 61.935484 264.258065 152.774193 5.780645 12.387097 18.167742 21.470968 32.206451 21.470968 19.819355 0 35.509677-15.690323 35.509678-35.509677 0-7.432258-2.477419-14.864516-6.606452-20.645162C772.129032 92.490323 650.735484 16.516129 511.174194 16.516129 328.670968 16.516129 177.548387 142.03871 142.03871 313.806452c0 0.825806 0 1.651613-0.825807 2.477419 0 0.825806 0 1.651613-0.825806 2.477419v3.303226c0.825806 19.819355 17.341935 36.335484 37.16129 36.335484z m0 0"></path>';
|
||||
zib_svgs['close'] = '<path d="M573.44 512.128l237.888 237.696a43.328 43.328 0 0 1 0 59.712 43.392 43.392 0 0 1-59.712 0L513.728 571.84 265.856 819.712a44.672 44.672 0 0 1-61.568 0 44.672 44.672 0 0 1 0-61.568L452.16 510.272 214.208 272.448a43.328 43.328 0 0 1 0-59.648 43.392 43.392 0 0 1 59.712 0l237.952 237.76 246.272-246.272a44.672 44.672 0 0 1 61.568 0 44.672 44.672 0 0 1 0 61.568L573.44 512.128z" p-id="35424" data-spm-anchor-id="a313x.7781069.0.i48"></path>';
|
||||
zib_svgs['pan_baidu'] = '<path d="M1008.45542717 705.56838367c0 133.69628798-108.3823688 242.0786568-242.0786568 242.0786568-58.29538853 0-111.75541773-20.63131534-153.53741716-54.95832779-15.23567982-11.3243619-25.10886432-29.45747728-25.10886432-49.89927221 0-34.31795067 27.81988637-62.13783703 62.13783703-62.13783705 15.29626421 0 29.2925531 5.53725801 40.11877667 14.70336569l0.08699297-0.09709037c20.55959792 17.50992466 47.18074185 28.11348765 76.30267481 28.11348765 65.06064555 0 117.80298272-52.74233717 117.80298272-117.80298272s-52.74233717-117.80298272-117.80298272-117.80298271c-31.58103786 0-60.23383015 12.45061019-81.38244299 32.68476118l-3.72878802 3.72878804c-1.17906546 1.23265934-2.33767721 2.48499566-3.46263098 3.76762419l-144.2234732 144.2232143c-0.02278387-0.07974355-0.04142523-0.16078165-0.0642091-0.24078412l-100.65837677 100.65863566c-44.08912555 46.24349614-106.29609093 75.05914134-175.23361968 75.05914134-133.69628798 0-242.0786568-108.3823688-242.0786568-242.07865678 0-133.41123067 107.92151318-241.61236411 241.22452045-242.07321974a259.95985503 259.95985503 0 0 1-2.2527555-34.18124742c0-142.27571092 115.33740512-257.61311605 257.61311605-257.61311606s257.61311605 115.33740512 257.61311604 257.61311606c0 11.58948333-0.77025027 22.99876693-2.2530144 34.18280086 133.18390974 0.60040685 240.96587169 108.74716969 240.9658717 242.0719252z m-868.63518026 0c0 65.06064555 52.74207826 117.80298272 117.80298272 117.80298272 33.27584736 0 63.32466973-13.80159033 84.74746576-35.98661051l-0.03158673-0.03158673 1.23602515-1.23576623c19.7507704-21.06679803 31.85107854-49.39284884 31.85107854-80.54876034 0-65.06064555-52.74207826-117.80298272-117.80298272-117.80298272-65.06090445-0.0002589-117.80298272 52.74207826-117.80298272 117.80272381z m372.30920692-409.59190913c-73.64032739 0-133.33744197 59.69737349-133.33744198 133.33744198 0 73.64032739 59.69711458 133.33744197 133.33744198 133.33744196s133.33744197-59.69711458 133.33744198-133.33744196c0-73.64006849-59.69711458-133.33744197-133.33744198-133.33744198z"></path>';
|
||||
zib_svgs['weiyun'] = '<path d="M987.909224 900.576653c10.971429-8.986122 21.545796-18.348408 31.681307-28.212245 96.193306-93.748245 149.169633-222.187102 149.169632-361.680979 0-14.524082-0.543347-28.88098-1.609143-43.070694a243.168653 243.168653 0 0 1 91.324082 189.962449c0 143.318204-103.006041 234.809469-270.607673 242.980571l0.041795 0.020898z m-532.500897 0.647837c-110.592 0-199.68-26.791184-257.609143-77.406041-50.823837-44.408163-77.656816-107.52-77.656817-182.522776 0-79.307755 28.065959-148.145633 79.119674-193.870367a211.800816 211.800816 0 0 1 142.774857-54.104816c8.463673 0 16.990041 0.459755 25.558204 1.421061 63.38351 7.000816 112.64 37.114776 135.188898 82.546939 16.509388 33.353143 15.610776 69.820082-2.507755 99.996734-14.085224 23.44751-33.248653 37.908898-56.967837 42.987103-27.397224 5.851429-60.666776-1.191184-84.78302-18.014041l-60.144327 104.155428c50.364082 31.764898 113.099755 43.509551 170.067592 31.305143 56.717061-12.099918 103.340408-46.205388 134.791837-98.617469 39.079184-64.992653 41.712327-145.387102 7.188898-215.123592-36.884898-74.396735-108.105143-125.680327-198.133551-143.777959a257.609143 257.609143 0 0 1 61.565387-84.365061c53.707755-48.817633 129.107592-75.692408 212.365062-75.692409 99.22351 0 190.840163 39.998694 257.94351 112.681796 67.37502 72.933878 104.489796 171.593143 104.489796 277.859266 0 106.788571-40.124082 204.716408-112.911674 275.602285-77.176163 75.190857-183.484082 114.938776-307.388081 114.938776h-172.95151z m677.302857-587.734204C1061.219265 127.749224 890.420245 0 686.226286 0c-113.204245 0-217.338776 37.971592-293.198368 106.976653a381.471347 381.471347 0 0 0-107.770775 170.819918A329.310041 329.310041 0 0 0 119.118367 357.982041C42.360163 426.736327 0 527.36 0 641.295673 0 751.992163 41.085388 846.367347 118.742204 914.285714c80.164571 70.029061 196.545306 107.081143 336.666123 107.081143h507.611428c248.602122 0 415.618612-146.181224 415.618612-363.791673 0-159.346939-103.026939-295.01649-245.885387-344.084898h-0.041796z"></path>';
|
||||
zib_svgs['lanzou'] = '<path d="M250.33955555 863.57105778c-136.51399111 0-247.56679111-111.16544-247.5667911-247.67943111 0-127.07953778 96.27534222-231.99402667 219.71740444-245.97504 40.12487111-124.01095111 155.95178667-209.48764445 287.69166222-209.48764445 166.63552 0 302.23928889 135.60376889 302.23928889 302.35306667 0 13.64081778-1.25041778 27.28049778-3.06858667 40.69262222 10.11598222-1.70439111 20.11932445-2.84103111 30.57664-2.84103111 100.02659555 0 181.41184 81.27146667 181.41184 181.52561778 0 99.91281778-81.27146667 181.52561778-181.41184 181.52561777l-589.58961778-0.11377777zM65.40288 615.89162667c0 101.95854222 82.97813333 184.93553778 184.93667555 184.93553778h589.47584c65.35850667 0 118.66794667-53.19566222 118.66794667-118.66794667 0-65.58606222-53.1968-118.66794667-118.66794667-118.66794667-17.16451555 0-33.53258667 3.52369778-48.87665777 10.56995556-12.16284445 30.80419555-29.32622222 59.56266667-51.03729778 85.25141333l-47.62624-40.8064c37.16892445-43.30723555 57.51466667-98.54976 57.51466667-155.61045333 0-132.19384889-107.52796445-239.60917333-239.60803556-239.60917334-98.09464889 0-185.05045333 59.67530667-221.53671111 148.44814222 25.91516445 4.32014222 52.28657778 13.18684445 79.90727111 26.7116089l109.11971556 55.12874666-28.52977778 55.92405334-108.21063111-54.78741334c-32.39480889-15.91296-62.17614222-23.64302222-90.59214223-23.64302222-101.95968 0.11377778-184.93667555 82.97813333-184.93667555 184.82289778z"></path>';
|
||||
zib_svgs['tianyi'] = '<path d="M838.4 416c-6.4-70.4-64-115.2-134.4-115.2-19.2 0-38.4 6.4-51.2 6.4-44.8-51.2-115.2-83.2-185.6-83.2-89.6 0-172.8 51.2-211.2 128h-12.8C115.2 352 19.2 448 12.8 576s96 224 224 230.4h294.4c25.6 0 44.8-19.2 44.8-44.8s-19.2-44.8-44.8-44.8H249.6c-70.4 0-134.4-57.6-134.4-128s51.2-128 121.6-134.4c12.8 0 25.6 0 38.4 6.4h6.4l25.6 6.4C320 390.4 390.4 320 473.6 320c57.6 0 108.8 32 140.8 83.2 6.4 6.4 6.4 12.8 6.4 19.2l6.4-6.4c19.2-19.2 51.2-19.2 70.4-19.2 44.8 0 70.4 38.4 70.4 76.8 0 12.8-6.4 25.6-6.4 38.4 12.8 6.4 19.2 19.2 38.4 19.2 6.4-6.4 19.2-12.8 19.2-19.2 64 6.4 115.2 57.6 108.8 128-6.4 57.6-57.6 108.8-121.6 108.8-51.2 0-96-32-115.2-83.2h51.2c6.4 0 12.8-6.4 12.8-12.8s0-6.4-6.4-6.4l-96-128c-6.4-6.4-12.8-12.8-19.2-6.4h-6.4l-96 128c-6.4 6.4-6.4 19.2 6.4 19.2 6.4 0 6.4 6.4 6.4 6.4h57.6c19.2 115.2 128 192 243.2 172.8 115.2-19.2 192-128 172.8-243.2-25.6-96-89.6-160-179.2-179.2z"></path>';
|
||||
zib_svgs['ctfile'] = '<path d="M732.719113 649.59415l128.975799 32.518323q-40.546284 158.91298-145.946298 242.363126T458.101875 1007.966394q-157.591923 0-256.305357-64.162716t-150.2753-185.821892Q0 636.281962 0 496.676736q0-152.246724 58.16715-265.634051t165.558912-172.204844Q330.99588 0 460.113947 0q146.332454 0 245.919818 74.46696t138.954859 209.438324l-126.984052 29.916857q-33.819056-106.35524-98.408575-154.909161T457.370213 110.359059q-112.37113 0-187.833963 53.858472t-106.050381 144.625242a581.793447 581.793447 0 0 0-30.587548 187.163273q0 124.362262 36.237607 217.08013t112.696313 138.629676a316.037452 316.037452 0 0 0 165.558912 45.891483q108.367311 0 183.504961-62.496152t101.822999-185.517033zM1194.58092 893.806756l14.023527 85.685781a360.973709 360.973709 0 0 1-73.288171 8.617356q-52.842275 0-81.905526-16.706289t-40.952763-43.92006q-11.869188-27.193448-11.848864-114.505145v-329.24802h-71.133831v-75.44251h71.133831v-141.779888l96.437152-58.187474v199.906391h97.554969v75.442509h-97.554969v334.69484q0 41.481186 5.121636 53.350373a40.42434 40.42434 0 0 0 16.706288 18.860628q11.584653 7.011763 33.148366 7.011763a314.757043 314.757043 0 0 0 42.558355-3.780255z"></path>';
|
||||
zib_svgs['vip_2'] = '<path d="M 1005.8172,351.70336 821.76656,101.2173 C 807.32558,81.588994 784.94516,70.064114 761.241,70.064114 H 259.20108 c -23.47379,0 -45.62431,11.284778 -60.06529,30.552936 L 19.285135,340.53863 c -22.9559861,30.61296 -21.3450398,74.07136 3.79723,102.76351 L 446.1382,928.77022 c 38.51883,40.57913 99.0787,40.87926 147.84328,-0.10692 L 1000.9268,454.40684 c 25.4875,-28.39202 27.5587,-71.85042 4.8904,-102.70348 z M 771.19435,468.39276 545.31666,727.28238 c -7.13419,8.22348 -17.26014,12.84544 -27.9039,12.84544 h -0.23013 c -10.70936,-0.0493 -20.88658,-4.8776 -27.96143,-13.26562 L 270.70784,469.95343 c -13.82618,-16.26491 -12.41002,-41.14051 3.16435,-55.58354 15.59983,-14.39456 39.41935,-12.91852 53.2763,3.3014 L 517.8155,641.86621 715.4441,415.39032 c 14.02155,-16.07753 37.88698,-17.23375 53.2763,-2.58109 15.38525,14.641 16.4925,39.518 2.47395,55.58353 z" fill="#8576e8" /><path d="M 761.18347,70.004089 H 259.20108 c -23.47402,0 -45.62431,11.284778 -60.06529,30.552931 L 19.285135,340.53863 c -22.9559861,30.61296 -21.3450398,74.07136 3.854764,102.76351 L 414.83,889.65112 c 260.51304,-95.26033 447.32529,-354.02989 447.32529,-658.35874 0,-27.49164 -1.55342,-54.62313 -4.54517,-81.33444 L 821.76656,101.15728 C 807.32558,81.528968 784.94493,70.004089 761.18347,70.004089 Z M 771.19435,468.39276 545.31666,727.28238 c -7.13419,8.22348 -17.26014,12.84544 -27.9039,12.84544 h -0.23013 c -10.70936,-0.0493 -20.88658,-4.8776 -27.96143,-13.26562 L 270.70784,469.95343 c -13.82618,-16.26491 -12.41002,-41.14051 3.16435,-55.58354 15.59983,-14.39456 39.41935,-12.91852 53.2763,3.3014 L 517.8155,641.86621 715.4441,415.39032 c 14.02155,-16.07753 37.88698,-17.23375 53.2763,-2.58109 15.38525,14.641 16.4925,39.518 2.47395,55.58353 z" fill="#9487f0" /><path d="m 270.6503,469.95343 c -13.82617,-16.26491 -12.41001,-41.14051 3.16436,-55.58354 15.59983,-14.39456 39.41935,-12.91852 53.2763,3.3014 l 97.00198,114.04829 C 559.0097,420.79261 651.98432,256.8632 674.13483,70.004089 H 259.20108 c -23.47379,0 -45.62431,11.284778 -60.06529,30.552931 L 19.285135,340.53863 c -22.9559861,30.61296 -21.3450398,74.07136 3.854764,102.76351 L 205.40697,650.99007 c 55.57765,-17.64747 108.04848,-42.61804 156.49194,-73.83125 z" fill="#a19ceb" /><path d="M 429.96139,70.004089 H 259.20108 c -23.47577,0 -45.62431,11.284778 -60.06529,30.552931 L 19.285135,340.53863 C 3.8868015,361.06061 -0.88602596,388.1564 6.5126313,413.04933 189.12491,365.029 341.87714,238.55545 429.96139,70.004089 Z" fill="#c0bdeb" />';
|
||||
zib_svgs['vip_1'] = '<path d="m 950.3677,301.98155 c -40.45962,0 -73.22375,33.23643 -73.22375,74.14736 0,4.66372 0.4664,9.26841 1.28258,13.696 L 689.12913,505.9458 552.53419,236.2171 c 30.60706,-15.82125 51.59476,-47.99506 51.59476,-85.18682 0,-52.835883 -42.3252,-95.694942 -94.50296,-95.694942 -52.17775,0 -94.50294,42.859059 -94.50294,95.694942 0,38.78569 22.79497,72.08117 55.5008,87.07592 L 343.76487,505.9458 148.46265,387.28642 c 0.5247,-3.66013 0.93279,-7.32027 0.93279,-11.09848 0,-40.96996 -32.82244,-74.14735 -73.223756,-74.14735 -40.401324,0 -73.340354,33.17739 -73.340354,74.14735 0,36.12912 25.535036,66.17769 59.290253,72.78956 l 82.085227,413.65486 c 8.04529,63.58477 43.31361,109.33254 84.2423,109.33254 h 570.80715 c 40.92602,0 76.13872,-45.74777 84.2423,-109.33254 l 82.08522,-413.891 c 33.17224,-7.08414 58.00772,-36.89657 58.00772,-72.55342 0.058,-40.96996 -32.76417,-74.20639 -73.2238,-74.20639 z M 680.67576,864.76789 H 345.80534 c -22.62008,0 -40.98432,-21.05375 -40.98432,-46.98664 0,-25.93289 18.36424,-46.98665 40.98432,-46.98665 h 334.87042 c 22.61779,0 40.98431,21.05376 40.98431,46.98665 0,25.93289 -18.36075,46.98664 -40.98431,46.98664 z" fill="#fc7032" /><path d="M 878.01844,390.06105 689.12913,505.9458 552.53419,236.2171 c 30.60706,-15.82125 51.59476,-47.99506 51.59476,-85.18682 0,-52.835883 -42.3252,-95.694942 -94.50296,-95.694942 -52.17775,0 -94.50294,42.859059 -94.50294,95.694942 0,38.78569 22.79497,72.08117 55.5008,87.07592 L 343.76487,505.9458 148.46265,387.28642 c 0.5247,-3.6011 0.93279,-7.32027 0.93279,-11.09848 0,-40.96996 -32.82244,-74.14735 -73.223756,-74.14735 -40.459623,0 -73.2237557,33.23643 -73.2237557,74.14735 0,36.12912 25.5350357,66.17769 59.2902537,72.78956 l 82.085228,413.65486 c 8.04529,63.58477 43.30989,109.33254 84.24229,109.33254 h 369.32524 c 169.18418,-180.95783 280.4773,-350.96082 280.4773,-573.16674 -0.11661,-2.89269 -0.2915,-5.78538 -0.3498,-8.73711 z M 680.67576,864.76789 H 345.80534 c -22.62008,0 -40.98432,-21.05375 -40.98432,-46.98664 0,-25.93289 18.36424,-46.98665 40.98432,-46.98665 h 334.87042 c 22.61779,0 40.98431,21.05376 40.98431,46.98665 0,25.93289 -18.36075,46.98664 -40.98431,46.98664 z M 877.96014,386.45995 c -0.1166,-5.90346 -0.17489,-11.86595 -0.46639,-17.71036 -0.2332,2.47946 -0.3498,4.9589 -0.3498,7.43835 0,3.48303 0.3498,6.90703 0.81619,10.27201 z" fill="#ff7e3e" /><path d="m 324.00144,778.01304 c 3.21091,-2.35768 6.70765,-4.15942 10.37726,-5.34699 140.67589,-74.18944 253.60138,-199.30282 316.21468,-342.87477 l -98.0009,-193.51514 c 30.60706,-15.82125 51.59476,-47.99507 51.59476,-85.18681 0,-52.835898 -42.32519,-95.694957 -94.50294,-95.694957 -52.17776,0 -94.50296,42.859059 -94.50296,95.694957 0,38.78567 22.79498,72.08114 55.50081,87.07591 L 343.82316,506.00484 148.46265,387.28642 c 0.5247,-3.6011 0.93279,-7.32027 0.93279,-11.09848 0,-40.96996 -32.82244,-74.14735 -73.223756,-74.14735 -40.459623,0 -73.2237557,33.23643 -73.2237557,74.14735 0,36.12912 25.5350357,66.17769 59.2902537,72.78956 l 71.707978,361.35028 c 66.92745,-6.848 130.82333,-2.5053 190.05528,-32.31474 z" fill="#ff9552" /><path d="m 534.16995,58.759342 c -7.81209,-2.125243 -16.03227,-3.364969 -24.54396,-3.364969 -52.17775,0 -94.50294,42.859059 -94.50294,95.694957 0,38.78567 22.79497,72.08114 55.5008,87.07591 l -18.42253,38.90375 C 491.90305,211.12743 520.00325,137.39331 534.16995,58.759342 Z M 148.46265,387.28642 c 0.5247,-3.6011 0.93279,-7.32027 0.93279,-11.09848 0,-40.96996 -32.82244,-74.14735 -73.223756,-74.14735 -40.459623,0 -73.2237557,33.23643 -73.2237557,74.14735 0,36.12912 25.5350357,66.17769 59.2902537,72.78956 L 84.508464,561.08405 C 154.05441,540.90524 219.67547,508.81894 278.52809,466.21558 Z" fill="#ffa56a" />';
|
||||
zib_svgs['menu_2'] = '<path d="M123.605 383.202C55.368 383.202 0.021 438.52 0.021 506.785c0 68.272 55.34 123.584 123.584 123.584 68.242 0 123.584-55.305 123.584-123.584-0.016-68.25-55.342-123.583-123.584-123.583z m388.398 0c-68.237 0-123.584 55.318-123.584 123.583 0 68.272 55.34 123.584 123.584 123.584 68.235 0 123.577-55.305 123.577-123.584 0-68.25-55.349-123.583-123.577-123.583z m388.392 0c-68.23 0-123.584 55.318-123.584 123.583 0 68.272 55.34 123.584 123.584 123.584 68.242 0 123.584-55.305 123.584-123.584 0-68.25-55.342-123.583-123.584-123.583z m0 0"></path>';
|
||||
zib_svgs['alipay'] = '<path d="M653.80568 617.306394c70.196759-127.645169 95.735411-248.897743 95.735411-248.897743l-12.766768 0 0 0L628.282377 368.408651 513.408069 368.408651l0-89.352027 280.800337 0 0-38.283931L513.408069 240.772692 513.408069 106.752326 385.771087 106.752326l0 134.020366L130.495076 240.772692l0 38.283931 255.277034 0 0 89.352027L168.784124 368.408651l0 38.289048 440.3481 0c0 6.383384 0 6.383384-6.383384 12.761652 0 44.669362-31.906687 108.49604-57.434084 159.542646C219.835847 451.360921 124.105552 527.945157 98.578156 540.718065c-216.981846 153.159262-12.761652 344.616782 19.154245 338.239538 229.749638 51.051723 376.530632-44.673455 478.639195-165.93217 6.382361 6.383384 12.761652 6.383384 19.149129 6.383384 70.196759 38.284955 408.436296 197.836811 408.436296 197.836811L1023.957021 725.798341C972.901205 725.798341 787.829116 661.980873 653.80568 617.306394L653.80568 617.306394 653.80568 617.306394zM487.874533 674.742525c-159.542646 204.221218-351.002212 140.39761-382.9089 127.635959-76.574003-19.150152-102.107539-159.547763-6.387477-204.226335 159.547763-51.051723 299.954583 6.387477 402.063145 57.4392C494.263034 668.358117 487.874533 674.742525 487.874533 674.742525L487.874533 674.742525 487.874533 674.742525zM487.874533 674.742525"></path>';
|
||||
zib_svgs['baidu'] = '<path d="M412.54 94.74c13.82-2.69 28.21 0.67 40.52 7.13 18.32 10.72 32.2 27.86 41.03 46.99 18.82 40.57 19.04 88.91 2.38 130.23-7.83 18.05-19.17 35.23-35.44 46.7-14.17 10.44-32.65 15.51-50.08 12.14-14.7-2.84-28.09-10.75-38.4-21.51-16.41-16.26-26.44-37.85-32.21-59.97-7.82-32.14-6.07-66.64 5.6-97.63 7.58-20.05 19.98-38.77 37.36-51.6 8.68-6.21 18.62-10.89 29.24-12.48zM642.54 112.74c14.09-3.24 28.43 1.98 40.47 9.09 12.5 7.77 23.39 18.14 31.82 30.2 13.27 17.99 21.69 39.65 23.54 61.95 1.2 20.12-4.42 39.95-11.88 58.44-8.6 20.17-20.6 39.39-37.41 53.73-11.2 9.99-25.06 17.06-39.91 19.51-15.25 2.42-31.08 0-45.41-5.48-16.19-6.35-29.7-18.93-37.51-34.43-9.97-19.57-12.73-42-12.38-63.72 0.38-12.08 1-24.34 4.57-35.97 5.44-18.49 15.28-35.39 26.82-50.71 9.67-12.59 21.15-23.86 34.29-32.81 7.03-4.53 14.79-8.01 22.99-9.8zM228.55 276.76c14.19-2.87 29.11-0.38 42.36 5.14 27.56 12.82 48.47 37.44 59.87 65.31 4.69 11.29 5.89 23.58 6.5 35.67 1.23 21.99-0.51 44.34-7.05 65.44-5.65 17.81-15.84 34.6-30.88 46-15.06 11.23-33.63 17.35-52.32 18.33-20.48 1.2-41.53-6-56.36-20.3-14.41-13.11-24.12-30.65-30.28-48.96-6.19-18.39-9.2-38.17-6.38-57.49 3.11-23.27 9.52-46.34 20.89-66.98 5.74-10.16 12.93-19.57 21.82-27.18 9.15-7.51 20.19-12.76 31.83-14.98zM773.09 335.14c16.95-1.24 34.45 1.2 49.77 8.79 16.02 7.8 28.92 21.02 38.19 36.07 10.21 17.52 16.89 37.52 16.85 57.94 0.51 21.72 0.12 43.77-5.45 64.91-4.39 15.87-11.71 31.45-23.77 42.96-14.07 13.2-33.49 19.59-52.57 19.96-19.19 0.57-39.12-0.89-56.7-9.27-17.16-7.33-30.5-22.16-37.31-39.39-7.85-19.67-9.44-41.14-9.35-62.12-0.01-24.34 2.7-49.22 12.47-71.74 6.11-13.99 15.56-26.85 28.47-35.25 11.5-8.11 25.55-11.68 39.4-12.86zM499.58 415.76c19.31-2.26 39.11 0.99 56.87 8.84 27.51 12.15 49.18 34.47 65.89 59.02 21.56 32.4 47.59 61.52 74.73 89.3 23.38 23.32 47.52 45.93 72.92 67.05 5.74 4.96 11.94 9.4 17.25 14.85 18.04 18.41 29.75 42.69 33.91 68.05 5.31 31.4-1.18 63.71-13.33 92.79-8.36 21.32-23.98 39.76-43.85 51.21-21.13 12.43-45.72 17.37-69.93 18.95-34.13 1.93-68.29-3.36-101.12-12.43-41.83-13.18-86.85-16.16-130.03-8.51-21.43 4.49-42.94 8.86-64.77 10.85-26.62 2.82-53.48 3.1-80.2 1.62-19.06-0.37-38.15-5.73-54.21-16.1-17.72-10.45-31.47-26.56-41.39-44.4-8.27-15.27-13.79-31.93-17.34-48.89-5.11-24.73-3.54-50.94 5.59-74.56 12.72-33.67 37.73-61.18 65.64-83.21 6.93-5.78 14.54-10.69 21.4-16.56 14.15-13.89 29.74-26.2 43.84-40.14 21.96-21.36 42.44-44.56 58.28-70.89 20.78-35.88 58.42-62.08 99.85-66.84z"></path>';
|
||||
zib_svgs['gitee'] = '<path d="M978.5 409.6H455.1c-25.1 0-45.5 20.3-45.5 45.5v113.7c0 25.1 20.3 45.5 45.5 45.5h318.6c25.1 0 45.5 20.4 45.5 45.5v22.6c0 75.4-61.2 136.5-136.5 136.5H250.3c-25.1 0-45.5-20.4-45.5-45.5V341.2c0-75.5 61.2-136.5 136.5-136.5h637c25.1 0 45.5-20.3 45.5-45.5l0.1-113.6c0-25.1-20.3-45.5-45.5-45.5H341.3C152.9 0 0 152.9 0 341.3v637.2c0 25.1 20.4 45.5 45.5 45.5h671.3c169.6 0 307.2-137.5 307.2-307.2V455.1c0-25.1-20.4-45.5-45.5-45.5z"></path>';
|
||||
zib_svgs['comment-fill'] = '<path d="M512 115.6c-249.9 0-448.5 174-448.5 386.7 0 58 19.2 116 44.9 167.6l44.9 238.5L371 869.7c44.9 12.9 89.7 19.3 141 19.3 249.9 0 448.5-174 448.5-386.7 0-212.6-198.6-386.7-448.5-386.7zM255.7 437.9c38.4 0 64.1 25.8 64.1 64.4 0 38.7-25.6 64.4-64.1 64.4-38.4 0-64.1-25.8-64.1-64.4 0-38.6 25.7-64.4 64.1-64.4zM512 566.8c-38.4 0-64.1-25.8-64.1-64.4 0-38.7 25.6-64.4 64.1-64.4 38.4 0 64.1 25.8 64.1 64.4 0 38.6-25.7 64.4-64.1 64.4z m256.3 0c-38.4 0-64.1-25.8-64.1-64.4 0-38.7 25.6-64.4 64.1-64.4 38.4 0 64.1 25.8 64.1 64.4 0 38.6-25.7 64.4-64.1 64.4z"></path>';
|
||||
zib_svgs['private'] = '<path d="M469.942857 512c0 25.6 19.2 51.2 51.2 51.2 25.6 0 51.2-19.2 51.2-51.2 0-25.6-19.2-51.2-51.2-51.2-25.6 0-51.2 25.6-51.2 51.2z m204.8 0c0 25.6 19.2 51.2 51.2 51.2s51.2-19.2 51.2-51.2c0-25.6-19.2-51.2-51.2-51.2s-51.2 25.6-51.2 51.2zM271.542857 512c0 25.6 19.2 51.2 51.2 51.2s44.8-25.6 44.8-51.2-19.2-51.2-51.2-51.2-44.8 25.6-44.8 51.2z m665.6-172.8c-25.6-57.6-57.6-102.4-96-147.2-38.4-38.4-89.6-76.8-140.8-96C642.742857 76.8 578.742857 64 521.142857 64 457.142857 64 399.542857 76.8 341.942857 102.4c-51.2 19.2-96 51.2-140.8 96S130.742857 288 105.142857 339.2C85.942857 396.8 73.142857 454.4 73.142857 512c0 70.4 19.2 140.8 51.2 198.4v153.6c0 25.6 19.2 44.8 44.8 44.8h153.6c64 32 128 44.8 198.4 51.2 57.6 0 115.2-12.8 172.8-32 51.2-19.2 102.4-51.2 140.8-96 38.4-38.4 76.8-89.6 96-140.8 25.6-57.6 38.4-115.2 38.4-179.2 0-57.6-12.8-115.2-32-172.8z m-153.6 435.2C713.142857 844.8 617.142857 883.2 521.142857 883.2c-57.6 0-121.6-12.8-172.8-44.8l-6.4-6.4H194.742857V691.2l-6.4-6.4C162.742857 633.6 149.942857 576 149.942857 512c0-102.4 38.4-192 108.8-262.4C329.142857 179.2 418.742857 140.8 521.142857 140.8c51.2 0 96 12.8 147.2 32 44.8 19.2 83.2 44.8 121.6 76.8 32 32 64 76.8 76.8 121.6 19.2 44.8 32 96 32 147.2-6.4 96-44.8 185.6-115.2 256z"></path>';
|
||||
zib_svgs['hot-fill'] = '<path d="M921.053465 625.705187c0 230.830879-173.604142 398.335748-412.826638 398.335748C270.846393 1024.040935 102.44096 856.495131 102.44096 625.705187c0-122.558548 72.208844-254.573016 75.278948-260.058268a31.519733 31.519733 0 0 1 31.437864-16.128279c12.730698 1.678323 23.169051 11.052374 26.443828 23.619332 0.163739 0.77776 19.60773 74.828666 45.314734 116.049928 17.233517 27.630935 34.753576 47.197731 54.443176 60.788057-13.344718-58.782256-23.537463-147.119379-6.917968-237.789781C374.042819 63.262152 566.599736 3.743071 574.827614 1.327922a30.578235 30.578235 0 0 1 29.964214 7.204511 32.256558 32.256558 0 0 1 9.660594 29.636736c-0.327478 1.801128-32.092819 176.01929 35.367597 324.489515 6.099273 13.508457 14.613695 29.227389 23.864941 44.864452 2.578887-21.531662 6.672359-44.373235 12.894436-66.600787 24.765505-88.091515 88.74647-118.178533 91.448162-119.406575a31.31506 31.31506 0 0 1 32.338428 4.011603c9.210312 7.368249 13.631261 19.321187 11.54359 31.028516-0.327478 2.16954-9.292181 62.138903 40.852849 147.160314 45.232864 76.752598 58.291039 126.57015 58.29104 221.98898z"></path>';
|
||||
zib_svgs['hot'] = '<path d="M429.568429 1023.994675S87.04221 973.306939 87.04221 681.468456c0-291.838482 447.485673-319.486339 348.670187-681.468456 0 0 335.358256 104.959454 253.438682 431.613756 0 0 44.543768-28.159854 78.335592-83.455566 0 0 169.471119 131.071318 169.471119 330.75028 0 199.678962-235.006778 346.1102-346.622197 345.086205 0 0 120.319374-162.303156 10.751944-267.26261-155.135193-148.479228-89.087537-244.22273-89.087537-244.22273S133.633968 697.852371 429.568429 1023.994675"></path>';
|
||||
zib_svgs['topping'] = '<path d="M256 51.2h512a51.2 51.2 0 0 1 0 102.4H256a51.2 51.2 0 1 1 0-102.4z"></path><path d="M876.4928 432.9984l-234.1888-193.1264a204.8 204.8 0 0 0-260.608 0L147.456 432.9984A102.4 102.4 0 0 0 212.6848 614.4H307.2v153.6a204.8 204.8 0 1 0 409.6 0v-153.6h94.5152a102.4 102.4 0 0 0 65.1776-181.4016z m-302.336-108.2368L819.2 512h-102.4a102.4 102.4 0 0 0-102.4 102.4v153.6a102.4 102.4 0 1 1-204.8 0v-153.6a102.4 102.4 0 0 0-102.4-102.4H204.8l245.0432-187.2384a102.4 102.4 0 0 1 124.3136 0z"></path>';
|
||||
zib_svgs['topic'] = '<path d="M434.432 802.901333a58.197333 58.197333 0 1 1-116.352 0l-0.042667-96.981333h-174.506666a58.197333 58.197333 0 1 1 0-116.352h174.506666V395.605333H221.098667a58.197333 58.197333 0 1 1 0-116.352h96.938666V143.530667a58.197333 58.197333 0 0 1 116.394667 0l-0.042667 135.722666h193.962667V221.098667a58.197333 58.197333 0 0 1 116.394667 0l-0.042667 58.154666h135.765333a58.197333 58.197333 0 1 1 0 116.394667l-135.765333-0.042667v193.962667h58.197333a58.197333 58.197333 0 1 1 0 116.352h-58.197333v174.549333a58.197333 58.197333 0 1 1-116.352 0v-174.549333h-193.962667v96.981333z m-0.042667-213.333333h193.962667V395.605333h-193.962667v193.962667z"></path>';
|
||||
zib_svgs['plate-fill'] = '<path d="M383.02 501.504L112.856 366.805l-0.853-0.426c-12.203-5.675-24.32-8.534-35.968-8.534-15.19 0-29.099 5.206-39.125 14.635a49.963 49.963 0 0 0-15.574 36.864v363.35c0 15.103 6.272 31.829 17.707 47.06 11.179 14.934 26.539 27.52 43.307 35.414l270.08 134.699 0.768 0.426 0.213 0.043c12.288 5.675 24.405 8.533 35.968 8.533 15.19 0 29.099-5.162 39.125-14.592 10.027-9.429 15.574-22.528 15.574-36.906V584.107c0-15.147-6.315-31.872-17.707-47.104a117.76 117.76 0 0 0-43.35-35.414zM953.9 372.48a56.49 56.49 0 0 0-39.125-14.635c-11.69 0-23.765 2.902-35.968 8.534L607.79 501.547c-16.768 7.893-32.128 20.48-43.307 35.413-11.435 15.232-17.707 32-17.707 47.104v363.307c0 14.378 5.547 27.477 15.574 36.906 9.984 9.387 23.893 14.592 39.082 14.592h0.17a86.109 86.109 0 0 0 36.012-8.618l269.78-135.083c16.769-7.893 32.172-20.48 43.35-35.413 11.392-15.232 17.664-32 17.664-47.147l1.024-363.264c0-14.336-5.546-27.435-15.53-36.864z m-96-118.272c23.894-11.477 37.462-29.867 37.334-50.432-0.17-20.395-13.696-38.4-37.205-49.365L557.655 12.928c-16.213-7.595-37.12-11.733-58.794-11.733-22.87 0-44.928 4.522-62.08 12.8L133.207 161.536c-23.808 11.52-37.418 29.91-37.248 50.475 0.128 20.352 13.654 38.357 37.163 49.322l300.373 141.483c11.52 5.419 25.515 9.088 40.534 10.752l-1.11 1.024h19.37c22.828 0 44.886-4.565 62.124-12.885L857.9 254.208z"></path><';
|
||||
zib_svgs['extra-points'] = '<path d="M949.79 815.69L551.71 126.21a45.27 45.27 0 0 0-78.42 0L75.21 815.69c-17.42 30.18 4.36 67.92 39.22 67.92h796.14c34.86 0 56.64-37.74 39.22-67.92zM185 797.61l327.5-567.32L840 797.61z"></path>';
|
||||
zib_svgs['deduct-points'] = '<g style="transform-origin:center;transform:rotate(180deg);"><path d="M949.79 815.69L551.71 126.21a45.27 45.27 0 0 0-78.42 0L75.21 815.69c-17.42 30.18 4.36 67.92 39.22 67.92h796.14c34.86 0 56.64-37.74 39.22-67.92zM185 797.61l327.5-567.32L840 797.61z"></path></g>';
|
||||
zib_svgs['share'] = '<path d="M823.04 1024H200.96a172.8 172.8 0 0 1-170.24-174.72V249.984a172.8 172.8 0 0 1 170.24-174.784h202.88v96H200.96a78.592 78.592 0 0 0-77.44 78.912v599.296a78.528 78.528 0 0 0 77.44 78.848h622.08a78.144 78.144 0 0 0 77.44-78.848V564.032h92.8v285.376A172.8 172.8 0 0 1 823.04 1024z m-345.6-293.824l-91.52-17.088a880.832 880.832 0 0 1 120.96-294.848 669.376 669.376 0 0 1 202.88-206.016 604.8 604.8 0 0 1 102.4-51.712L638.08 89.024l34.56-89.088 290.56 121.6 28.8 22.272 1.92 44.416-16.64 45.824-128.64 245.504-81.92-45.44 100.48-192a488.768 488.768 0 0 0-108.16 51.584A576 576 0 0 0 584.32 471.04a803.008 803.008 0 0 0-106.88 259.136z m495.36-491.328l-1.92 1.664z m-22.4-60.416l-3.2 0.96z m-11.52-17.984l-1.28 1.856 1.92-1.856h-0.64z m12.8-45.888l2.56 1.344a15.488 15.488 0 0 1-2.56-1.344z" style="transform:scale(.85);transform-origin: center;"></path>';
|
||||
zib_svgs['approve'] = '<path d="M856 633.6h-137.6c-8-4.8-16-11.2-22.4-19.2-28.8-28.8-30.4-52.8-28.8-62.4v-6.4c0-3.2 4.8-16 16-35.2 4.8-8 8-14.4 12.8-20.8 9.6-16 20.8-30.4 32-44.8 40-48 62.4-108.8 62.4-171.2C792 128 673.6 6.4 523.2 0h-20.8C352 6.4 232 128 232 273.6c0 62.4 22.4 123.2 62.4 171.2l1.6 3.2c11.2 14.4 20.8 28.8 32 43.2 20.8 30.4 28.8 51.2 27.2 54.4v6.4c0 9.6-1.6 33.6-27.2 62.4l-1.6 1.6c-6.4 6.4-14.4 12.8-22.4 19.2h-137.6c-91.2 0-132.8 35.2-132.8 116.8v179.2c0 25.6 9.6 49.6 27.2 67.2 20.8 16 44.8 25.6 70.4 25.6l763.2-1.6c52.8 0 94.4-43.2 94.4-94.4V750.4c-1.6-80-41.6-116.8-132.8-116.8zM105.6 929.6V750.4c0-22.4 3.2-32 9.6-38.4 8-6.4 22.4-8 51.2-8h158.4l8-4.8c16-9.6 30.4-20.8 43.2-33.6 44.8-46.4 49.6-92.8 49.6-115.2 1.6-24-11.2-52.8-40-96l-38.4-52.8c-28.8-35.2-44.8-80-46.4-126.4 0-108.8 88-198.4 201.6-203.2h17.6c112 4.8 200 94.4 200 203.2 0 46.4-16 91.2-46.4 126.4-12.8 16-25.6 33.6-36.8 51.2-4.8 8-11.2 16-16 25.6-17.6 32-25.6 52.8-25.6 73.6-1.6 24 3.2 68.8 49.6 115.2 12.8 12.8 27.2 24 43.2 35.2l8 4.8h158.4c56 0 60.8 8 60.8 46.4V928c0 6.4-3.2 12.8-8 17.6-4.8 4.8-11.2 8-17.6 8H131.2c-6.4 0-12.8-3.2-17.6-8-4.8-3.2-8-9.6-8-16z"></path><path d="M328 804.8h368v70.4h-368v-70.4z"></path>';
|
||||
zib_svgs['qzone-color'] = '<path d="M1016.86385778 416.68152889c9.54026667-9.99537778 4.27804445-26.77873778-9.18528-29.30119111l-314.97329778-58.99832889c-5.50456889-1.03082667-10.26275555-4.53632-12.94791111-9.53799111L527.78439111 35.53166222c-3.18350222-5.95057778-9.49134222-8.93155555-15.78666666-8.98389333-6.29418667 0.0512-12.60088889 3.03445333-15.78439112 8.98389333L344.24376889 318.84401778c-2.68515555 5.00167111-7.44448 8.50716445-12.94904889 9.53799111L16.32142222 387.38033778c-13.46332445 2.52245333-18.72554667 19.30581333-9.18528 29.30119111L236.24817778 656.59562667c4.05504 4.24732445 5.92213333 10.18538667 5.04376889 16.04266666l-52.35484445 320.88974222c-2.06961778 13.79669333 11.82606222 24.35640889 24.23239111 18.41152L504.03555555 871.34094222a18.31594667 18.31594667 0 0 1 7.96444445-1.79768889 18.31822222 18.31822222 0 0 1 7.96785778 1.79768889L810.83050667 1011.93955555c12.40632889 5.94488889 26.30200889-4.61482667 24.23239111-18.41152l-53.33902223-326.88128 235.13998223-249.96522666z" fill="#FFCD00"></path><path d="M565.95342222 491.09902222c-5.13934222-4.29169778-126.27854222-45.88885333-311.71470222-18.20444444-3.59537778 0.53475555-6.72768-0.44828445-9.14773333-2.26645333-0.81578667 4.55111111 4.08120889 8.13738667 10.22634666 8.56405333 130.91726222 9.12611555 204.14008889 62.56298667 226.97756445 81.35224889 46.39857778-32.90794667 81.78574222-57.57838222 83.12945777-58.62627556 4.17336889-3.24949333 4.20408889-7.74940445 0.52906667-10.82026666m154.33955556-34.10147556c-47.49539555 40.01336889-182.22535111 133.00280889-229.28497778 168.92359111-5.53415111 4.22229333-3.61472 10.72241778 2.38705778 13.0048 19.39342222 7.38190222 41.22168889 13.59644445 64.19456 18.71075555l181.79868444-173.20163555c14.27228445-15.00046222 5.95968-33.16849778-11.85792-37.16096-1.16622222 3.42584889-3.70801778 6.75043555-7.23626667 9.72344889M859.23498667 657.63555555l-0.11491556 0.0512c-80.16327111 33.80224-274.81884445 90.59328-514.00476444 82.29546667-28.88362667-1.00124445-57.60568889-4.22684445-73.71207112-7.19644444-2.35178667-0.43235555-4.41230222-1.15143111-6.2304711-2.10033778-12.02289778 13.90819555 2.35861333 24.41898667 53.64394666 34.79324445 150.05696 30.35136 325.45792 44.29824 472.52366222 34.88995555l-10.10801778-61.80864c49.75160889-35.76149333 73.95100445-66.61233778 76.82730667-71.19075555 3.29841778-5.25198222 1.17532445-9.73368889 1.17532445-9.7336889" fill="#F1A308"></path><path d="M861.14190222 665.59431111c-60.65493333 5.84476445-245.63939555 4.19384889-354.78869333-37.73667556-5.81063111-2.23232-7.77557333-8.60842667-2.42232889-12.73628444 45.53955555-35.08906667 175.9232-125.92924445 221.88259555-165.0176 8.95658667-7.61856 11.32088889-17.56387555 0.42666667-25.64778666-20.8896-15.49994667-94.62670222-41.19096889-179.99416889-41.88842667-122.16661333-1.00124445-242.18510222 33.56216889-294.83576888 61.5424-12.49621333 6.64120889-4.99712 24.14478222 7.77102222 22.18097777 186.84928-28.71751111 308.90097778 14.51349333 314.07786666 18.96675556 3.70346667 3.18350222 3.49752889 7.85749333-0.56888888 11.05351111-3.45429333 2.71815111-226.71701333 163.11182222-293.80835556 219.71626667-10.56540445 8.91335111-7.78808889 27.58656 9.50044444 30.74048 16.10183111 2.93774222 44.83527111 6.15765333 73.70979556 7.14979556 239.13016889 8.20792889 433.85059555-48.05973333 513.9968-81.49902223 0 0-2.44394667-8.02929778-14.94698667-6.82439111" fill="#FFFFFF"></path>';
|
||||
zib_svgs['qq-color'] = '<path d="M686.293 1024c91.136 0 164.352-34.304 164.352-76.288S776.917 870.4 686.293 870.4s-164.352 33.792-164.352 76.288S595.67 1024 686.293 1024z m-348.672 0c90.624 0 164.352-34.304 164.352-76.288S428.245 870.4 337.621 870.4 173.27 904.192 173.27 946.688 246.997 1024 337.621 1024z" fill="#F5B824"></path><path d="M166.613 724.48a354.816 354.816 0 0 0 343.552 243.712h3.072A354.816 354.816 0 0 0 856.79 724.48c51.2 108.032 51.2 86.016 61.44 77.312 85.504-137.216-39.936-294.912-39.936-294.912L843.99 388.096C840.917 0 528.597 0 512.213 0S183.51 0 183.51 388.096L146.133 506.88s-125.44 158.72-40.96 294.912c9.728 6.656 10.24 30.72 61.44-77.312z" fill="#121213"></path><path d="M593.11 348.16c36.863 0 66.56-41.984 66.56-93.696s-29.697-93.696-66.56-93.696S526.55 204.8 526.55 256s29.695 92.16 66.56 92.16z m-171.009 0c36.864 0 66.56-40.96 66.56-92.16s-29.696-93.696-66.56-93.696-66.56 42.496-66.56 93.696 27.648 92.16 66.56 92.16z" fill="#FFFFFF"></path><path d="M443.605 294.912c15.872 0 28.672-17.92 28.672-40.448s-12.8-40.448-28.672-40.448-28.672 18.432-28.672 40.448 12.8 40.448 28.672 40.448z m172.544 5.632c15.872 0 28.672-17.92 28.672-40.448s-12.8-40.448-28.672-40.448-28.672 18.432-28.672 40.448 12.8 40.448 28.672 40.448z" fill="#161616"></path><path d="M512.213 951.808c376.832 0 269.312-484.864 269.312-484.864A421.376 421.376 0 0 1 512.213 550.4a420.864 420.864 0 0 1-269.312-83.456s-107.52 484.864 269.312 484.864z" fill="#FAFAFB"></path><path d="M275.67 606.72c-3.073 34.816-7.68 88.064-7.169 115.2 0 42.496 26.624 45.056 86.528 51.2s47.616-10.24 47.616-37.376V650.24a414.208 414.208 0 0 0 109.056 7.68 465.408 465.408 0 0 0 366.08-153.6 475.648 475.648 0 0 0-36.864-117.76 371.712 371.712 0 0 1-328.704 161.792A371.712 371.712 0 0 1 183.51 388.096a531.456 531.456 0 0 0-37.376 118.784 455.168 455.168 0 0 0 129.536 99.84z" fill="#D53118"></path><path d="M512.725 486.912a409.6 409.6 0 0 0 209.408-51.2v-4.096c0-1.024-8.192-15.36-31.744-22.016a494.08 494.08 0 0 0-178.176-35.84 494.08 494.08 0 0 0-175.616 35.84c-25.6 8.704-35.84 15.36-35.84 24.064a7.68 7.68 0 0 0 0 4.096 409.6 409.6 0 0 0 211.968 49.152z" fill="#F0B225"></path>';
|
||||
zib_svgs['weibo-color'] = '<path d="M1010.912 451.136a39.104 39.104 0 1 1-74.624-23.424 197.184 197.184 0 0 0-40.224-190.944 191.168 191.168 0 0 0-183.616-60 37.824 37.824 0 0 1-29.248-5.856 44.8 44.8 0 0 1-17.536-26.336 38.784 38.784 0 0 1 29.984-46.816 268.256 268.256 0 0 1 258.24 84.864 276.832 276.832 0 0 1 57.056 268.48z" fill="#FF9933"></path><path d="M738.88 302.592a35.2 35.2 0 0 1-25.6-4.384 36.352 36.352 0 0 1-14.624-21.216 33.696 33.696 0 0 1 25.6-40.224 131.424 131.424 0 0 1 125.824 40.96 135.072 135.072 0 0 1 27.808 130.944 32.416 32.416 0 0 1-16.832 19.744 34.464 34.464 0 0 1-47.552-41.6 66.656 66.656 0 0 0-13.152-64.384 62.752 62.752 0 0 0-61.472-19.84z" fill="#FF9933"></path><path d="M768.864 496.48c58.528 18.304 124.352 62.912 124.352 141.92 0 130.208-185.088 294.816-463.808 294.816-212.16 0-429.44-104.608-429.44-276.544 0-89.984 56.32-193.856 152.896-291.904C281.632 233.824 432.32 174.56 488.64 231.616c24.864 25.6 27.072 69.504 11.712 121.44-8.768 27.072 23.424 12.448 23.424 12.448 104.608-44.64 195.2-46.816 228.256 1.472a108.8 108.8 0 0 1-0.736 103.136c-6.592 19.008 2.912 21.952 17.568 26.336z" fill="#E6162D"></path><path d="M429.44 870.944c169.6-16.832 298.464-122.176 286.784-235.552-10.24-112.672-156.544-190.208-326.4-173.376s-297.6 122.176-286.784 235.552c11.104 112.736 157.408 190.304 326.4 173.376z" fill="#FFFFFF"></path><path d="M447.072 549.152a128.8 128.8 0 0 1 92.192 179.2 181.184 181.184 0 0 1-218.752 93.632 128 128 0 0 1-80.48-182.176 184.736 184.736 0 0 1 207.04-90.656z" fill="#1A1A1A"></path><path d="M384.864 737.184a45.984 45.984 0 0 0-19.2-68.928 64 64 0 0 0-76.096 25.6 46.016 46.016 0 0 0 17.568 68.768 63.008 63.008 0 0 0 77.728-25.44z" fill="#FFFFFF"></path>';
|
||||
zib_svgs['poster-color'] = '<path d="M800.614 930.765H230.042c-73.524 0-133.12-59.597-133.12-133.12V226.304c0-73.523 59.596-133.12 133.12-133.12h570.572c73.524 0 133.12 59.597 133.12 133.12v571.29c0 73.523-59.596 133.17-133.12 133.17z" fill="#FFB96E"></path><path d="M933.734 451.123l-352 218.42a46.454 46.454 0 0 1-57.292-6.554L409.907 548.915a46.5 46.5 0 0 0-65.126-0.46L96.92 788.53v12.8c0 71.475 57.908 129.383 129.383 129.383h578.048c71.475 0 129.382-57.908 129.382-129.383V451.123z" fill="#FF7C0E"></path><path d="M268.442 335.718a68.864 68.864 0 1 0 137.728 0 68.864 68.864 0 1 0-137.728 0z" fill="#FFFFFF"></path>';
|
||||
zib_svgs['copy-color'] = '<path d="M736.341333 130.474667a75.904 75.904 0 0 0-107.349333 0l-154.453333 154.496a75.904 75.904 0 0 0 0 107.349333l45.909333 45.952 95.146667-95.146667a44.757333 44.757333 0 0 1 63.274666 63.317334l-95.146666 95.146666 45.269333 45.226667a75.904 75.904 0 0 0 107.349333 0l154.496-154.496a75.904 75.904 0 0 0 0-107.349333l-154.496-154.496z" fill="#41d2d2"></path><path d="M345.6 613.12a44.757333 44.757333 0 1 0 63.317333 63.274667l95.146667-95.146667 45.226667 45.269333a75.904 75.904 0 0 1 0 107.349334l-154.496 154.496a75.904 75.904 0 0 1-107.349334 0L132.949333 733.866667a75.904 75.904 0 0 1 0-107.349334l154.453334-154.453333a75.904 75.904 0 0 1 107.392 0l45.952 45.909333-95.146667 95.146667z" fill="#4193db"></path>';
|
||||
zib_svgs['user-auth'] = '<defs><linearGradient x1="104.617" x2="899.526" y1="120.692" y2="896.775" gradientUnits="userSpaceOnUse" id="_00a1"><stop offset="0" stop-color="#5fb5ff"></stop><stop offset="1" stop-color="#0060ef"></stop></linearGradient></defs><path d="M37.187 583.527c54.417 45.581 92.125 139.24 84.635 209.533l1.088-9.987c-7.49 70.548 43.597 122.275 114.084 116.065l-10.052.833c70.679-6.21 163.572 33.353 208.002 88.345l-6.338-7.874c44.622 55.248 117.348 55.632 162.739 1.408l-6.467 7.746c45.583-54.415 139.244-92.122 209.538-84.632l-10.051-1.088c70.614 7.49 122.342-43.597 116.068-114.017l.896 10.05c-6.21-70.74 33.355-163.63 88.348-208.06l-7.874 6.338c55.185-44.62 55.633-117.346 1.408-162.735l7.747 6.466c-54.417-45.581-92.125-139.176-84.635-209.533l-1.088 10.051c7.49-70.612-43.598-122.275-114.084-116.065l10.051-.897c-70.678 6.274-163.571-33.29-208-88.281l6.337 7.81C554.917-10.181 482.19-10.629 436.8 43.595l6.466-7.747c-45.582 54.416-139.243 92.123-209.537 84.697l10.05 1.024c-70.613-7.49-122.278 43.66-116.068 114.081l-.896-10.05c6.21 70.676-33.354 163.567-88.348 208.06l7.875-6.402c-55.185 44.685-55.634 117.346-1.409 162.735Z" fill="url(#_00a1)"></path><path fill="#fff" d="M447.4 743.76c-10.126 11.545-23.881 17.089-38.178 17.089-14.424 0-28.148-5.65-38.273-17.23L232.916 585.79c-21.027-24.283-20.928-62.672.223-86.822 20.922-23.92 55.581-23.76 76.324.352l99.887 114.61 288.866-329.39c20.825-24.036 55.5-24.036 76.324 0 21.11 24.044 21.11 63.06 0 87.07L447.432 743.76Z"></path>';
|
||||
zib_svgs['money'] = '<path d="M940.169 692.661c0 283.552-369.536 293.951-423.799 293.951h-13.107c-54.263 0-423.799-10.398-423.799-293.951 0-305.835 343.278-450.451 343.278-450.451s-115.038-40.633-115.038-126.703c0-69.905 171.092-72.701 198.486-72.701h7.34c27.394 0 198.486 2.796 198.486 72.701 0 86.202-115.038 126.703-115.038 126.703s343.19 144.442 343.19 450.451zM573.561 299.663c-19.442-8.459-32.789-27.502-32.789-49.661 0-23.282 14.734-43.123 35.386-50.707 15.317-5.582 69.625-32.059 75.653-66.268-16.034-10.529-68.027-22.981-138.455-22.981h-7.165c-70.43 0-122.334 12.496-138.455 22.85 6.073 34.515 61.167 61.167 75.279 66.147 21.027 7.705 35.76 27.546 35.76 50.828 0 22.16-13.347 41.202-32.442 49.525-3.276 1.359-300.852 130.858-300.852 388.021 0 220.463 298.101 231.561 357.87 231.561h13.020c59.725 0 357.87-11.185 357.87-231.561 0-258.474-297.534-386.619-300.505-387.886zM626.775 649.188c10.214 0.479 18.956 6.343 23.493 14.801 2.151 3.658 3.492 8.307 3.492 13.27 0 4.963-1.341 9.612-3.68 13.605-4.658 8.401-13.478 14.154-23.668 14.48l-89.684-0.015v70.822c-0.002 10.383-5.662 19.442-14.065 24.265-4.084 2.469-8.858 3.888-13.963 3.888-5.105 0-9.879-1.419-13.948-3.885-8.418-4.827-14.078-13.887-14.079-24.27v-70.821h-85.678c-14.85-0.854-26.57-13.105-26.57-28.093s11.719-27.239 26.494-28.090l85.709-0.003v-51.73h-87.819c-9.655 0-18.525-7.383-23.375-15.729-2.271-3.867-3.612-8.516-3.612-13.478 0-4.963 1.341-9.612 3.68-13.605 4.737-8.218 13.65-15.601 23.306-15.601h46.225l-44.564-42.423c-5.041-4.903-8.17-11.753-8.17-19.331 0-14.889 12.069-26.957 26.957-26.957 7.547 0 14.369 3.101 19.262 8.098l76.158 74.278 76.153-74.274c4.898-5.002 11.721-8.102 19.266-8.102 14.889 0 26.957 12.069 26.957 26.957 0 7.579-3.127 14.428-8.163 19.325l-44.571 42.43h46.225c14.898 0 26.957 14.331 26.957 29.229s-12.059 29.229-26.957 29.229h-87.819v51.73z"></path>';
|
||||
zib_svgs['money-color'] = '<path d="M 717.83072,306.26253 C 913.76176,53.698405 686.43949,38.616198 634.03788,58.097382 566.71767,-5.5621016 465.02249,-2.2314476 397.70227,62.684887 80.619706,18.695115 293.02338,306.26253 293.02338,306.26253 -5.7838943,488.12881 8.2023,731.26656 20.758795,853.68381 36.299011,1004.5059 242.16866,1014.9386 242.16866,1014.9386 l 586.82979,-2.8287 C 913.16329,1011.7042 998.23837,924.75871 1009.4895,856.7631 1052.1318,500.57163 873.35719,418.18508 717.83072,306.26253 Z m 18.95906,429.65438 c 20.20228,0 36.61275,21.24078 36.61275,41.6646 0,20.42382 -16.41047,40.91048 -36.61275,40.91048 H 554.5963 v 71.82902 c 0,20.41997 -18.83475,37.01425 -39.03703,37.01425 -20.20228,0 -38.78838,-16.59043 -38.78838,-37.01425 V 818.49199 H 294.39091 c -20.20243,0 -36.61274,-22.24626 -36.61274,-42.67008 0,-20.42381 16.40961,-39.96784 36.61274,-39.96784 H 476.83305 V 668.98962 H 294.39091 c -20.20227,0 -36.48842,-21.80637 -36.48842,-42.29303 0,-20.48666 16.22276,-40.3449 36.48842,-40.3449 H 446.93367 L 338.64945,487.8146 c -15.03632,-13.68384 -16.23376,-37.10696 -2.67292,-52.28499 13.53542,-15.20121 36.70445,-16.41179 51.71784,-2.70223 L 516.11871,549.77733 647.15382,432.63886 c 15.15186,-13.5679 38.31859,-12.13225 51.71783,3.20497 13.42074,15.31802 12.00066,38.7388 -3.1702,52.28498 l -110.02472,98.34856 h 151.23738 c 20.20237,0 36.61274,19.7954 36.61274,40.28206 0,20.42382 -16.41047,42.35587 -36.61274,42.35587 h -182.1935 v 66.86445 h 182.06917 z" fill="#fc7032" /><path d="M 760.9082,243.16863 C 772.28363,194.6542 778.93485,144.38017 780.55103,92.786459 746.11391,47.288466 662.88052,47.414151 633.72707,58.223067 566.40686,-5.4364166 464.71168,-2.1057625 397.39147,62.810572 80.308903,18.820801 292.71258,306.38822 292.71258,306.38822 17.899395,473.61219 7.6428522,692.68125 17.58859,822.01118 c 6.091766,0.12568 12.24569,0.25136 18.399615,0.25136 78.198365,0 153.537335,-9.30069 224.338555,-31.86115 -1.86482,-4.46182 -2.54859,-8.9865 -2.54859,-14.07673 0,-20.42382 16.09967,-40.28207 36.30194,-40.28207 h 88.26843 c 33.69118,-17.91012 63.77704,-29.85019 94.1737,-52.59919 V 669.17814 H 294.08011 c -20.20237,0 -36.48842,-21.80636 -36.48842,-42.29301 0,-20.42383 16.22275,-40.34492 36.48842,-40.34492 H 446.62287 L 338.33865,487.94029 c -15.03633,-13.68385 -16.23377,-37.10696 -2.67291,-52.285 13.5354,-15.20121 36.70444,-16.41178 51.71783,-2.70222 L 515.80791,549.90302 646.84302,432.76454 c 12.43217,-11.12313 30.27233,-12.00292 43.63691,-3.45634 18.70746,-34.73118 34.69041,-70.89284 47.80172,-108.15199 -6.89986,-4.83887 -13.86188,-9.74059 -20.69957,-14.64231 17.77801,-23.12606 32.07501,-44.11546 43.32612,-63.34527 z" fill="#ff9552" />';
|
||||
zib_svgs['order-color'] = '<path d="M 702.98231,186.42345 H 327.31182 c -15.78609,0 -28.63225,-12.92529 -28.63225,-28.80859 V 32.413259 c 0,-15.883302 12.84616,-28.8085861 28.63225,-28.8085861 h 375.67049 c 15.78609,0 28.63226,12.9252811 28.63226,28.8085861 V 157.61486 c 0,15.94758 -12.84617,28.80859 -28.63226,28.80859 z" fill="#8486f8" /><path d="m 834.89519,97.747017 h -31.63608 v 97.614803 c 0,32.21675 -25.94798,58.32453 -57.96753,58.32453 H 285.00256 c -32.01955,0 -57.96754,-26.10778 -57.96754,-58.32453 V 97.747017 h -31.63607 c -70.62196,0 -127.82256,57.552863 -127.82256,128.609763 v 663.04761 c 0,71.05689 57.2006,128.60971 127.82256,128.60971 h 639.49624 c 70.62197,0 127.82255,-57.55283 127.82255,-128.60971 V 226.35678 c 0,-71.0569 -57.20058,-128.609763 -127.82255,-128.609763 z M 735.89663,746.58325 H 294.39752 c -28.44052,0 -51.44858,-23.14976 -51.44858,-51.76543 0,-28.61567 23.00806,-51.76542 51.44858,-51.76542 h 441.49911 c 28.44051,0 51.44857,23.14975 51.44857,51.76542 0,28.55137 -23.07197,51.76543 -51.44857,51.76543 z m 0,-203.52494 H 294.39752 c -28.44052,0 -51.44858,-23.14976 -51.44858,-51.76543 0,-28.61567 23.00806,-51.76543 51.44858,-51.76543 h 441.49911 c 28.44051,0 51.44857,23.14976 51.44857,51.76543 0,28.61567 -23.07197,51.76543 -51.44857,51.76543 z" fill="#6c6cea" /><path d="m 962.71774,226.35678 c 0,-71.0569 -57.20058,-128.609763 -127.82255,-128.609763 h -31.63608 v 97.614803 c 0,32.21675 -25.94798,58.32453 -57.96753,58.32453 H 285.00256 c -32.01955,0 -57.96754,-26.10778 -57.96754,-58.32453 V 97.747017 h -31.63607 c -70.62196,0 -127.82256,57.552863 -127.82256,128.609763 v 663.04761 c 0,71.05689 57.2006,128.60971 127.82256,128.60971 H 446.1868 C 710.58775,935.06085 912.41957,709.47934 962.71774,430.71768 Z M 735.89663,746.58325 H 294.39752 c -28.44052,0 -51.44858,-23.14976 -51.44858,-51.76543 0,-28.61567 23.00806,-51.76542 51.44858,-51.76542 h 441.49911 c 28.44051,0 51.44857,23.14975 51.44857,51.76542 0,28.55137 -23.07197,51.76543 -51.44857,51.76543 z m 0,-203.52494 H 294.39752 c -28.44052,0 -51.44858,-23.14976 -51.44858,-51.76543 0,-28.61567 23.00806,-51.76543 51.44858,-51.76543 h 441.49911 c 28.44051,0 51.44857,23.14976 51.44857,51.76543 0,28.61567 -23.07197,51.76543 -51.44857,51.76543 z" fill="#757bf2" /><path d="m 268.32172,739.3811 c -15.69769,-9.28354 -25.32929,-26.24265 -25.30888,-44.56328 0,-28.61567 23.00807,-51.76542 51.44858,-51.76542 h 157.60522 c 41.09495,-29.45164 79.12216,-63.01879 113.57034,-99.99409 H 294.39752 c -28.44052,0 -51.44858,-23.14976 -51.44858,-51.76543 0,-28.61567 23.00806,-51.76543 51.44858,-51.76543 h 351.9594 c 37.13245,-57.10273 66.78729,-119.47846 87.62236,-185.90541 H 285.00256 c -32.01955,0 -57.96754,-26.10778 -57.96754,-58.32452 V 97.747017 h -31.63607 c -70.62196,0 -127.82256,57.552863 -127.82256,128.609763 v 554.8868 c 69.98285,-4.75856 137.34534,-19.16285 200.74533,-41.86248 z" fill="#8486f8" /><path d="M 538.66642,3.6046729 H 337.02634 c -21.15463,0 -38.28286,17.2337081 -38.28286,38.5186231 V 147.84052 c 0,21.2849 17.12823,38.51862 38.28286,38.51862 H 446.95373 C 485.23659,130.4782 516.29747,69.06704 538.66642,3.6046729 Z" fill="#8d92f8" />';
|
||||
zib_svgs['user-color'] = '<path d="M 776.46153,309.90478 H 977.5329 c 25.6088,0 46.3426,-21.46588 46.3426,-47.9788 0,-26.51292 -20.7338,-47.97881 -46.3426,-47.97881 H 776.46153 c -25.60875,0 -46.34258,21.46589 -46.34258,47.97881 0,26.51292 20.79554,47.9788 46.34258,47.9788 z M 977.59461,458.88824 H 812.00525 c -25.60875,0 -46.34259,21.46589 -46.34259,47.97881 0,26.51292 20.73384,47.9788 46.34259,47.9788 h 165.58936 c 25.60879,0 46.34259,-21.46588 46.34259,-47.9788 -0.062,-26.51292 -20.7955,-47.97881 -46.34259,-47.97881 z m 0,260.72105 h -53.21939 c -25.60875,0 -46.34259,21.46588 -46.34259,47.97881 0,26.51292 20.73384,47.97881 46.34259,47.97881 h 53.21939 c 25.60879,0 46.34259,-21.46589 46.34259,-47.97881 -0.062,-26.51293 -20.7955,-47.97881 -46.34259,-47.97881 z M 571.4064,479.77915 c 52.20483,-43.44286 85.71218,-110.01266 85.71218,-184.56827 0,-130.52025 -102.55842,-236.699708 -228.62753,-236.699708 -126.0691,0 -228.62752,106.179458 -228.62752,236.699708 0,74.55561 33.50735,141.12541 85.71217,184.56827 C 122.04994,533.50775 3.2006527,692.07419 3.2006527,878.94237 c 0,52.57864 41.2825423,95.31875 92.0680903,95.31875 H 761.83677 c 50.78556,0 92.06809,-42.74011 92.06809,-95.31875 C 853.78146,692.07419 734.93217,533.44386 571.4064,479.77915 Z m 12.83523,371.05313 H 272.74047 c -25.60875,0 -46.34258,-21.46588 -46.34258,-47.9788 0,-26.51293 20.73383,-47.97881 46.34258,-47.97881 h 311.50116 c 25.60876,0 46.34259,21.46588 46.34259,47.97881 0,26.51292 -20.79554,47.9788 -46.34259,47.9788 z" fill="#2595E8" /><path d="m 866.7401,213.94717 h -90.27856 c -25.60875,0 -46.34259,21.46589 -46.34259,47.97881 0,26.51292 20.73384,47.9788 46.34259,47.9788 h 100.39864 c -1.11074,-32.64603 -4.56638,-64.6532 -10.12008,-95.95761 z m -54.79656,244.94107 c -25.60875,0 -46.34258,21.46589 -46.34258,47.97881 0,26.51292 20.73383,47.9788 46.34258,47.9788 h 29.61976 c 10.42863,-30.98498 18.69748,-63.05603 24.68314,-95.95761 z M 571.4064,479.77915 c 52.20483,-43.44286 85.71218,-110.01266 85.71218,-184.56827 0,-130.52025 -102.55842,-236.699708 -228.62753,-236.699708 -126.0691,0 -228.62753,106.179458 -228.62753,236.699708 0,74.55561 33.50736,141.12541 85.71219,184.56827 C 122.04994,533.50775 3.2006527,692.07418 3.2006527,878.94237 c 0,52.57864 41.2825423,95.31875 92.0680903,95.31875 H 418.98805 C 579.92208,924.11017 714.19833,810.71152 795.0973,661.85585 744.62029,576.18397 665.44914,510.63636 571.4064,479.77915 Z m 12.83523,371.05313 H 272.74048 c -25.60875,0 -46.34259,-21.46588 -46.34259,-47.9788 0,-26.51292 20.73384,-47.9788 46.34259,-47.9788 h 311.50115 c 25.60875,0 46.34258,21.46588 46.34258,47.9788 0,26.44903 -20.79554,47.9788 -46.34258,47.9788 z" fill="#3A9CED" /><path d="m 18.627612,764.266 c 12.588398,0.76664 25.238504,1.27773 38.012026,1.27773 217.211582,0 409.184652,-111.35427 525.997592,-281.80362 -3.70247,-1.34161 -7.40494,-2.68323 -11.16912,-3.89708 15.98233,-13.28839 30.23684,-28.81283 42.26987,-46.0622 11.66278,-20.69925 22.21482,-42.03736 31.71782,-64.07822 7.52836,-23.38248 11.66278,-48.42601 11.66278,-74.42785 0,-130.52024 -102.55842,-236.699701 -228.62753,-236.699701 -126.0691,0 -228.62753,106.179461 -228.62753,236.699701 0,74.55562 33.50736,141.12542 85.71219,184.56827 C 156.79145,522.00817 55.775728,629.33759 18.627612,764.266 Z" fill="#59adf8" /><path d="m 506.11951,72.566216 c -24.25118,-9.071892 -50.4153,-14.055044 -77.62846,-14.055044 -126.0691,0 -228.62753,106.179458 -228.62753,236.699708 0,48.4899 14.25451,93.59381 38.50569,131.15911 124.64983,-81.64703 220.35868,-206.22583 267.7503,-353.803774 z" fill="#6bc2fc" />';
|
||||
zib_svgs['user-color-2'] = '<path d="m 663.80596,435.43096 c 54.78277,-44.03343 89.94476,-111.50819 89.94476,-187.07733 0,-132.29455 -107.62289,-239.2698887 -239.91744,-239.2698887 -132.29456,0 -239.91745,106.9753387 -239.91745,239.2698887 0,75.56914 35.16199,143.0439 89.94476,187.07733 -171.60087,54.45899 -296.319087,215.18102 -296.319087,404.58952 0,53.29341 48.999157,125.97022 103.952207,155.31599 102.83616,54.91613 233.16134,0 349.742,0 116.58067,0 248.83587,58.38663 349.742,0 C 922.66429,965.4294 960.25456,893.31389 960.25456,840.02048 960.12505,650.61198 835.40683,489.8252 663.80596,435.43096 Z m 13.46905,376.0973 H 350.39154 c -26.87334,0 -48.63104,-21.75769 -48.63104,-48.63103 0,-26.87335 21.7577,-48.63104 48.63104,-48.63104 h 326.88347 c 26.87334,0 48.63104,21.75769 48.63104,48.63104 0,26.87334 -21.82245,48.63103 -48.63104,48.63103 z" fill="#2595E8" /><path d="m 663.80596,435.43096 c 54.78277,-44.03343 89.94476,-111.50819 89.94476,-187.07733 0,-132.29455 -107.62289,-239.9174391 -239.91744,-239.9174391 -132.29456,0 -239.91745,107.6228891 -239.91745,239.9174391 0,75.56914 35.16199,143.0439 89.94476,187.07733 -171.60087,54.45899 -296.319087,215.18102 -296.319087,404.58952 0,53.29341 34.441907,77.78436 96.614527,96.61453 191.55794,58.017 339.70497,0 339.70497,0 176.36556,0 309.78814,-165.77291 394.682,-316.65217 C 845.57337,533.14632 762.49265,466.70765 663.80596,435.43096 Z m 13.46905,376.0973 H 350.39154 c -26.87334,0 -48.63104,-21.75769 -48.63104,-48.63103 0,-26.87335 21.7577,-48.63104 48.63104,-48.63104 h 326.88347 c 26.87334,0 48.63104,21.75769 48.63104,48.63104 0,26.80858 -21.82245,48.63103 -48.63104,48.63103 z" fill="#3a9ced" /><path d="m 83.730264,723.78518 c 13.210029,0.77706 26.484816,1.2951 39.889106,1.2951 227.93776,0 429.39071,-112.86805 551.97201,-285.63451 -3.8853,-1.35985 -7.77061,-2.71971 -11.72066,-3.95005 16.77155,-13.46905 31.72997,-29.20453 44.3572,-46.68839 12.23871,-20.98064 23.31182,-42.60882 33.2841,-64.94931 7.90011,-23.70035 12.2387,-49.08433 12.2387,-75.43963 0,-132.29456 -107.62289,-239.9174441 -239.91744,-239.9174441 -132.29456,0 -239.91745,107.6228841 -239.91745,239.9174441 0,75.56914 35.16199,143.04389 89.94476,187.07733 C 228.71681,478.23405 122.7128,587.02252 83.730264,723.78518 Z" fill="#59ADF8" /><path d="M 595.29512,22.682301 C 569.84639,13.487084 542.39025,8.4361909 513.83328,8.4361909 c -132.29456,0 -239.91745,107.6228891 -239.91745,239.9174391 0,49.14908 14.95842,94.86615 40.40715,132.94211 C 445.12817,298.53879 545.56325,172.26646 595.29512,22.682301 Z" fill="#6BC2FC" />';
|
||||
zib_svgs['gift-color'] = '<path d="M 960.50258,200.79974 H 618.15627 L 726.18827,95.952356 C 746.22761,76.534996 746.69414,44.536769 727.2294,24.543448 707.81203,4.5041121 675.81381,4.0375857 655.82049,23.502323 L 506.14349,168.76984 371.28722,25.094632 C 352.17952,4.7620784 320.21087,3.7209536 299.87831,22.828655 c -20.33255,19.1077 -21.37367,51.076354 -2.26597,71.408907 L 397.62156,200.79974 H 65.012828 c -33.98966,0 -61.4876019,27.55918 -61.4876019,61.4876 V 406.0238 c 0,33.98966 27.5591839,61.4876 61.4876019,61.4876 h 46.973092 v 411.79544 c 0,77.83939 63.07991,140.98056 140.98054,140.98056 h 519.58248 c 77.83939,0 140.98054,-63.07993 140.98054,-140.98056 V 467.5114 h 46.9731 c 33.98966,0 61.48762,-27.55919 61.48762,-61.4876 V 262.28734 c 0,-33.98966 -27.49796,-61.4876 -61.48762,-61.4876 z m -397.2197,590.07274 c 0,27.92665 -22.59854,50.52518 -50.52517,50.52518 -27.92665,0 -50.52518,-22.59853 -50.52518,-50.52518 V 622.27152 c 0,-27.92663 22.59853,-50.52517 50.52518,-50.52517 27.92663,0 50.52517,22.59854 50.52517,50.52517 z" fill="#ff3369" /><path d="M 958.35908,200.79974 H 618.15627 L 726.18827,95.952356 C 746.22761,76.534996 746.69414,44.536769 727.2294,24.543448 707.81548,4.5171078 675.78558,4.0271668 655.82049,23.502323 L 506.14349,168.76984 371.28722,25.094632 C 352.17952,4.7620784 320.21087,3.7209536 299.87831,22.828655 c -20.33255,19.1077 -21.37367,51.076354 -2.26597,71.408907 L 397.62156,200.79974 H 65.012828 c -33.98966,0 -61.4876019,27.55918 -61.4876019,61.4876 V 406.0238 c 0,33.98966 27.5591839,61.4876 61.4876019,61.4876 h 46.973092 v 411.79544 c 0,77.83939 63.07991,140.98056 140.98054,140.98056 H 364.97923 C 617.91129,965.2915 823.74778,784.31952 913.52948,546.33066 V 467.5114 h 25.04824 c 15.81643,-61.79387 23.79976,-125.33136 23.76214,-189.11725 -0.0613,-26.21184 -1.34735,-52.11748 -3.98078,-77.59441 z m -395.0762,590.07274 c 0,27.92665 -22.59854,50.52518 -50.52517,50.52518 -27.92665,0 -50.52518,-22.59853 -50.52518,-50.52518 V 622.27152 c 0,-27.92663 22.59853,-50.52517 50.52518,-50.52517 27.92663,0 50.52517,22.59854 50.52517,50.52517 z" fill="#ff4d7c" /><path d="M 618.15627,200.79974 726.18827,95.952356 C 746.22761,76.534996 746.69414,44.536769 727.2294,24.543448 707.81548,4.5171078 675.78558,4.0271668 655.82049,23.502323 L 506.14349,168.76984 371.28722,25.094632 C 352.17952,4.7620784 320.21087,3.7209536 299.87831,22.828655 c -20.33255,19.1077 -21.37367,51.076354 -2.26597,71.408907 L 397.62156,200.79974 H 65.012828 c -33.98966,0 -61.4876019,27.55918 -61.4876019,61.4876 V 406.0238 c 0,33.98966 27.5591839,61.4876 61.4876019,61.4876 h 46.973092 v 291.6374 c 132.22284,-20.39379 253.05456,-75.08346 353.43123,-154.39266 6.12426,-16.47428 20.57752,-28.84528 38.2154,-32.09115 C 611.97076,474.92175 692.01489,346.37347 729.98531,200.86098 H 618.15627 Z" fill="#ff5f89" />';
|
||||
zib_svgs['security-color'] = '<path d="M 919.69915,164.38967 549.01842,10.797004 C 529.75915,2.7923704 508.21285,2.5516296 488.71284,10.014596 L 106.05526,157.04707 c -31.401937,12.07822 -52.12183,42.24887 -52.120399,75.89355 v 293.4631 c 0,113.9908 83.657449,321.1483 411.125189,483.46778 21.30557,10.5325 46.28243,11.1945 68.06948,1.625 332.16219,-145.76855 436.7039,-381.45384 436.7039,-499.35667 V 239.50081 c 0,-32.86112 -19.80093,-62.53243 -50.13428,-75.11114 z M 554.43509,497.09352 v 234.66215 c 0,23.47223 -19.07871,42.55095 -42.55094,42.55095 -23.47224,0 -42.55095,-19.07872 -42.55095,-42.55095 V 497.09352 c -44.53706,-17.15278 -76.25466,-60.24539 -76.25466,-110.80097 0,-65.60188 53.20372,-118.80561 118.80561,-118.80561 65.60188,0 118.80561,53.20373 118.80561,118.80561 0,50.55558 -31.65742,93.64819 -76.25467,110.80097 z" fill="#6c6cea" /><path d="m 897.00932,251.41749 c 0,-33.64354 -2.34722,-66.74541 -6.86111,-99.18524 L 548.95824,10.857189 C 529.69897,2.8525556 508.15266,2.6118148 488.65265,10.074781 L 106.05526,157.04707 c -31.401937,12.07822 -52.12183,42.24887 -52.120399,75.89355 v 293.4631 c 0,100.02783 64.458359,271.79642 301.527919,422.0789 C 666.7407,869.33907 897.00932,587.25097 897.00932,251.41749 Z M 554.43509,497.09352 v 234.66215 c 0,23.47223 -19.07871,42.55095 -42.55094,42.55095 -23.47224,0 -42.55095,-19.07872 -42.55095,-42.55095 V 497.09352 c -44.59724,-17.15278 -76.25466,-60.24539 -76.25466,-110.80097 0,-65.60188 53.20372,-118.80561 118.80561,-118.80561 65.60188,0 118.80561,53.20373 118.80561,118.80561 0,50.55558 -31.65742,93.64819 -76.25467,110.80097 z" fill="#757bf2" /><path d="M 548.95824,10.797004 C 529.69897,2.7923704 508.15266,2.5516296 488.65265,10.014596 L 106.05526,157.04707 c -31.401937,12.07822 -52.12183,42.24887 -52.120399,75.89355 v 293.4631 c 0,46.76391 14.143525,109.17598 53.324099,177.72694 138.42599,-24.49538 263.12975,-88.59264 362.07424,-180.13435 v -26.90279 c -44.59724,-17.15278 -76.25466,-60.24539 -76.25466,-110.80097 0,-65.60188 53.20372,-118.80561 118.80561,-118.80561 45.86113,0 85.58337,26.06019 105.3843,64.15743 41.76854,-79.02318 69.27318,-166.71304 79.02319,-259.759375 z" fill="#8486f8" />';
|
||||
zib_svgs['trend-color'] = '<path d="M 904.33245,30.216169 H 122.79236 C 57.093827,30.216169 3.8689304,83.441066 3.8689304,149.1396 v 547.93184 c 0,65.69854 53.2248966,118.92343 118.9234296,118.92343 h 781.54009 c 65.69854,0 118.92345,-53.22489 118.92345,-118.92343 V 149.1396 c 0,-65.698534 -53.22491,-118.923431 -118.92345,-118.923431 z M 774.93359,370.39531 629.48853,504.21445 c -22.283,20.52701 -56.55523,20.46646 -78.83824,-0.0605 L 455.64476,416.65677 331.57444,533.4609 c -10.79251,10.17425 -25.07137,15.82946 -39.90354,15.80398 -16.05162,0.0381 -31.39994,-6.58364 -42.38615,-18.2866 -22.0408,-23.43349 -20.95087,-60.24889 2.48262,-82.28969 L 415.31736,294.70576 c 22.25031,-20.94998 56.91046,-21.13504 79.38321,-0.42386 l 95.42939,87.92099 106.02593,-97.48815 c 23.6757,-21.7986 60.4911,-20.22425 82.28969,3.45144 21.67749,23.61514 20.1637,60.43054 -3.51199,82.22913 z m 7.81116,504.15301 H 244.38007 c -32.15293,0 -58.25069,26.0372 -58.25069,58.25068 0,32.15292 26.03721,58.25068 58.25069,58.25068 h 538.36468 c 32.15292,0 58.25068,-26.03721 58.25068,-58.25068 0,-32.15292 -26.09776,-58.25068 -58.25068,-58.25068 z" fill="#6C6CEA" /><path fill="#757bf2" d="M 904.33245,30.216169 H 122.79236 C 57.093827,30.216169 3.8689304,83.441066 3.8689304,149.1396 v 547.93184 c 0,65.69854 53.2248966,118.92343 118.9234296,118.92343 H 663.57911 C 877.87138,678.36098 1019.8044,437.97095 1019.8044,164.39862 c 0,-16.71226 -0.6055,-33.24286 -1.6349,-49.65235 C 1003.3949,65.820537 958.04176,30.216169 904.33245,30.216169 Z M 774.93359,370.39531 629.48853,504.21445 c -22.283,20.52701 -56.55523,20.46646 -78.83824,-0.0605 L 455.64476,416.65677 331.57444,533.4609 c -10.79251,10.17425 -25.07137,15.82946 -39.90354,15.80398 -16.05162,0.0381 -31.39994,-6.58364 -42.38615,-18.2866 -22.0408,-23.43349 -20.95087,-60.24889 2.48262,-82.28969 L 415.31736,294.70576 c 22.25031,-20.94998 56.91046,-21.13504 79.38321,-0.42386 l 95.42939,87.92099 106.02593,-97.48815 c 23.6757,-21.7986 60.4911,-20.22425 82.28969,3.45144 21.67749,23.61514 20.1637,60.43054 -3.51199,82.22913 z M 553.73842,874.54832 H 244.38007 c -32.15293,0 -58.25069,26.0372 -58.25069,58.25068 0,1.08993 0.12111,2.11931 0.18166,3.20924 19.67928,1.51379 39.54022,2.24041 59.58282,2.24041 109.41682,0 213.5051,-22.70687 307.84456,-63.70033 z" id="path2136" /><path d="M 122.79236,30.216169 C 57.093827,30.216169 3.8689304,83.441066 3.8689304,149.1396 v 513.65961 c 10.0515736,0.36331 20.1636976,0.66607 30.2758226,0.66607 188.255067,0 360.827257,-67.27288 494.949147,-178.99067 L 455.64476,416.65677 331.57444,533.4609 c -10.79251,10.17425 -25.07137,15.82946 -39.90354,15.80398 -16.05162,0.0381 -31.39994,-6.58364 -42.38615,-18.2866 -22.0408,-23.43349 -20.95087,-60.24889 2.48262,-82.28969 L 415.31736,294.70576 c 22.25031,-20.94998 56.91046,-21.13504 79.38321,-0.42386 l 95.42939,87.92099 106.02593,-97.48815 c 2.11931,-1.93766 4.35972,-3.6331 6.66069,-5.20745 44.3238,-75.81066 76.11341,-159.85634 92.52291,-249.230569 H 122.79236 Z" fill="#8486f8" />';
|
||||
zib_svgs['msg-color'] = '<path d="M 568.39536,1021.6475 H 459.38412 c -41.47503,0 -75.02647,-33.61333 -75.02647,-75.02646 0,-41.47503 33.61334,-75.02647 75.02647,-75.02647 h 109.01124 c 41.47503,0 75.02648,33.61334 75.02648,75.02647 0,41.41313 -33.61335,75.02646 -75.02648,75.02646 z M 875.62011,579.78367 H 844.73049 V 332.23345 C 844.73049,149.4957 696.59654,1.3617451 513.85879,1.3617451 331.12104,1.3617451 182.98708,149.4957 182.98708,332.23345 v 247.48832 h -30.88961 c -68.588557,0 -124.17748,55.58892 -124.17748,124.17748 0,68.58856 55.588923,124.17748 124.17748,124.17748 h 723.52264 c 68.58856,0 124.17748,-55.58892 124.17748,-124.17748 0.0619,-68.52665 -55.58892,-124.11558 -124.17748,-124.11558 z M 386.02903,512.06176 c 0,28.4787 -23.08654,51.5652 -51.56523,51.5652 -28.47868,0 -51.56522,-23.0865 -51.56522,-51.5652 V 301.59145 c 0,-28.47871 23.08654,-51.5652 51.56522,-51.5652 28.47869,0 51.56523,23.08649 51.56523,51.5652 z" fill="#fc7032" /><path d="M 844.73049,579.78367 V 332.23345 C 844.73049,149.4957 696.59654,1.3617451 513.85879,1.3617451 331.12104,1.3617451 182.98708,149.4957 182.98708,332.23345 v 247.48832 h -30.88961 c -68.588557,0 -124.17748,55.58892 -124.17748,124.17748 0,68.58856 55.588923,124.17748 124.17748,124.17748 H 625.34615 C 726.86712,767.90699 811.36476,682.17129 870.04883,579.65987 H 844.73049 Z M 386.02903,512.06176 c 0,28.4787 -23.08654,51.5652 -51.56523,51.5652 -28.47868,0 -51.56522,-23.0865 -51.56522,-51.5652 V 301.59145 c 0,-28.47871 23.08654,-51.5652 51.56522,-51.5652 28.47869,0 51.56523,23.08649 51.56523,51.5652 z m 152.65288,359.4709 h -79.29779 c -29.58965,0 -55.0937,17.14714 -67.28859,42.03216 50.94619,-8.60452 100.0972,-22.84222 146.58638,-42.03216 z" fill="#ff7e3e" /><path d="m 30.581821,678.3333 c 20.304194,1.79519 40.856,2.78564 61.655419,2.78564 336.8763,0 616.5542,-244.57888 671.33838,-565.85562 C 702.91065,45.498607 613.58457,1.3617451 513.92069,1.3617451 331.18294,1.3617451 183.04899,149.4957 183.04899,332.23345 V 579.72177 H 152.15937 C 92.299143,579.78367 42.4053,622.00154 30.581821,678.3333 Z M 282.83668,301.59145 c 0,-28.47871 23.08653,-51.5652 51.56522,-51.5652 28.47869,0 51.56523,23.08649 51.56523,51.5652 v 210.47031 c 0,28.4787 -23.08654,51.5652 -51.56523,51.5652 -28.47869,0 -51.56522,-23.0865 -51.56522,-51.5652 z" fill="#ff9552" />';
|
||||
zib_svgs['shop-color'] = '<path d="m 137.60557,184.57537 c -24.32046,0 -47.499951,-1.20101 -70.499293,0.2402 -40.113736,2.52212 -75.123179,-45.99869 -55.546715,-91.036564 7.626414,-17.594797 23.359645,-26.001868 42.035352,-26.362171 38.31222,-0.660555 76.684496,-0.900757 114.936666,0.180152 32.00691,0.900757 49.90196,15.072676 57.94873,46.298933 4.50379,17.41465 5.04424,35.7901 7.32616,53.7452 2.04172,16.03349 3.90328,32.12702 5.945,48.82106 h 712.07886 c 18.1953,0 35.60995,3.00253 50.62257,14.05182 17.5348,12.91086 22.2787,33.74838 13.3312,59.75025 -12.1302,35.48985 -24.98099,70.79954 -37.05114,106.34944 -13.87167,40.89439 -26.36217,82.32924 -41.1346,122.92338 -14.17192,38.97278 -40.53409,60.2907 -83.65035,60.11055 -173.42585,-0.78065 -346.8517,-0.3603 -520.27755,-0.3603 h -15.49303 c 4.80404,29.00439 9.72818,56.98793 13.93171,85.03151 1.26106,8.40707 6.60556,7.68646 12.37041,7.68646 h 190.11989 c 102.08585,0 204.17171,-0.06 306.25756,0.12011 10.14854,0 20.53727,0.7206 30.50566,2.58217 14.95257,2.88242 23.96015,12.91086 26.30212,27.80338 4.74399,29.78505 -8.22692,59.99045 -47.9203,59.87035 -176.42838,-0.66055 -352.91681,-0.96081 -529.34518,0.18015 -45.87859,0.30026 -70.49929,-26.96267 -80.76793,-67.43671 C 223.29763,630.57045 211.94809,564.7551 199.03723,499.3601 179.28062,398.95566 160.0044,298.37107 140.48799,197.90658 c -0.78066,-3.96334 -1.74146,-7.98672 -2.88242,-13.33121 z m 638.63709,797.59077 c -43.35646,1.98167 -98.78308,-45.87858 -96.56121,-93.67878 2.46207,-53.98541 38.13207,-95.30015 93.97904,-96.14086 55.48666,-0.84071 98.48282,39.99364 99.50368,93.19838 1.02086,51.34318 -44.91777,96.44111 -96.92151,96.62126 z m -429.54124,-4.26359 c -52.24394,0.0601 -94.7597,-41.37479 -95.18005,-92.77802 -0.42035,-49.72182 42.57581,-93.73884 91.87727,-94.15919 54.2256,-0.42035 99.08333,41.79515 98.96323,93.13833 -0.1201,51.88363 -42.81601,93.73883 -95.66045,93.79888 z" fill="#fc7032" /><path d="m 257.34627,216.52223 h -17.65485 c -2.04172,-16.69404 -3.96333,-32.78757 -5.945,-48.82106 -2.28192,-17.9551 -2.82237,-36.33055 -7.32616,-53.7452 C 218.37349,82.729713 200.53849,68.557795 168.47152,67.657037 130.1593,66.576128 91.847084,66.81633 53.534863,67.476886 34.859157,67.777138 19.125925,76.244259 11.499511,93.839056 -8.016902,138.93698 26.93249,187.39774 67.046226,184.87562 c 22.999343,-1.44121 46.178834,-0.2402 70.499294,-0.2402 1.14096,5.34449 2.10176,9.36787 2.88242,13.45131 19.51641,100.46449 38.79262,200.98903 58.54924,301.45352 12.85081,65.395 24.20035,131.21035 40.59414,195.76464 10.26864,40.47404 34.82929,67.73697 80.76793,67.43671 112.77484,-0.7206 225.48963,-0.8407 338.26448,-0.66055 35.06949,-26.96268 67.61686,-57.04798 97.22176,-89.83555 -73.74202,-0.0601 -147.54408,-0.0601 -221.2861,-0.0601 H 344.4195 c -5.76485,0 -11.10935,0.78065 -12.37041,-7.68647 -4.20353,-28.04358 -9.12767,-55.96707 -13.93171,-85.03151 h 15.49303 c 164.35822,0 328.71645,-0.42035 493.07467,0.2402 68.09727,-105.38863 109.53212,-229.63312 114.87661,-363.12539 -228.01175,-0.06 -456.08356,-0.06 -684.21542,-0.06 z m 86.05237,574.44311 c -49.30146,0.42035 -92.29762,44.43737 -91.87727,94.15919 0.0601,8.88747 1.50126,17.47469 3.90328,25.64156 64.79449,-3.36283 127.30707,-15.25282 186.51686,-34.52904 -4.20353,-47.68009 -47.13964,-85.69206 -98.54287,-85.27171 z" fill="#ff7c33" /><path d="m 239.75147,216.52223 c -2.04172,-16.69404 -3.96333,-32.78757 -5.945,-48.82106 -2.28192,-17.9551 -2.82237,-36.33055 -7.32616,-53.7452 C 218.43354,82.729713 200.59854,68.557795 168.53158,67.657037 130.21935,66.576128 91.907134,66.81633 53.594914,67.476886 34.919207,67.777138 19.185976,76.244259 11.559562,93.839056 -7.9568515,138.93698 26.992541,187.39774 67.106277,184.87562 c 22.999342,-1.44121 46.178833,-0.2402 70.499293,-0.2402 1.14096,5.34449 2.10176,9.36787 2.88242,13.45131 19.51641,100.46449 38.79263,200.98903 58.54924,301.45352 8.22692,41.8552 15.85333,83.8305 24.56066,125.5656 32.87884,-9.64671 65.02744,-21.62718 96.2009,-35.85015 -0.54045,-3.30278 -1.08091,-6.48545 -1.62136,-9.78823 h 22.09858 C 493.82515,503.38348 616.62843,374.57516 684.78575,216.58228 H 257.28622 c -5.16434,-0.06 -10.44879,-0.06 -17.53475,-0.06 z" fill="#ff8d4d" /><path d="m 257.34627,216.52223 h -17.65485 c -2.04172,-16.69404 -3.96333,-32.78757 -5.945,-48.82106 -2.28192,-17.9551 -2.82237,-36.33055 -7.32616,-53.7452 C 218.37349,82.729713 200.53849,68.557795 168.47152,67.657037 130.1593,66.576128 91.847084,66.81633 53.534863,67.476886 34.859157,67.777138 19.125925,76.244259 11.499511,93.839056 -8.016902,138.93698 26.93249,187.39774 67.046226,184.87562 c 22.999343,-1.44121 46.178834,-0.2402 70.499294,-0.2402 1.14096,5.34449 2.10176,9.36787 2.88242,13.45131 l 23.59985,121.78242 c 55.12636,-27.98354 106.22934,-62.75278 152.10792,-103.28687 -19.57646,-0.06 -39.15293,-0.06 -58.78944,-0.06 z" fill="#ffa56a" />';
|
||||
zib_svgs['home-color'] = '<path d="M 1006.2514,425.49937 551.5932,63.42086 C 528.86313,45.308141 497.09785,45.308141 474.36778,63.479476 L 20.391461,425.49937 c -29.6627416,20.7505 -15.4564478,68.58214 20.400238,68.58214 H 133.92816 V 905.1054 c 0,41.14928 52.27913,74.50247 72.2248,74.50247 0,0 52.46333,7.94426 76.79922,0 37.5989,-12.27387 70.20152,-70.00748 95.80126,-70.00748 h 76.79922 76.79922 76.79923 76.79922 c 25.59974,0 32.531,58.10265 57.7972,70.00748 25.2662,11.90483 76.79922,0 76.79922,0 19.94564,0 72.2248,-33.35319 72.2248,-74.50247 V 494.08151 h 93.19328 c 35.74347,0 49.94937,-47.83164 20.28657,-68.58214 z M 673.36955,658.62954 c 24.1507,0 43.69856,20.16432 43.69856,45.07662 0,24.91232 -19.54786,45.07665 -43.69856,45.07665 -181.89773,1.13067 -121.82819,0 -316.85718,0 -24.15074,0 -43.69856,-20.16433 -43.69856,-45.07665 0,-24.9123 19.54786,-45.07662 43.69856,-45.07662 189.23552,-1.02371 4.40318,0.11724 316.85718,0.11724 z" fill="#2ed2f2" /><path d="M 474.36778,63.42086 20.391461,425.49937 c -29.6627416,20.7505 -15.4564478,68.58214 20.400238,68.58214 H 133.92816 V 905.1054 c 0,41.14928 57.33572,91.50429 156.23377,68.50183 0,0 61.03326,-54.70147 76.3507,-65.00694 8.89538,-5.98476 153.35892,-1.00011 153.35892,-1.00011 221.55091,-70.34427 372.50222,-255.95561 372.50222,-564.57521 0,-2.81364 -0.17048,-5.56866 -0.2273,-8.38227 L 551.5932,63.42086 c -22.74724,-18.113443 -54.47818,-18.113443 -77.22542,0 z m 199.00177,595.15005 c 24.15078,0 43.69856,20.16433 43.69856,45.07665 0,24.91231 -19.54786,45.07663 -43.69856,45.07663 -179.89752,3.13089 -121.82818,0 -316.85718,0 -24.15125,0 -43.69856,-20.16432 -43.69856,-45.07663 0,-24.91232 19.54786,-45.07665 43.69856,-45.07665 207.25458,0.9602 4.38835,0 316.85718,0 z" fill="#4cd7f2" /><path d="M 474.36778,63.42086 20.391461,425.49937 c -29.6627416,20.7505 -15.4564478,68.58214 20.400238,68.58214 h 93.136461 v 269.053 c 62.67817,-5.09969 122.7992,-33.51953 179.05613,-56.02854 -0.0568,-1.11373 -0.17048,-2.28607 -0.17048,-3.39981 0,-24.9123 19.54565,-45.07662 43.69856,-45.07662 C 553.07296,584.6626 674.91397,384.09552 713.48812,192.49596 L 551.53637,63.538094 C 528.8063,45.308141 497.09785,45.308141 474.36778,63.42086 Z" fill="#60daf2" /><path d="m 535.5685,54.335192 c -20.17294,-7.971941 -43.41444,-5.04108 -61.20072,9.085668 L 20.391461,425.49937 c -29.6627416,20.7505 -15.4564478,68.58214 20.400238,68.58214 h 93.136461 v 2.63778 C 328.61121,426.32001 479.87983,260.90225 535.5685,54.335192 Z" fill="#74e6f8" />';
|
||||
zib_svgs['add-color'] = '<path d="m 132.75454,821.87989 h 762.27705 c 71.02097,6.77839 127.34791,-54.93705 127.34791,-118.50996 l 0,-373.0267 C 1027.6842,259.49724 964.56765,201.93479 899.54336,201.85 603.52363,201.46306 433.38233,201.07891 137.3626,200.69169 66.49123,193.75246 4.5811081,254.4676 4.0885562,317.87001 L 3.890813,694.25518 C 3.8566897,759.20555 67.804167,821.87989 132.75454,821.87989 Z M 663.21747,468.67994 c 25.03862,0.0645 40.74679,18.80225 40.74679,42.03175 0,23.22954 -18.22743,42.03179 -40.74679,42.03179 -27.12309,0 -68.09943,0.15711 -82.35641,0.15711 -14.25697,0 -17.81575,2.53062 -17.81575,16.70032 0,16.45124 -1.18173,75.76021 -1.18173,75.76021 -0.23541,12.81018 -17.7735,28.66366 -40.52453,28.66366 -20.73987,0 -43.93049,-13.84667 -44.20397,-30.66184 l -1.22664,-75.41982 c -0.25727,-15.81807 -8.7481,-15.10147 -16.10808,-15.10147 -13.5192,0 -58.5187,-0.0972 -92.03683,-0.0982 -22.51939,0 -40.74679,-18.80225 -40.74679,-42.03179 0,-23.2295 18.22743,-42.03175 40.74679,-42.03175 0.83475,0 1.88552,10e-5 3.13862,3.1e-4 32.14879,0.0101 62.55932,0.0185 94.50761,0.0347 7.52081,0.003 10.55106,-4.53477 10.5534,-10.40981 0.002,-5.20596 0.0139,-60.74822 0.0205,-77.41089 0,-22.57185 20.88677,-38.51906 42.96811,-38.51906 21.70493,0 41.01475,15.21214 41.01475,35.07288 0,17.71 0.36656,74.64185 0.36529,80.89233 -10e-4,7.8219 6.90728,10.41677 13.55884,10.41941 27.29749,0.005 59.54003,0.0296 86.72208,0.0299 1.08085,2e-4 1.95363,3.1e-4 2.60466,3.1e-4 z" fill="#fb5e99" /><path d="m 132.75414,821.76984 c 0,0 451.31832,-24.18823 643.4704,-128.70718 102.74959,-55.88949 244.74016,-219.67378 244.74016,-251.46024 l 1.4144,-111.36924 C 1027.6838,259.38719 964.56726,201.82474 899.54297,201.73995 603.52327,201.35301 433.38197,200.96886 137.3622,200.58164 66.49083,193.64241 4.580714,254.35755 4.088164,317.75996 L 3.890414,694.14513 C 3.856314,759.0955 67.80377,821.76984 132.75414,821.76984 Z M 663.21707,468.56989 c 25.0386,0.0645 40.7468,18.80225 40.7468,42.03175 0,23.22954 -18.2274,42.03179 -40.7468,42.03179 -27.1231,0 -68.0994,0.15711 -82.3564,0.15711 -14.257,0 -17.8158,2.53062 -17.8158,16.70032 0,16.45124 -1.1817,75.76021 -1.1817,75.76021 -0.2354,12.81018 -17.7735,28.66366 -40.5245,28.66366 -20.7399,0 -43.9305,-13.84667 -44.204,-30.66184 l -1.2266,-75.41982 c -0.2573,-15.81807 -8.7481,-15.10147 -16.1081,-15.10147 -13.5192,0 -58.5187,-0.0972 -92.0368,-0.0982 -22.5194,0 -40.7468,-18.80225 -40.7468,-42.03179 0,-23.2295 18.2274,-42.03175 40.7468,-42.03175 0.8347,0 1.8855,10e-5 3.1386,3.1e-4 32.1488,0.0101 62.5593,0.0185 94.5076,0.0347 7.5208,0.003 10.5511,-4.53477 10.5534,-10.40981 0,-5.20596 0.014,-60.74822 0.021,-77.41089 0,-22.57185 20.8868,-38.51906 42.9681,-38.51906 21.7049,0 41.0148,15.21214 41.0148,35.07288 0,17.71 0.3665,74.64185 0.3652,80.89233 -10e-4,7.8219 6.9073,10.41677 13.5589,10.41941 27.2975,0.005 59.54,0.0296 86.7221,0.0299 1.0808,2e-4 1.9536,3.1e-4 2.6046,3.1e-4 z" fill="#fb71ac" /><path d="M 562.65545,212.17869 C 668.25792,187.56834 245.79263,201.20966 137.3622,200.58164 66.49083,193.64241 4.58071,254.35755 4.08816,317.75996 L 9.5478685,514.52082 C 117.73973,720.64396 214.81282,514.1631 299.95919,395.14608 385.10555,276.12906 496.51304,244.57588 562.65545,212.17869 Z" fill="#fb84b7" />';
|
||||
zib_svgs['tag-color'] = ' <path d="M 335.62909,311.2937 584.9847,80.429349 C 625.1003,43.262523 690.09617,42.955359 730.70323,79.692156 L 892.39428,226.14788 c 24.02022,21.80863 25.24887,57.25534 2.64161,80.35406 z" fill="#1dce75" /><path d="M 155.93823,310.80224 308.78297,82.333765 c 27.03041,-43.002939 84.28576,-60.879876 133.92343,-41.835717 37.35113,14.313836 72.42924,27.890478 71.38488,27.890478 -2.27301,0 -263.30085,241.369354 -263.30085,241.369354 z" fill="#48e1aa" /><path d="M 889.99841,384.82873 H 134.68249 c -72.367799,0 -131.0360949,58.66829 -131.0360949,131.0361 v 342.91772 c 0,72.3678 58.6682959,131.0361 131.0360949,131.0361 h 755.31592 c 72.3678,0 131.03609,-58.6683 131.03609,-131.0361 V 515.86483 c 0,-72.36781 -58.66829,-131.0361 -131.03609,-131.0361 z M 196.85246,767.37059 c -44.2316,0 -80.0469,-35.81531 -80.0469,-80.0469 0,-44.2316 35.8153,-80.0469 80.0469,-80.0469 44.23159,0 80.0469,35.8153 80.0469,80.0469 0,44.17016 -35.81531,80.0469 -80.0469,80.0469 z" fill="#05c46d" /><path d="m 134.68249,384.82873 c -72.367799,0 -131.0360949,58.66829 -131.0360949,131.0361 v 342.91772 c 0,72.3678 58.6682959,131.0361 131.0360949,131.0361 H 653.85084 C 827.88988,857.30816 940.18898,648.00671 940.18898,412.41204 c 0,-5.89755 -0.0614,-11.73366 -0.24573,-17.63121 -15.83388,-6.55581 -32.80747,-9.91713 -49.94484,-9.89067 H 134.68249 Z m 62.16997,382.54186 c -44.2316,0 -80.0469,-35.81531 -80.0469,-80.0469 0,-44.2316 35.8153,-80.0469 80.0469,-80.0469 44.23159,0 80.0469,35.8153 80.0469,80.0469 0,44.17016 -35.81531,80.0469 -80.0469,80.0469 z" fill="#1dce75" /><path d="m 720.38253,307.97633 c 13.94524,-51.97212 21.3786,-106.27869 21.3786,-162.24395 0,-19.71992 -0.98292,-39.1941 -2.76447,-58.483994 l -8.35486,-7.55623 C 690.03474,42.955359 625.1003,43.262523 584.92327,80.429349 L 335.62909,311.2937 Z m -15.91109,76.8524 H 134.68249 c -72.367799,0 -131.0360949,58.66829 -131.0360949,131.0361 v 342.91772 c 0,7.24907 0.7371932,14.31384 1.8429831,21.19431 3.6245334,0.0614 7.2490668,0.12286 10.9350328,0.12286 320.187599,0 591.843309,-207.45846 688.047029,-495.27099 z M 196.85246,767.37059 c -44.2316,0 -80.0469,-35.81531 -80.0469,-80.0469 0,-44.2316 35.8153,-80.0469 80.0469,-80.0469 44.23159,0 80.0469,35.8153 80.0469,80.0469 0,44.17016 -35.81531,80.0469 -80.0469,80.0469 z" fill="#3cd38e" /><path d="m 414.63163,310.61794 c 39.86987,-49.20765 72.5521,-103.69852 96.75661,-162.05965 L 335.62909,311.2937 Z m -279.94914,74.21079 c -72.367799,0 -131.0360949,58.66829 -131.0360949,131.0361 v 87.54169 C 147.89054,568.81987 275.36354,491.23028 371.75156,384.82873 Z" fill="#48e1aa" />';
|
||||
zib_svgs['ontop-color'] = '<path d="m 560.78185,23.03432 -0.0444,0.03125 C 529.63367,-2.5365049 502.8427,5.7784491 472.22811,26.203805 203.12063,209.39766 645.29116,157.03935 660.28768,376.10836 c 11.81581,172.60542 -245.05263,346.62545 -173.8575,347.17842 77.21601,0.59975 81.06738,-1.48139 111.35145,-4.30787 96.48711,-13.56498 148.14631,20.23609 183.80428,92.97164 5.46604,11.1991 26.49804,24.94136 37.57955,23.27951 11.48967,-1.6933 25.01615,-19.61782 28.35125,-32.34464 21.86923,-82.47465 12.78908,-163.75921 -28.65685,-239.65286 -19.98539,-36.57721 -23.38499,-71.33013 -21.49956,-110.51263 3.63048,-76.28057 -4.40415,-137.22957 -33.80621,-198.61818 0.0176,-0.14053 -0.009,-0.2498 0.0441,-0.35133 C 712.13896,128.16613 560.78185,23.03432 560.78185,23.03432 Z" fill="#f23d4f" /><path d="M 616.33456,831.06942 422.57497,830.3147 c -0.19939,39.27515 19.69349,113.3645 46.69343,166.83864 14.53976,28.75846 86.93517,28.80606 101.53559,0.0686 27.46444,-53.94498 44.92537,-136.49383 45.53057,-166.15268 z" fill="#f23d4f" /><path d="m 520.26833,760.43205 c 0,-0.14138 -0.32828,0.0393 -0.48802,0.0238 l -0.47919,-0.0465 c -45.65365,-0.16699 -96.55948,34.112 -96.72615,69.90538 -0.0958,24.59867 9.34239,62.51955 21.89325,105.28755 58.44783,-16.97058 118.41572,-46.64381 166.42835,-80.52412 5.86486,-5.78617 5.33406,-16.7628 5.43799,-24.00868 0.17549,-35.86363 -50.12928,-70.35701 -96.06623,-70.63731 z" fill="#fc4956" /><path d="M 423.34667,62.066284 C 291.45746,168.02865 335.07761,204.21986 335.07761,204.21986 c 0,0 21.74221,431.44455 26.66971,513.96705 78.55662,0.80244 126.70546,11.72308 202.86596,1.02006 C 700.52488,555.94098 755.26376,407.90903 637.31834,228.18752 566.16255,150.0483 525.39207,86.344299 423.34667,62.066284 Z M 590.84063,444.22433 c -45.52348,40.66928 -101.24044,45.39305 -148.16909,4.17191 -45.10834,-39.6219 -36.80431,-112.49244 5.73843,-152.27773 42.40089,-39.62126 95.91795,-34.24778 141.02577,4.73398 40.43079,41.81687 39.05654,109.91771 1.40489,143.37184 z" fill="#fc4d59" /><path d="m 242.1199,466.49776 c 1.6727,27.89977 -4.93097,58.9429 -18.17645,84.29131 -43.07667,82.37064 -54.42945,166.7202 -31.39526,254.37415 2.93703,11.06015 17.32271,24.61914 29.30396,27.38309 8.7153,2.05557 25.37906,-9.62559 33.02952,-18.7328 22.34847,-26.70457 39.99161,-56.49766 63.62754,-82.18817 8.33374,-9.07641 28.58803,-13.61675 43.28246,-13.46968 C 492.33562,582.33932 520.66533,558.13123 488.2612,473.46426 396.14392,449.82018 398.16428,346.1744 440.70702,306.38911 459.27585,277.7973 459.58934,208.74811 437.60972,173.11402 416.71926,137.64531 415.70691,134.69537 384.11821,96.377099 279.78515,196.62363 233.2361,319.87181 242.1199,466.49776 Z" fill="#ff747c" />';
|
||||
zib_svgs['comment-color'] = '<path d="M 916.07974,259.8083 H 296.90951 c -55.61912,0 -100.68152,45.06237 -100.68152,100.68152 v 401.82121 c 0,55.62089 45.06237,100.68153 100.68152,100.68153 h 68.16663 c 12.54747,0 22.74232,10.18915 22.74232,22.74232 v 80.83477 c 0,18.76091 21.35486,29.43833 36.37565,18.21799 L 581.39965,867.45657 c 3.92109,-2.9559 8.68672,-4.52434 13.63333,-4.52434 h 320.98644 c 55.61914,0 100.68148,-45.06237 100.68148,-100.68152 V 360.48982 C 1016.7613,304.87067 971.69889,259.8083 916.07974,259.8083 Z M 813.58849,720.50619 h -415.0926 c -26.60308,0 -48.19924,-21.59616 -48.19924,-48.19925 0,-26.60308 21.59616,-48.19924 48.19924,-48.19924 h 415.15292 c 26.60308,0 48.19924,21.59616 48.19924,48.19924 -0.0603,26.60309 -21.59615,48.19925 -48.25956,48.19925 z m 0,-190.80627 h -415.0926 c -26.60307,0 -48.19924,-21.59615 -48.19924,-48.19924 0,-26.60308 21.59616,-48.19924 48.19924,-48.19924 h 415.15292 c 26.60307,0 48.19924,21.59616 48.19924,48.19924 0,26.60309 -21.59615,48.19924 -48.25956,48.19924 z" fill="#ff8e12"></path><path d="M 97.114901,651.07273 C 47.347224,647.51359 7.8950281,605.88972 7.8950281,555.21717 V 253.77585 c 0,-116.2554 94.2269419,-210.532354 210.5323619,-210.532354 h 579.23544 c 53.08552,0 96.09686,43.001329 96.09686,96.096864 v 31.67034 c 0,26.36179 -20.32934,49.40573 -46.69113,50.18995 -27.26665,0.84454 -49.70735,-21.05324 -49.70735,-48.19924 0,-18.64026 -15.08112,-33.72138 -33.72137,-33.66105 l -545.21245,0.30162 c -62.91841,0 -114.13388,51.21028 -114.13388,114.13387 v 281.47393 c 0,10.07418 6.21342,19.2435 15.74469,22.56134 19.30382,6.63569 32.93715,25.1553 32.3339,46.87211 -0.90486,28.23184 -27.146,48.38021 -55.257199,46.3895 z" fill="#fca315"></path><path d="M 916.07974,259.8083 H 296.90951 c -55.61915,0 -100.68152,45.06058 -100.68152,100.68152 v 401.82121 c 0,55.61916 45.06237,100.68153 100.68152,100.68153 h 68.16663 c 12.54747,0 22.74232,10.18915 22.74232,22.74232 v 80.83477 c 0,1.14616 0.0603,2.232 0.2413,3.31784 30.22256,-6.21341 59.78154,-14.29689 88.49598,-24.12978 l 104.84391,-78.30114 c 3.92109,-2.9559 8.68672,-4.52434 13.63333,-4.52434 h 49.40573 C 704.03927,823.35939 757.54707,775.28079 803.15236,720.44586 H 398.49589 c -26.60308,0 -48.19924,-21.59615 -48.19924,-48.19924 0,-26.60309 21.59616,-48.19924 48.19924,-48.19924 h 415.15292 c 18.15766,0 33.90235,10.01386 42.1668,24.85367 C 925.43003,540.9806 967.47618,413.63567 972.06084,276.75947 955.48754,265.69706 936.00588,259.79798 916.07974,259.8083 Z M 813.64881,529.69992 H 398.49589 c -26.60308,0 -48.19924,-21.59615 -48.19924,-48.19924 0,-26.60308 21.59618,-48.19924 48.19924,-48.19924 h 415.15292 c 26.60309,0 48.19924,21.59616 48.19924,48.19924 -0.0603,26.66341 -21.59616,48.19924 -48.19924,48.19924 z" fill="#fca315"></path><path d="m 218.42739,139.64198 538.63708,-0.30162 c 6.39439,-31.36872 10.79808,-63.461332 13.09041,-96.096864 H 218.42739 C 102.18231,43.243496 7.8950281,137.4703 7.8950281,253.77585 v 301.381 c 0,50.67671 39.3918709,92.29642 89.2198729,95.85556 28.171519,1.99071 54.412659,-18.15766 55.196879,-46.32918 0.66357,-21.71681 -13.03008,-40.23642 -32.27358,-46.87211 -9.53127,-3.25752 -15.74469,-12.48716 -15.74469,-22.56134 V 253.77585 c 0,-62.92359 51.21547,-114.13387 114.13388,-114.13387 z" fill="#fcb138"></path><path d="M 196.22799,360.48982 V 707.7174 c 55.19687,-12.06489 108.0411,-30.3432 157.80878,-54.05071 7.50835,-17.91252 25.03662,-29.56633 44.45912,-29.55899 h 11.16003 c 45.72594,-26.84438 88.315,-58.57505 126.98298,-94.34745 H 398.49589 c -26.60308,0 -48.19924,-21.59616 -48.19924,-48.19924 0,-26.60309 21.59616,-48.19924 48.19924,-48.19924 h 225.4325 c 39.87447,-52.72358 72.81162,-110.99701 97.424,-173.49315 H 296.90951 c -55.61915,-0.0603 -100.68152,45.00205 -100.68152,100.6212 z" fill="#fcb138"></path><path d="M 518.42092,43.30382 H 218.42739 c -116.24468,0 -210.5323619,94.20222 -210.5323619,210.53236 V 449.16677 C 40.62411,442.20718 72.833548,432.99584 104.29351,421.5985 V 253.83618 c 0,-62.91841 51.21547,-114.13388 114.13388,-114.13388 l 245.58086,-0.12064 c 20.45,-30.5845 38.66798,-62.737441 54.41267,-96.27784 z" fill="#f9c776"></path>';
|
||||
zib_svgs['wallet-color'] = '<path d="m 680.14953,699.80571 c -102.77395,0 -186.36599,-86.21462 -186.36599,-192.21295 0,-105.99832 83.59204,-192.21294 186.36599,-192.21294 H 1020.0991 V 197.67007 c 0,-80.98749 -63.64062,-146.624402 -142.16425,-146.624402 H 149.15081 c -78.523917,0 -142.1642132,65.634642 -142.1642132,146.624402 v 627.32218 c 0,80.98748 63.6402962,146.6244 142.1642132,146.6244 h 728.78404 c 78.52473,0 142.16425,-65.63692 142.16425,-146.6244 V 699.87188 H 680.14953 Z" fill="#fc7032" /><path d="m 680.14953,388.03036 c -63.89691,0 -115.92542,53.66082 -115.92542,119.5624 0,65.90159 52.05748,117.63857 115.92542,119.56241 H 1020.0991 V 388.03036 Z m 4.68321,163.62912 c -23.6085,0 -42.72625,-19.71754 -42.72625,-44.06672 0,-24.34917 19.11775,-44.06672 42.72625,-44.06672 23.6085,0 42.72625,19.71755 42.72625,44.06672 0,24.34918 -19.11775,44.06672 -42.72625,44.06672 z" fill="#fc7032" /><path d="M 1013.812,388.03036 H 680.14953 c -63.89662,0 -115.92542,53.66082 -115.92542,119.5624 0,65.90159 52.02851,119.56241 115.92542,119.56241 H 910.97391 C 957.03614,554.70313 992.19227,474.17881 1013.812,388.03036 Z M 684.83274,551.65948 c -23.6085,0 -42.72625,-19.71754 -42.72625,-44.06672 0,-24.34917 19.11775,-44.06672 42.72625,-44.06672 23.6085,0 42.72625,19.71755 42.72625,44.06672 0,24.34918 -19.11775,44.06672 -42.72625,44.06672 z" fill="#ff7e3e" /><path d="m 680.14953,699.80571 c -102.77395,0 -186.36599,-86.21462 -186.36599,-192.21295 0,-105.99832 83.59204,-192.21294 186.36599,-192.21294 H 1020.0991 V 197.67007 c 0,-80.98749 -63.64062,-146.624402 -142.16425,-146.624402 H 149.15081 c -78.523917,0 -142.1642132,65.636912 -142.1642132,146.624402 v 627.32218 c 0,80.98965 63.6402962,146.6244 142.1642132,146.6244 H 431.81124 C 602.07469,931.38757 751.10333,833.92469 858.9454,699.87188 H 680.14953 Z" fill="#ff7e3e" /><path d="m 149.15081,51.045668 c -78.523917,0 -142.1642132,65.636912 -142.1642132,146.624402 v 506.89961 c 11.7400952,0.52933 23.6084972,0.86016 35.4768992,0.86016 170.455914,0 328.209434,-56.30748 456.708944,-151.7192 -3.52845,-14.75507 -5.45305,-30.17181 -5.45305,-46.05171 0,-105.99832 83.82892,-192.21294 186.36599,-192.21294 H 712.3546 C 759.31498,235.38483 793.05973,146.19273 810.70195,51.111834 H 149.15081 Z" fill="#ff9552" /><path d="m 564.67319,499.32198 c 36.05428,-33.34778 69.09334,-70.13622 98.66812,-109.83596 -53.37574,8.00611 -94.94722,53.59465 -98.66812,109.83596 z" fill="#ff9552" /><path d="M 502.76504,51.045668 H 149.15081 C 70.626893,51.045668 6.9865968,116.65998 6.9865968,197.67007 V 402.6531 C 214.26663,357.85855 391.39452,228.43737 502.76504,51.045668 Z" fill="#ffa56a" />';
|
||||
zib_svgs['book-color'] = '<path d="M 166.74332,30.412781 V 709.22842 c 0,0 253.18864,-29.46445 303.13786,57.06238 0,-146.92229 2.66309,-667.283176 2.66309,-667.283176 0,0 -55.01559,-85.660227 -305.80095,-68.594843 z m 692.27411,0 V 709.22842 c 0,0 -253.18864,-29.46445 -303.13786,57.06238 0,-146.92229 -2.66309,-667.283176 -2.66309,-667.283176 0,0 55.01559,-85.660227 305.80095,-68.594843 z" fill="#3a9ced" /><path d="m 512.4257,996.27351 c -11.62667,0 -23.18839,-3.93304 -32.73655,-11.66579 L 379.20613,903.14718 H 65.480862 c -29.128759,0 -52.742219,-24.2345 -52.742219,-54.12927 V 141.73775 L 118.28803,95.341233 V 794.88865 h 279.36489 c 11.88656,0 23.38325,4.13302 32.67159,11.66579 l 85.0241,68.92815 98.85918,-66.59499 c 8.60292,-5.80122 18.6755,-8.88392 28.96925,-8.866 H 906.69327 V 102.14072 l 105.54943,46.39651 v 705.61363 c 0,29.89477 -23.61353,54.12926 -52.74225,54.12926 H 658.96073 L 541.4599,987.40751 c -8.63556,5.78238 -18.72317,8.86278 -29.0342,8.866 z" fill="#138ee8" /><path d="m 906.62832,462.38031 c 30.78795,-86.86014 47.6109,-180.58643 47.6109,-278.37907 0,-20.79844 -0.77945,-41.46355 -2.27338,-61.86202 L 906.62832,102.20738 Z M 643.11209,800.0216 c -10.26736,0 -20.33044,3.06643 -28.96925,8.866 l -98.85919,66.59499 -85.02409,-68.92815 c -9.30617,-7.5416 -20.81399,-11.65061 -32.6716,-11.66579 H 118.22308 V 95.341233 L 12.67369,141.73775 v 707.28016 c 0,29.89477 23.613496,54.12927 52.742219,54.12927 H 379.20613 l 55.47027,44.99661 c 90.48018,-34.13076 173.2309,-84.6603 244.74468,-148.12219 z" fill="#3a9ced" /><path d="M 118.22308,689.16326 V 95.341233 L 12.67369,141.73775 v 564.02426 c 35.91927,-3.13309 71.189005,-8.73267 105.54939,-16.59875 z M 166.74332,30.412781 V 676.29756 c 113.99335,-34.13076 217.39927,-93.85961 303.9173,-172.65369 0.77944,-191.85224 1.88365,-404.636246 1.88365,-404.636246 0,0 -55.01559,-85.660227 -305.80095,-68.594843 z m 386.53812,68.594843 c 0,0 0.77944,152.255226 1.49392,315.376296 C 641.87797,306.65868 702.41461,175.53521 726.12262,31.479367 587.77173,45.478315 553.28144,99.007624 553.28144,99.007624 Z" fill="#59adf8" /><path d="M 118.22308,325.0573 V 95.341233 L 12.67369,141.73775 v 231.3826 C 49.177541,359.72136 84.447276,343.58924 118.22308,325.0573 Z M 406.55154,55.410902 C 360.69439,37.345593 285.80304,22.280059 166.74332,30.412781 V 296.12614 C 262.39631,234.23391 344.13854,152.1825 406.55154,55.410902 Z" fill="#6bc2fc" />';
|
||||
zib_svgs['posts'] = '<path d="M810.666667 256h42.666666a128 128 0 0 1 128 128v363.221333A106.112 106.112 0 0 1 875.221333 853.333333h-53.76a42.666667 42.666667 0 0 0-38.442666 24.277334l-26.026667 54.442666a85.333333 85.333333 0 0 1-155.648-3.584l-20.693333-49.066666a42.666667 42.666667 0 0 0-39.296-26.069334h-113.92a42.666667 42.666667 0 0 1 0-85.333333h113.92a128 128 0 0 1 117.930666 78.250667l20.693334 49.066666 26.026666-54.485333A128 128 0 0 1 821.504 768h53.717333c11.477333 0 20.778667-9.301333 20.778667-20.778667V384a42.666667 42.666667 0 0 0-42.666667-42.666667h-42.666666v255.317334a128.128 128.128 0 0 1-127.872 128.298666h-213.589334c-35.712 0-90.197333 22.485333-115.370666 47.530667l-37.418667 37.205333C272.981333 852.906667 213.333333 829.098667 213.333333 767.232h85.333334v0.682667H213.333333c0-24.277333-19.541333-44.373333-43.605333-44.885334A130.261333 130.261333 0 0 1 42.666667 593.450667V255.658667A127.744 127.744 0 0 1 170.410667 128h512.512A128.085333 128.085333 0 0 1 810.666667 256zM298.666667 767.914667H213.333333v-0.682667h85.333334v0.682667z m-10.24-50.688l5.248-5.248c41.130667-40.96 117.290667-72.362667 175.530666-72.362667h213.589334c23.381333 0 42.538667-19.2 42.538666-42.965333V256.298667C725.333333 232.576 706.218667 213.333333 682.922667 213.333333H170.410667A42.410667 42.410667 0 0 0 128 255.658667v337.792c0 23.68 19.669333 43.733333 43.605333 44.288A130.133333 130.133333 0 0 1 288.426667 717.226667z"></path><path d="M256 384h341.333333a42.666667 42.666667 0 0 0 0-85.333333H256a42.666667 42.666667 0 1 0 0 85.333333zM256 554.666667h256a42.666667 42.666667 0 0 0 0-85.333334H256a42.666667 42.666667 0 1 0 0 85.333334z"></path>';
|
||||
zib_svgs['points'] = '<path d="M419.886252 370.432927c119.605022 0 243.995044-26.302516 318.706976-76.460106v91.304594h69.207683V185.366307C807.800911 65.18189 607.999688 0.289697 420.006126 0.289697S32.091467 65.18189 32.091467 185.366307v545.629859c0 120.184417 199.801223 185.076609 387.794785 185.07661V846.984967c-197.463666 0-318.706976-67.579385-318.706976-115.978811V566.977553c74.711932 50.037714 198.992069 76.460105 318.706976 76.460105v-69.217673c-197.463666 0-318.706976-67.569395-318.706976-115.968822V294.102686c74.711932 50.027725 199.111944 76.330241 318.706976 76.330241z m0-301.045432c197.473655 0 318.706976 67.579385 318.706976 115.978812 0 48.399426-121.24331 115.978811-318.706976 115.978811s-318.706976-67.579385-318.706976-115.978811c0.00999-48.399426 121.363185-115.978811 318.706976-115.978812z m310.056015 338.925849c-171.740545 0-261.536715 66.060971-261.536714 131.29281v350.623625c0 65.231838 89.906055 131.292809 261.536714 131.29281 170.461881 0 260.128186-65.121953 261.526725-129.894271h0.119875V539.616143c-0.119875-65.241827-89.906055-131.302799-261.6466-131.302799z m0 69.097799c126.967329 0 192.438916 43.604437 192.438917 62.195011s-65.471587 62.195011-192.438917 62.195011-192.438916-43.604437-192.438916-62.195011 65.471587-62.195011 192.438916-62.195011z m0 475.013648c-126.967329 0-192.438916-43.604437-192.438916-62.195012v-83.712527c43.844186 23.855073 108.26687 39.758456 192.438916 39.758456 84.172047 0 148.474855-15.893393 192.438917-39.758456v83.712527c0 18.590574-65.471587 62.195011-192.438917 62.195012z m0-175.366756c-126.967329 0-192.438916-43.614426-192.438916-62.195011v-83.712527c43.844186 23.855073 108.26687 39.748466 192.438916 39.748466 84.172047 0 148.474855-15.893393 192.438917-39.748466v83.712527c0 18.580585-65.471587 62.195011-192.438917 62.195011z m0 0"></path>';
|
||||
zib_svgs['points-color'] = '<path d="M716.032 626.2784c-58.6752-0.1024-114.5344-10.496-164.2496-42.0352-61.0304-38.7072-60.9792-95.9488-0.3584-134.5024 90.5216-57.4976 245.76-56.4224 335.5648 2.304 55.296 36.1984 54.4256 95.5392-1.9456 130.7136-51.3536 32.0512-108.4416 43.8784-169.0112 43.52z" fill="#FF8E12"></path><path d="M118.9376 643.8912c92.3648 96.9216 208.0768 117.2992 331.1104 122.5216-3.9424 54.6304 6.7072 99.1744 50.1248 132.352l-1.0752 7.8336c-26.4704 0-44.032 0.8192-70.4-0.512-88.6784-4.4032-173.7216-21.8112-248.1152-71.1168-48.128-31.8976-82.1248-72.9088-77.2608-132.7104 1.4848-17.8688 9.2672-35.3792 15.616-58.368z" fill="#FCA315"></path><path d="M517.7344 611.5328c91.5968 97.9968 316.3136 89.1392 396.7488 1.8432 21.0944 25.5488 18.944 59.648-6.8608 87.9104-34.048 37.2224-80.2304 52.0704-129.3312 59.7504-82.3808 12.8512-161.1776 5.1712-230.9632-42.9568-41.6256-28.7232-51.5584-67.84-29.5936-106.5472z" fill="#FF8E12"></path><path d="M517.376 749.7728c88.7808 97.792 312.6784 94.1056 397.3632 3.1744 20.6848 26.88 18.2272 60.7232-7.2192 88.3712-37.5296 40.7552-88.4736 55.04-141.8752 61.8496-77.9776 9.9328-152.6784 1.024-218.0608-45.0048-41.728-29.3888-52.0704-67.5328-30.208-108.3904z" fill="#FF8E12"></path><path d="M795.648 285.2864l-0.0512-0.0512c7.8336-43.6736-15.2064-90.2144-62.6688-122.0608-85.0944-57.1392-182.3232-72.704-297.4208-75.1104-18.7904 1.8432-51.3024 4.2496-83.6096 8.2944-66.6112 8.2944-128.7168 28.8768-183.7568 66.1504-83.456 56.576-88.1664 138.3936-10.1376 201.1648 23.2448 18.688 50.9952 33.3824 78.848 45.4656 59.392 25.7024 123.2384 33.6384 187.904 37.7856 1.4336 0.1024 2.8672 0.1536 4.2496 0.2048h0.0512c2.9696 0.1536 5.888 0.2048 8.704 0.1536 18.0224 0.256 36.4544-0.1024 43.008-1.2288 4.0448-8.0896 20.8384-25.1904 28.16-32.4608 58.4192-47.9232 132.5056-60.2624 207.7696-57.6 0 0 24.4224 0.7168 39.3216 2.5088 23.9616-15.9232 34.6624-52.0704 38.144-66.7648 0.1536-0.7168 0.3584-1.4336 0.512-2.1504 0.6656-2.6112 0.9728-4.3008 0.9728-4.3008zM472.8832 576.0512c-7.3728-11.3152-15.9232-38.144-15.9232-38.144l-30.3616-0.7168c-114.2272-6.3488-220.1088-32.768-302.7456-117.504-33.7408 49.0496-27.0336 107.1616 17.3568 152.4224 58.624 59.7504 135.7824 83.7632 216.9856 97.7408 10.7008 1.8432 21.4528 3.0208 32.0512 3.84 25.088 2.816 55.1936 5.0176 66.3552 4.352-7.3216-40.0896 3.5328-80.384 16.2816-101.9904zM517.376 749.7728c-21.8624 40.8576-11.52 79.0016 30.208 108.3904 11.008 7.7312 22.272 14.336 33.7408 20.0704 26.0608-18.5856 50.5344-39.1168 73.3696-61.44-54.784-9.3696-105.0112-31.4368-137.3184-67.0208zM761.0368 679.2704c-89.5488 10.496-189.44-10.0864-243.3024-67.7376-21.9648 38.7584-12.032 77.8752 29.5424 106.5472 47.616 32.8704 99.4816 46.848 153.8048 48.3328 22.3744-27.2384 42.4448-56.3712 59.9552-87.1424zM551.4752 449.7408c-60.672 38.5536-60.672 95.8464 0.3584 134.5024 49.7152 31.488 105.5744 41.9328 164.2496 42.0352 25.6512 0.1536 50.6368-1.8944 74.8544-6.7584 25.8048-59.4432 42.5984-123.648 48.64-191.0272-90.3168-33.8432-212.0192-27.0848-288.1024 21.248z" fill="#FCA315"></path><path d="M118.9376 643.8912c-6.3488 22.9888-14.1312 40.4992-15.5648 58.4192-2.0992 25.5488 2.9696 47.6672 13.1584 67.1232 50.688-5.3248 99.584-16.6912 145.8688-33.4336-51.8656-18.1248-100.2496-46.6944-143.4624-92.1088zM426.5984 537.1392c-114.2272-6.3488-220.1088-32.768-302.7456-117.504-33.7408 49.0496-27.0336 107.1616 17.3568 152.4224 58.624 59.7504 135.7824 83.7632 216.9856 97.7408 9.984 1.7408 20.0704 2.816 30.0032 3.6352 24.1152-15.616 47.0528-32.8192 68.7104-51.5072 3.328-18.5856 9.3696-34.7648 16.0256-45.9776-7.3728-11.3152-15.9232-38.144-15.9232-38.144l-30.4128-0.6656zM351.8976 96.3584c-66.6112 8.2944-128.7168 28.8768-183.7568 66.1504-83.456 56.576-88.1664 138.3936-10.1376 201.1648 23.2448 18.688 50.9952 33.3824 78.848 45.4656 59.392 25.7024 123.2384 33.6384 187.904 37.7856 1.4336 0.1024 2.8672 0.1536 4.2496 0.2048h0.0512c2.9696 0.1536 5.888 0.2048 8.704 0.1536 18.0224 0.256 36.4544-0.1024 43.008-1.2288 4.0448-8.0896 20.8384-25.1904 28.16-32.4608 37.3248-30.6176 81.1008-46.6432 127.4368-53.6064 23.1424-65.0752 35.7888-135.168 35.7888-208.2304 0-7.3216-0.1536-14.6432-0.4096-21.9136-69.9392-30.3104-147.8656-39.9872-236.288-41.8816-18.7392 1.9456-51.2512 4.352-83.5584 8.3968z" fill="#FFBC42" p-id="7872"></path><path d="M123.8528 419.6864c-20.8896 30.3104-26.2144 64.1536-16.7936 96.256 30.5152-11.1104 59.904-24.5248 88.0128-40.0384a352.2816 352.2816 0 0 1-71.2192-56.2176zM435.5072 88.064c-18.7904 1.8432-51.3024 4.2496-83.6096 8.2944-66.6112 8.2944-128.7168 28.8768-183.7568 66.1504-83.456 56.576-88.1664 138.3936-10.1376 201.1648 23.2448 18.688 50.9952 33.3824 78.848 45.4656 12.544 5.4272 25.2928 10.0352 38.2464 14.0288 106.2912-82.3808 185.088-198.5024 220.3648-332.3392-19.456-1.4336-39.424-2.3552-59.9552-2.7648z" fill="#FFC65E"></path>';
|
||||
zib_svgs['money-color-2'] = '<path d="M 783.74365,87.860049 H 243.43248 c -75.7128,0 -137.08867,58.224241 -137.08867,130.050721 v 622.10914 c 0,36.60768 41.73278,59.55128 75.18894,41.30437 l 116.63027,-63.58772 c 18.75878,-10.22727 42.31306,-7.91034 58.46086,5.75054 L 480.5399,928.3792 c 19.02016,16.10649 47.74599,16.13027 66.79575,0.0553 L 672.4174,822.87887 c 16.21713,-13.70231 39.89249,-15.9349 58.63571,-5.52937 l 114.18227,63.20067 c 33.45616,18.52338 75.48036,-4.3682 75.48036,-41.13849 V 217.91077 C 920.83231,146.08429 859.45716,87.860049 783.74365,87.860049 Z M 649.91901,548.67753 c 21.94452,0.35445 39.53842,17.33171 39.53842,38.15264 0,20.82093 -17.5939,37.79819 -39.53842,38.15264 h -96.1719 v 45.50669 c -0.37362,20.81792 -18.26964,37.50857 -40.21733,37.50857 -21.9477,0 -39.84372,-16.69065 -40.21734,-37.50857 v -45.50669 h -96.17189 c -21.94453,-0.35445 -39.53842,-17.33171 -39.53842,-38.15264 0,-20.82093 17.59389,-37.79819 39.53842,-38.15264 h 96.17189 v -39.2585 h -96.17189 c -21.94453,-0.35445 -39.53842,-17.33171 -39.53842,-38.15264 0,-20.82093 17.59389,-37.7982 39.53842,-38.15264 h 47.32823 l -68.2529,-84.15697 c -12.35664,-15.26105 -7.46061,-35.88559 10.95776,-46.11492 18.41838,-10.22933 43.42307,-6.1929 55.7797,9.06816 l 91.1593,112.30145 89.81872,-113.51791 c 12.18177,-15.37164 37.06989,-19.68455 55.66312,-9.6211 18.59323,10.06345 23.78069,30.63269 11.6572,46.00434 l -68.07804,86.03695 h 46.80365 c 21.94453,0.35444 39.53842,17.33171 39.53842,38.15264 0,20.82093 -17.59389,37.79819 -39.53842,38.15264 H 553.8054 v 39.2585 z" fill="#4869f0" /><path d="M 783.74365,87.860049 H 243.43248 c -75.71351,0 -137.08867,58.224241 -137.08867,130.050721 v 622.10914 c 0,15.8154 7.81033,29.08447 19.35095,37.5444 17.13609,2.43292 34.44703,4.31291 51.99111,5.52937 1.28229,-0.55294 2.56459,-1.10587 3.84688,-1.7694 l 116.63027,-63.58772 c 18.75878,-10.22727 42.31306,-7.91034 58.46086,5.75054 l 47.09508,39.86674 c 292.77056,-73.43 508.66188,-326.39856 508.66188,-627.25145 0,-24.4951 -1.45715,-48.71373 -4.25488,-72.49001 C 886.44357,118.8798 838.94002,87.860049 783.74365,87.860049 Z M 649.91901,548.67753 c 21.94452,0.35445 39.53842,17.33171 39.53842,38.15264 0,20.82093 -17.5939,37.79819 -39.53842,38.15264 h -96.1719 v 45.50669 c -0.37362,20.81792 -18.26964,37.50857 -40.21733,37.50857 -21.9477,0 -39.84372,-16.69065 -40.21734,-37.50857 v -45.50669 h -96.17189 c -21.94453,-0.35445 -39.53842,-17.33171 -39.53842,-38.15264 0,-20.82093 17.59389,-37.79819 39.53842,-38.15264 h 96.17189 v -39.2585 h -96.17189 c -21.94453,-0.35445 -39.53842,-17.33171 -39.53842,-38.15264 0,-20.82093 17.59389,-37.7982 39.53842,-38.15264 h 47.32823 l -68.2529,-84.15697 c -12.35664,-15.26105 -7.46061,-35.88559 10.95776,-46.11492 18.41838,-10.22933 43.42307,-6.1929 55.7797,9.06816 l 91.1593,112.30145 89.81872,-113.51791 c 12.18177,-15.37164 37.06989,-19.68455 55.66312,-9.6211 18.59323,10.06345 23.78069,30.63269 11.6572,46.00434 l -68.07804,86.03695 h 46.80365 c 21.94453,0.35444 39.53842,17.33171 39.53842,38.15264 0,20.82093 -17.59389,37.79819 -39.53842,38.15264 H 553.8054 v 39.2585 z" fill="#597cf0" /><path d="m 243.43248,87.860049 c 0,72.981341 -137.08867,58.210631 -137.08867,130.050721 v 433.613 c 82.12497,-7.35406 159.99506,-28.42095 231.10398,-60.82304 -0.11658,-1.27176 -0.40801,-2.54351 -0.40801,-3.87056 0,-21.06689 18.01038,-38.15264 40.21734,-38.15264 h 38.46876 c 19.58409,-12.1646 38.52704,-25.26921 56.65398,-39.2585 h -95.18103 c -21.94452,-0.35445 -39.53842,-17.33171 -39.53842,-38.15264 0,-20.82093 17.5939,-37.7982 39.53842,-38.15264 h 47.32823 l -68.31118,-84.15697 c -12.35664,-15.26105 -7.46061,-35.88559 10.95776,-46.11492 18.41838,-10.22933 43.42307,-6.1929 55.7797,9.06816 l 91.1593,112.30145 89.81872,-113.51791 c 10.60805,-13.38107 30.89157,-18.3575 48.20251,-12.77284 C 686.52261,233.33771 709.89529,162.6171 719.8622,87.860049 H 243.43248 Z" fill="#6994f0" /><path d="M 106.34381,217.91077 V 384.84238 C 261.67599,330.4334 390.48804,223.99308 469.29071,87.860049 H 243.43248 c -75.70889,0 -137.08867,58.130701 -137.08867,130.050721 z" fill="#7a9bf0" />';
|
||||
zib_svgs['merchant-color'] = '<path d="m 208.11748,161.67385 h 605.24097 c 29.0295,0 52.52654,-23.91392 52.52654,-53.462 0,-29.548082 -23.49748,-53.461996 -52.52654,-53.461996 H 208.11748 c -29.03106,0 -52.52655,23.913914 -52.52655,53.461996 -0.0615,29.54808 23.49549,53.462 52.52655,53.462 z" fill="#1fbd45" /><path d="M 998.79255,404.88211 914.34414,217.1391 c -0.41844,-0.8985 -1.29907,-1.47989 -2.27575,-1.50244 H 111.93044 c -0.98411,0 -1.90671,0.62602 -2.27575,1.50244 L 29.204201,406.57236 c -14.700052,34.55623 -12.424312,74.74663 7.995843,106.11017 23.495481,36.05867 63.782226,59.84739 109.481556,59.84739 54.0027,0 100.31709,-33.3042 120.42971,-80.75642 0.83549,-2.07014 3.716,-2.07014 4.55148,0 20.11262,47.45222 66.42702,80.75642 120.42972,80.75642 54.0027,0 100.31708,-33.3042 120.4297,-80.75642 0.83549,-2.07014 3.716,-2.07014 4.55149,0 20.11262,47.45222 66.3655,80.75642 120.42971,80.75642 54.06421,0 100.31709,-33.3042 120.42971,-80.75642 0.83549,-2.07014 3.71599,-2.07014 4.55148,0 20.11262,47.45222 66.42702,80.75642 120.42972,80.75642 42.87002,0 80.94253,-20.90903 104.86857,-53.2742 24.23351,-32.80338 27.80101,-77.00029 11.00966,-114.37361 z M 760.14736,594.19016 c -34.0746,27.98304 -77.06764,44.07172 -122.70546,44.07172 -45.63781,0 -88.63085,-16.08868 -122.70545,-44.07172 -34.74237,28.54811 -78.05397,44.10419 -122.70546,44.07172 -45.63781,0 -88.63085,-16.08868 -122.70544,-44.07172 -34.74238,28.54811 -78.05398,44.10419 -122.70546,44.07172 -12.30129,0 -24.47958,-1.18944 -36.35033,-3.4431 v 271.81731 c 0,39.005 31.06077,70.61491 69.37932,70.61491 h 660.76424 c 38.31972,0 69.37933,-31.6139 69.37933,-70.61491 V 636.19602 c -8.91844,1.25203 -17.89839,2.00326 -26.93984,2.00326 -45.63782,0.0626 -88.63086,-16.08868 -122.70545,-44.00912 z" fill="#1cac3f" /><path d="M 912.06839,215.63666 H 111.93044 c -0.98407,0 -1.90671,0.62602 -2.27575,1.50244 L 29.204201,406.57236 c -14.700052,34.55623 -12.424312,74.74663 7.995843,106.11017 23.495481,36.05867 63.782226,59.84739 109.481556,59.84739 54.0027,0 100.31709,-33.3042 120.42971,-80.75642 0.83549,-2.07014 3.716,-2.07014 4.55148,0 20.11262,47.45222 66.42702,80.75642 120.42972,80.75642 54.0027,0 100.31708,-33.3042 120.4297,-80.75642 0.83549,-2.07014 3.716,-2.07014 4.55149,0 20.11262,47.45222 66.3655,80.75642 120.42971,80.75642 54.0027,0 100.31709,-33.3042 120.42971,-80.75642 0.83549,-2.07014 3.71599,-2.07014 4.55148,0 17.89839,42.19366 56.40146,73.11899 102.65434,79.50438 43.30057,-93.5898 67.59563,-198.07232 67.59563,-308.37681 0,-1.69025 -0.0615,-3.4431 -0.0615,-5.13335 L 914.40564,217.2017 c -0.4321,-0.92384 -1.33267,-1.52687 -2.33725,-1.56504 z m -151.92103,378.5535 c -34.0746,27.98304 -77.06764,44.07172 -122.70546,44.07172 -45.63781,0 -88.63085,-16.08868 -122.70545,-44.07172 -34.74237,28.54811 -78.05397,44.10419 -122.70546,44.07172 -45.63781,0 -88.63085,-16.08868 -122.70544,-44.07172 -34.74238,28.54811 -78.05398,44.10419 -122.70546,44.07172 -12.30129,0 -24.47958,-1.18944 -36.35033,-3.4431 v 271.81731 c 0,39.11122 31.04267,70.61491 69.37932,70.61491 h 159.79387 c 210.29069,-35.93347 389.27459,-165.64455 494.02014,-345.43711 -26.87833,-7.19922 -51.84997,-20.0326 -73.31573,-37.62373 z" fill="#1fbd45" /><path d="M 736.28284,54.749854 H 208.11748 c -29.02736,0 -52.52655,23.913914 -52.52655,53.461996 0,29.54808 23.49549,53.462 52.52655,53.462 h 513.21928 c 7.58856,-35.21326 12.58446,-70.953852 14.94608,-106.923996 z M 707.4978,215.63666 H 111.93044 c -0.98411,0 -1.90671,0.62602 -2.27575,1.50244 L 29.204201,406.57236 c -14.700052,34.55623 -12.424312,74.74663 7.995843,106.11017 23.495481,36.05867 63.782226,59.84739 109.481556,59.84739 54.0027,0 100.31709,-33.3042 120.42971,-80.75642 0.83549,-2.07014 3.716,-2.07014 4.55148,0 20.11262,47.45222 66.42702,80.75642 120.42972,80.75642 54.0027,0 100.31708,-33.3042 120.4297,-80.75642 0.83549,-2.07014 3.716,-2.07014 4.55149,0 3.69038,8.76427 8.36488,17.02771 13.71594,24.72774 C 611.8552,433.49116 673.30019,330.63629 707.4978,215.63666 Z M 374.56315,637.38545 c -38.49301,-3.50413 -75.09777,-18.5593 -105.1761,-43.25789 -34.74238,28.5481 -78.05397,44.10419 -122.70545,44.07172 -12.3013,0 -24.47958,-1.18944 -36.35034,-3.44311 v 90.2093 c 95.02753,-11.39354 184.39647,-41.88065 264.23189,-87.58002 z" fill="#39ca66" /><path d="M 492.59411,54.749854 H 208.11748 c -29.01779,0 -52.52655,23.913914 -52.52655,53.461996 0,29.54808 23.49549,53.462 52.52655,53.462 H 432.31775 C 455.25968,127.99404 475.4338,92.248374 492.59411,54.749854 Z M 391.66196,215.63666 H 111.93044 c -0.98364,0 -1.90671,0.62602 -2.27575,1.50244 L 29.204201,406.57236 c -6.212157,14.52363 -9.164468,30.1115 -9.225975,45.57416 C 167.40929,414.648 296.69593,330.38588 391.66196,215.63666 Z" fill="#4ed886" />';
|
||||
zib_svgs['medal-color'] = '<path d="M 512.03261,779.34977 C 300.22792,780.73628 128.67101,612.48577 127.81597,402.45898 126.96094,192.19105 295.64737,23.639121 508.49031,22.071757 720.23393,20.504393 892.76802,188.45349 894.60024,397.75688 896.43246,607.78368 725.85274,777.90297 512.03261,779.34977 Z M 756.38974,340.54809 c -2.13759,-31.34728 -20.58194,-48.1663 -47.6988,-55.40029 -18.13898,-4.82266 -37.07193,-8.74107 -55.76058,-9.28362 -32.79674,-1.02481 -55.76058,-12.17721 -65.22705,-45.63441 -3.66444,-13.08146 -11.84836,-24.89698 -18.07791,-37.31532 -11.72621,-23.45018 -29.31552,-38.94297 -56.98205,-40.20892 -29.43768,-1.38651 -47.63774,14.58854 -59.91361,38.8224 -10.32151,20.31545 -18.93295,41.59544 -30.84238,61.00664 -4.947,8.13824 -15.57388,15.61336 -24.9182,17.78355 -23.14705,5.36521 -47.08807,6.99286 -70.60156,10.91127 -26.07861,4.40067 -45.62229,17.18072 -54.47802,43.34365 -8.79466,25.74094 1.09933,46.05639 18.13898,64.26192 10.01614,10.73042 19.9712,22.00339 31.88063,30.50332 27.05579,19.4112 37.31623,42.62025 25.28465,74.99235 -4.7027,12.71976 -4.27518,27.18774 -7.14566,40.69118 -5.55774,26.28349 0.79396,49.37197 22.16987,65.4676 22.41416,16.8793 47.45451,15.31194 72.18948,2.71274 25.52894,-13.02118 51.2411,-35.68767 76.83111,-35.62739 25.59002,0.0603 51.30218,22.78706 76.77004,35.86852 23.69672,12.11694 47.27129,14.16657 69.86868,-1.80849 23.51349,-16.63818 28.70478,-40.51034 24.24638,-67.15553 -3.60337,-21.5814 -9.28325,-42.98194 -11.17654,-64.74419 -0.85504,-9.64532 2.87048,-22.12395 9.1611,-29.41822 15.39065,-17.90412 34.81219,-32.43238 50.08069,-50.39679 11.0544,-13.02118 26.20075,-24.83669 26.20075,-49.37197 z" fill="#718ff2" /><path d="m 406.49671,840.47697 c -4.15304,9.76588 -6.16848,16.03534 -9.34433,21.76225 -24.24638,43.46421 -48.55384,86.92842 -73.22774,130.1515 -13.68058,23.99278 -25.22357,25.31898 -44.33974,5.12408 -25.77323,-27.18774 -49.77532,-56.18398 -77.19755,-81.6235 -13.74166,-12.71977 -32.36923,-22.90763 -50.56929,-27.79058 -35.484,-9.52475 -72.311635,-13.86514 -108.345305,-21.46083 -25.590012,-5.36521 -30.41486,-16.33675 -17.589316,-38.88268 26.750419,-46.84008 54.172652,-93.31845 81.411661,-139.85711 19.0551,-32.49267 28.27727,-34.12031 54.41695,-7.65597 50.87466,51.48188 107.79564,94.34326 174.85491,123.21893 16.12354,6.93257 33.28534,11.57438 49.04243,19.10979 8.0007,3.91841 14.04703,11.93608 20.88732,17.90412 z m 599.19719,8.2588 c -8.85575,5.90776 -17.22289,15.19138 -27.30011,17.54242 -38.23233,8.74107 -77.3197,13.98571 -115.49096,23.20905 -14.41347,3.49643 -29.3766,11.81551 -40.00348,22.06366 -28.64372,27.73029 -54.84447,57.87191 -82.44992,86.6873 -18.13899,18.9289 -30.17057,18.0247 -42.87396,-4.3404 -25.46787,-44.60959 -49.95855,-89.70145 -74.69352,-134.67275 -10.32151,-18.74808 -4.88593,-31.22671 15.75709,-37.91815 88.80162,-28.63454 162.27366,-80.41784 226.46245,-146.30741 18.20006,-18.62752 30.10949,-17.18073 43.30148,4.76237 29.43768,49.01027 58.38676,98.26168 87.39692,147.51308 2.93155,4.94322 4.82481,10.429 9.89401,21.46083 z" fill="#6282ea" /><path d="m 510.93327,222.03125 c 13.06984,26.46434 24.18531,47.62376 34.07931,69.44629 12.09265,26.64519 33.10211,39.42523 61.68475,42.62025 23.20813,2.59218 46.35518,6.14889 73.16667,9.76588 -17.52824,17.66299 -32.24708,34.12031 -48.73706,48.70886 -24.6739,21.88281 -35.78938,46.7195 -27.11687,79.87528 5.55774,21.40055 7.57318,43.76563 12.15373,71.49592 -24.91819,-13.44316 -45.56121,-23.63103 -65.22705,-35.38626 -26.56719,-15.79421 -52.1572,-16.57789 -79.09085,-0.54255 -19.91013,11.8758 -41.10281,21.76225 -66.14316,34.84371 4.33626,-27.00689 7.08459,-50.09537 11.90944,-72.82215 6.29062,-29.77992 -0.30537,-53.77264 -24.55176,-74.14838 -17.65039,-14.82967 -32.55245,-32.79408 -51.05787,-51.7833 25.28464,-3.49642 48.67599,-7.65597 72.25056,-9.82616 29.01015,-2.65247 49.46995,-15.07081 61.31831,-42.25855 9.64969,-22.54593 21.92557,-43.82591 35.36185,-69.98884 z" fill="#849ff8" /><path d="m 385.54832,822.63313 c -15.7571,-7.5354 -32.9189,-12.17721 -49.04244,-19.10979 -67.05927,-28.87567 -123.98025,-71.79733 -174.8549,-123.21893 -26.13968,-26.46434 -35.36186,-24.83669 -54.41695,7.65597 -23.452424,40.02807 -46.96592,80.11642 -70.112972,120.32534 92.962082,47.68912 196.205152,72.54532 300.972752,72.46045 16.79535,0 33.34641,-0.84397 49.8364,-2.04963 l 9.1611,-16.45732 c 3.17585,-5.66663 5.19129,-11.99637 9.34432,-21.76225 -6.77921,-5.96804 -12.82554,-13.98571 -20.88731,-17.84384 z" fill="#708ef2" /><path d="m 631.12694,392.51224 c 16.42891,-14.58854 31.20882,-31.04586 48.73706,-48.70885 -26.81149,-3.617 -49.95854,-7.23399 -73.16667,-9.76589 -28.64371,-3.19501 -49.5921,-15.97505 -61.68475,-42.62024 -9.894,-21.76225 -21.00947,-42.98195 -34.07931,-69.44629 -13.43628,26.16292 -25.71216,47.50319 -35.484,69.86827 -11.84836,27.24802 -32.24708,39.66637 -61.31831,42.25855 -23.57457,2.17019 -46.96592,6.32974 -72.25056,9.82616 18.5665,19.04951 33.46856,37.01391 51.05788,51.7833 24.18531,20.37574 30.84237,44.36847 24.55175,74.14838 -4.76377,2Line truncated
|
||||
zib_svgs['dingtalk'] = '<path d="M879.36 393.813a174.933 174.933 0 0 1-11.307 29.014v1.28c-32.853 70.186-118.4 208-118.4 208l-24.96 42.666h120.534l-231.04 306.56 52.266-208.64H571.52l32.853-138.026c-26.666 6.4-58.24 15.36-95.573 27.306 0 0-50.56 29.654-145.493-56.96 0 0-64-56.533-26.88-70.613a1098.24 1098.24 0 0 1 124.586-20.053c64-8.747 104.534-13.44 104.534-13.44s-199.68 2.986-247.04-4.48-106.667-86.614-120.32-156.16c0 0-19.84-38.187 42.666-20.054s320 70.4 320 70.4-335.786-103.04-357.973-128S137.813 124.8 143.36 56.107a15.147 15.147 0 0 1 20.053-13.44S411.52 156.16 581.333 218.453s317.227 94.72 298.027 175.36z"></path>';
|
||||
zib_svgs['huawei'] = '<path d="M436.8 136s-81.6-3.2-136 62.4-12.8 169.6 12.8 224c25.6 52.8 153.6 260.8 160 267.2 6.4 3.2 9.6 3.2 9.6 0s16-302.4 3.2-377.6c-9.6-75.2-43.2-166.4-49.6-176zM152 273.6c-9.6 0-75.2 68.8-81.6 132.8-6.4 65.6 22.4 110.4 100.8 160 78.4 56 264 156.8 270.4 152 3.2-9.6-72-145.6-136-243.2-60.8-97.6-144-201.6-153.6-201.6z m25.6 604.8c56 25.6 145.6-32 169.6-48 22.4-19.2 65.6-51.2 65.6-51.2l-320 11.2s28.8 64 84.8 88z m9.6-257.6C131.2 592 11.2 526.4 8 526.4S-14.4 608 24 672s110.4 81.6 142.4 84.8c38.4 6.4 256 3.2 256 0-8-3.2-177.6-107.2-235.2-136zM720 198.4c-52.8-65.6-136-62.4-136-62.4-6.4 9.6-41.6 100.8-51.2 176-12.8 72 3.2 371.2 3.2 377.6 0 3.2 6.4 6.4 9.6 0 6.4-3.2 136-214.4 160-267.2 27.2-54.4 64-155.2 14.4-224z m296 328c-3.2 0-123.2 65.6-179.2 94.4-56 28.8-230.4 132.8-230.4 136 0 3.2 217.6 6.4 256 0 32-6.4 104-25.6 142.4-84.8 33.6-64 14.4-145.6 11.2-145.6zM672 832c25.6 16 113.6 72 169.6 48 56-25.6 88-88 88-88L608 782.4c1.6-1.6 43.2 30.4 64 49.6z m278.4-422.4c-6.4-65.6-72-132.8-81.6-132.8-9.6 0-91.2 104-152 201.6-62.4 97.6-139.2 233.6-136 243.2 3.2 9.6 192-94.4 270.4-152 76.8-52.8 105.6-97.6 99.2-160z"></path>';
|
||||
zib_svgs['xiaomi'] = '<path d="M851.626667 853.333333a13.653333 13.653333 0 0 1-13.653334-13.653333V184.32a13.653333 13.653333 0 0 1 13.653334-13.653333h158.293333a13.653333 13.653333 0 0 1 14.08 13.653333v655.36a13.653333 13.653333 0 0 1-14.08 13.653333z m-265.386667 0s-12.8-3.84-12.8-13.653333v-402.346667A93.013333 93.013333 0 0 0 479.573333 341.333333H183.466667c-17.066667 0-12.8 12.8-12.8 12.8v485.546667c0 11.52-12.8 13.653333-12.8 13.653333H14.08a13.653333 13.653333 0 0 1-14.08-13.653333V184.32A13.653333 13.653333 0 0 1 14.08 170.666667h548.693333a182.613333 182.613333 0 0 1 181.333334 182.186666l0.426666 486.826667a13.653333 13.653333 0 0 1-13.653333 13.653333z m-294.4 0a12.8 12.8 0 0 1-12.8-12.8v-384a12.8 12.8 0 0 1 12.8-12.8h160.853333a12.8 12.8 0 0 1 12.373334 12.8v384a12.8 12.8 0 0 1-12.8 12.8z"></path>';
|
||||
zib_svgs['xunlei'] = '<path d="M124.154411 206.710498 261.74916 228.209956 405.364419 365.804705 619.497288 204.990897 993.583529 0.317738 769.990949 423.423404 1154.398608 573.917065 582.518882 726.132869 677.114716 1023.682262 576.498373 930.806028 388.164598 828.470084 171.451693 668.515441 100.074917 523.180582 126.733177 272.068036 0.317738 228.209956 83.735532 223.910318Z"></path>';
|
||||
zib_svgs['123pan'] = '<path d="M998.17244445 513.82044445c0 96.36977778 0.45511111 192.73955555-0.11377778 289.10933333-0.45511111 76.11733333-34.36088889 133.91644445-99.66933334 172.71466667-29.12711111 17.29422222-61.21244445 25.03111111-95.00444444 25.14488888-194.78755555 0.11377778-389.57511111 0.56888889-584.47644444-0.11377778-108.99911111-0.34133333-194.44622222-86.24355555-194.78755556-195.47022222-0.56888889-194.56-0.45511111-389.00622222 0-583.56622222 0.22755555-109.68177778 86.69866667-194.90133333 197.29066666-195.12888889 135.168-0.34133333 270.336-0.11377778 405.504-0.11377777 57.11644445 0 114.34666667-0.11377778 171.46311112 0 105.35822222 0.11377778 186.70933333 72.47644445 198.99733333 177.152 0.91022222 8.07822222 0.68266667 16.27022222 0.68266667 24.34844444 0.11377778 95.34577778 0.11377778 190.57777778 0.11377778 285.92355556zM258.27555555 286.94755555v80.4408889h132.096c12.06044445 0 24.00711111 0.68266667 35.72622223 3.5271111 28.10311111 6.59911111 41.52888889 23.89333333 40.96 53.13422223-0.45511111 24.34844445-16.95288889 42.55288889-43.008 47.55911111-19.22844445 3.64088889-38.68444445 1.47911111-58.02666667 2.048-53.02044445 1.59288889-90.112 29.12711111-106.496 79.53066666-5.91644445 18.20444445-8.64711111 37.09155555-8.76088889 56.20622223-0.11377778 40.61866667-0.11377778 81.12355555 0 121.74222222 0 3.072-0.91022222 6.37155555 1.59288889 9.216h309.02044444v-80.32711111H347.24977778c1.13777778-22.528-1.59288889-44.032 2.38933333-65.30844444 3.41333333-18.65955555 14.336-30.03733333 32.42666667-35.04355556 7.85066667-2.16177778 15.81511111-3.41333333 24.00711111-3.41333334 19.456-0.11377778 38.912 0.68266667 58.14044444-0.68266666 42.78044445-3.072 76.11733333-21.16266667 94.208-62.35022222 17.52177778-39.70844445 20.82133333-80.44088889 8.41955556-121.74222222-13.65333333-45.62488889-43.80444445-73.84177778-91.59111111-81.57866667-11.49155555-1.82044445-23.09688889-2.84444445-34.70222223-2.95822223-58.25422222-0.45511111-116.39466667-0.45511111-174.64888888-0.56888888-2.27555555 0-4.66488889 0.34133333-7.62311112 0.56888888z m363.52 373.3048889v79.41688888c1.25155555 0.56888889 1.93422222 1.024 2.50311112 1.024 60.30222222-0.45511111 120.71822222 3.29955555 180.79288888-2.84444444 32.99555555-3.41333333 61.55377778-17.52177778 83.62666667-43.008 34.816-40.16355555 37.66044445-129.82044445-25.48622222-176.58311111-3.18577778-2.38933333-7.168-3.98222222-9.216-8.41955556 19.456-12.40177778 36.18133333-26.73777778 46.76266667-47.104 40.39111111-77.36888889-14.67733333-172.71466667-102.05866667-175.21777777-56.43377778-1.59288889-112.86755555-0.79644445-169.30133333-1.13777778-2.38933333 0-4.77866667 0.34133333-7.28177778 0.56888888V367.50222222c39.02577778 0 77.14133333-0.11377778 115.25688889 0 8.76088889 0 17.74933333 0 26.39644444 1.25155556 28.55822222 4.20977778 42.78044445 23.32444445 41.75644445 55.06844444-0.91022222 28.10311111-15.13244445 42.43911111-44.032 45.51111111-28.55822222 3.072-57.11644445 0.91022222-85.67466667 1.70666667-3.75466667 0.11377778-7.73688889-1.25155555-11.264 1.59288889v77.71022222c4.55111111 2.16177778 8.87466667 1.13777778 12.97066667 1.25155556 28.21688889 0.91022222 56.43377778-1.70666667 84.53688888 1.82044444 18.54577778 2.27555555 33.792 9.67111111 39.936 28.21688889 6.94044445 21.16266667 7.39555555 42.43911111-7.50933333 61.32622222-4.89244445 6.25777778-11.49155555 10.35377778-19.11466667 12.62933333-9.55733333 2.84444445-19.22844445 4.43733333-29.1271111 4.43733334-37.43288889 0.11377778-74.752 0.11377778-112.1848889 0.22755556h-12.288z m-418.816 80.09955555V286.94755555H106.95111111v453.40444445h96.02844444z"></path>';
|
||||
zib_svgs['alipan'] = '<path d="M841.984 576.554667a18.816 18.816 0 0 1-13.184-21.973334c41.941333-200.448-75.605333-402.346667-269.226667-456.021333-199.509333-55.125333-405.333333 67.285333-459.52 273.109333v0.981334a460.586667 460.586667 0 0 0 62.464 371.2 439.893333 439.893333 0 0 0 208.768 167.765333c236.544 89.301333 491.178667-44.373333 566.272-283.349333a23.04 23.04 0 0 0-15.573333-29.269334l-80-22.442666z m-393.130667 194.133333c-72.704-20.010667-133.162667-68.266667-170.752-135.125333a298.112 298.112 0 0 1-28.288-219.989334C282.026667 293.12 404.48 220.501333 523.52 253.141333c112.64 31.232 182.4 146.346667 161.92 262.912a21.205333 21.205333 0 0 0 15.104 24.405334l75.605333 20.949333a17.493333 17.493333 0 0 1 11.733334 22.954667c-47.36 142.933333-195.114667 225.834667-338.986667 186.325333z"></path>';
|
||||
zib_svgs['quark'] = '<path d="M466.4832 1021.6448c-120.4736-10.6496-235.4176-65.024-317.6448-149.76-82.5344-85.2992-124.416-168.7552-144.4352-288.1024-5.2224-30.9248-5.9904-104.8064-1.28-135.2192 11.1616-75.1616 36.1472-146.432 70.2464-201.216C169.8816 91.6992 331.9296 0 509.952 0c75.9808 0 144.384 13.824 210.2784 42.6496 57.4976 25.2416 120.7296 70.144 163.1232 116.224 66.3552 72.0384 100.4544 133.376 125.44 225.9968 19.7632 73.0624 20.2752 175.7696 1.536 248.32-21.0944 80.384-49.7152 137.7792-101.2224 201.5232-44.7488 55.6544-91.8016 94.8736-153.7536 128.2048-65.0752 35.1232-125.184 52.5312-201.216 58.7776-37.1712 3.072-51.456 3.072-87.6544 0v-0.0512z m91.8528-260.5056c12.8-5.4784 22.6304-20.8384 22.6304-35.6352 0-25.4976 4.9664-54.3744 11.4688-67.072 13.312-26.0608 30.976-35.1232 84.5824-43.4688 20.7872-3.072 42.1376-7.5264 47.36-9.6256 14.848-6.5024 27.0848-18.944 35.1232-36.352 7.2704-15.872 7.5264-17.408 7.5264-58.0096-0.256-45.056-1.792-54.8864-17.408-95.232C726.4256 355.2768 665.6 294.912 605.184 273.1008a427.1104 427.1104 0 0 0-53.8624-13.5168c-28.6208-4.7104-34.048-4.9664-58.7776-2.048-48.896 5.632-79.104 15.3088-112.9472 35.584-21.3504 12.9536-22.8864 14.336-48.64 39.7312-37.7344 37.2224-57.2416 73.3696-69.2224 127.488-20.8384 94.8736 16.896 194.9696 96 255.3344 33.0752 25.1904 81.408 45.5168 116.5824 48.896 30.208 3.072 72.8576 1.28 84.0192-3.4304z"></path>';
|
||||
zib_svgs['360yunpan'] = '<path d="m 472.51068,161.14113 c 60.83076,-14.15228 126.70267,-4.36113 180.93361,26.95061 52.84075,29.64424 94.26521,79.41236 114.47191,137.13313 52.99522,2.75064 104.97941,22.06215 147.27448,54.58531 36.91691,28.14778 66.47572,66.12946 84.85692,109.12787 18.1566,42.11478 25.3321,88.98974 20.6561,134.71029 -4.311,45.52101 -20.5297,89.81635 -46.47966,127.19945 -21.44242,31.02669 -49.3302,57.44998 -81.22002,77.16055 -35.69525,22.11916 -76.5861,35.3878 -118.26332,38.76554 -45.22988,4.31837 -90.97933,-7.58208 -130.81702,-29.08841 -44.24694,-24.24272 -81.10768,-60.17212 -112.59027,-99.56475 -20.71223,-25.34013 -39.26196,-52.37625 -58.20488,-79.07033 -30.12049,-41.70145 -60.54992,-83.43143 -95.83794,-120.84304 -18.11441,-18.86969 -37.57689,-36.7275 -59.8478,-50.42372 -21.58284,-12.76982 -45.76349,-21.63459 -70.84284,-23.08831 -49.54085,-2.35158 -98.95531,22.83178 -127.78391,63.60686 -17.67913,24.71303 -27.873758,54.92737 -28.323104,85.498 -0.758274,31.51125 8.63594,63.13653 26.301024,89.06099 26.89079,40.19075 73.51085,65.80167 121.40875,66.34325 39.37431,0.96914 78.80477,-14.6226 107.12787,-42.41407 7.58278,-7.04051 13.28391,-16.44686 22.8326,-21.05027 17.11742,-9.33509 40.27299,-4.70318 52.3914,10.77454 12.21671,14.52283 12.89073,37.46862 1.36209,52.60428 -32.04427,39.30713 -76.97928,67.49766 -125.90227,79.19858 -53.89391,13.2259 -112.35155,6.39918 -161.72388,-19.31151 C 88.021513,805.19081 49.896971,765.44188 27.822651,717.7688 5.1725922,669.39738 -0.51448766,613.05907 12.165606,561.05337 27.710311,495.12344 72.813814,437.48819 131.93144,406.1907 c 34.3191,-18.32811 73.17384,-28.09077 111.97241,-27.44942 52.36332,1.4537 103.11179,22.07641 144.42391,54.30027 44.07843,34.36167 80.32131,77.67362 114.09278,122.15424 14.42133,19.5538 29.37626,38.72279 43.09547,58.78966 30.10646,42.44257 59.59506,86.2676 98.84298,120.70052 24.96701,21.84838 54.86282,38.62304 87.4688,44.87968 20.19266,4.31837 41.21382,2.32309 61.20989,-2.12355 45.932,-9.77691 87.21604,-38.83682 113.37663,-78.25796 25.68317,-38.29523 35.84971,-86.72366 28.39331,-132.3872 -7.24577,-46.34763 -32.84468,-89.26053 -69.59309,-117.65059 -32.05831,-25.15485 -72.54195,-38.89382 -113.03963,-38.56601 -16.76636,0.58432 -33.47657,2.23756 -50.20081,3.54874 -4.31095,-18.51339 -6.89472,-37.45435 -12.62393,-55.58295 -15.23578,-48.07212 -52.78459,-87.93509 -99.12381,-106.13494 -29.67115,-11.57266 -62.57199,-14.93614 -93.82991,-8.75075 -39.92194,7.62484 -76.90906,30.20008 -102.05862,62.60921 -4.90073,6.01436 -8.62191,12.96936 -13.98603,18.59891 -10.77035,11.07384 -27.69119,15.29244 -42.30911,10.68903 -17.08935,-4.83144 -29.83965,-21.67734 -30.20475,-39.66343 -0.50551,-10.21871 3.31396,-20.12387 9.21168,-28.27605 36.15864,-53.68743 92.88907,-92.52423 155.46107,-106.47698 z"></path>';
|
||||
zib_svgs['quick-reply'] = '<path d="m 179.78385,957.32954 c -1.28242,0 -2.56485,0 -3.84727,-0.1109 -11.86239,-1.10894 -23.08358,-5.7665 -33.34294,-13.86178 -9.93877,-8.53886 -16.99208,-19.07381 -21.05308,-31.49397 -4.27474,-11.86568 -5.12969,-24.72942 -2.56485,-38.25851 L 144.83787,750.17907 C 118.44137,715.80185 98.029502,678.87406 84.136607,640.61555 66.717054,594.26175 57.846975,546.02275 57.846975,497.11838 c 0,-116.21718 47.983925,-224.78265 135.188555,-305.95725 41.46495,-38.92388 89.66261,-69.53069 143.41743,-90.82239 55.57158,-22.067958 114.56295,-33.268277 175.26421,-33.268277 120.01324,0 232.97316,44.135917 318.1473,124.201567 42.31989,39.58925 75.66284,85.72126 98.85329,137.17619 24.15226,53.34014 36.33526,110.118 36.33526,168.78106 0,58.55216 -12.183,115.33002 -36.33526,168.67016 -23.29732,51.56582 -56.5334,97.69783 -98.85329,137.0653 -41.35808,39.03477 -89.55574,69.64159 -143.31056,90.93328 -55.46471,22.06796 -114.24234,33.15739 -174.83674,33.15739 -36.12153,0 -72.56366,-4.21399 -108.57832,-12.64195 -30.7781,-6.87544 -59.41884,-16.52324 -85.17413,-28.49982 l -107.40277,63.09883 c -10.1525,5.43382 -20.51873,8.31707 -30.7781,8.31707 z M 218.315,703.1843 c 8.90985,9.94875 11.90683,24.32595 8.16486,38.42286 l -21.66759,113.96248 92.84244,-56.73513 c 5.49391,-3.12668 11.40993,-4.80161 17.22808,-4.80699 5.10363,-0.005 9.82975,1.21507 14.19202,3.54741 26.2585,14.32759 53.54821,24.89992 81.09031,31.48882 27.42782,6.92275 56.79816,10.53104 87.55417,10.62277 96.61839,0.28816 189.45109,-36.18329 261.43825,-102.05382 34.06943,-31.03512 61.52411,-67.34852 81.27382,-107.74187 20.31719,-41.69312 31.60904,-85.84096 33.22364,-131.29316 1.61459,-45.45221 -6.44035,-89.61365 -24.05914,-131.34763 C 832.56463,326.81659 807.40587,290.33017 775.153,258.93272 706.68671,192.76093 615.37828,155.64637 518.72351,154.34459 421.8659,153.04007 330.7085,187.74814 260.66433,252.68328 c -32.89572,30.92644 -59.2654,67.00474 -78.27056,107.41033 -19.65321,41.81406 -30.47467,86.34652 -31.94304,132.05402 -1.21895,37.94379 4.14374,75.47175 15.80997,111.66854 11.86764,36.41723 29.26826,69.85306 52.0543,99.36813 z"/><path d="M 477.20695,739.84399 496.83654,549.14136 360.04496,463.97457 535.13819,245.87662 515.57699,436.65023 652.36857,521.81702 Z" />';
|
||||
zib_svgs['xiaohongshu'] = '<path d="M87.844571 423.533714H16.457143C22.674286 516.388571 0 586.971429 0 586.971429l38.4 69.741714c50.285714-21.467429 49.481143-233.142857 49.481143-233.142857z m159.707429 0s-1.243429 211.675429 49.517714 233.142857l38.4-69.741714s-22.674286-70.582857-16.530285-163.401143H247.552z m-115.163429 212.48H87.844571c0 52.845714 44.141714 57.380571 44.141715 57.380572h22.674285c45.385143 0 47.469714-51.968 47.469715-51.968V330.715429H132.388571v305.334857h0.036572z m239.762286-148.48h46.189714l-35.474285 72.155429s-20.626286 40.448 12.361143 42.057143h77.165714l30.939428-55.661715h-38.4c-4.900571 0-8.228571-5.376-5.741714-9.508571l57.344-112.64h-66.852571l-4.096 8.265143h-4.132572c-4.973714 0-8.265143-5.339429-5.778285-9.508572l47.872-91.977142h-66.852572l-56.941714 114.688s-20.626286 40.886857 12.397714 42.093714z m9.874286 136.521143s-8.630857 0.841143-14.006857-4.973714l-34.669715 66.486857s5.778286 7.826286 17.334858 7.826286h85.796571l36.754286-69.339429h-91.209143z"></path><path d="M640.731429 423.533714h44.141714v-70.948571h-157.622857v70.948571h44.982857v202.971429h-66.011429l-33.426285 66.889143h234.788571V626.468571H640.731429v-202.971428z m315.611428 52.406857h-8.228571v-45.787428a77.458286 77.458286 0 0 0-77.531429-77.568h-26.843428v-21.869714h-68.022858v21.467428h-42.971428v69.302857h42.934857v54.052572h-68.096v69.705143h68.132571v148.114285h68.022858v-148.114285h93.622857c9.142857 0 16.566857 7.424 16.566857 16.493714v73.069714h-64.768a58.514286 58.514286 0 0 0 58.587428 58.587429h17.737143A58.587429 58.587429 0 0 0 1024 634.806857v-91.611428a67.876571 67.876571 0 0 0-67.657143-67.254858z m-112.64-54.052571h24.393143a10.605714 10.605714 0 0 1 10.715429 10.715429v43.337142h-35.108572v-54.052571z"></path><path d="M1022.390857 386.413714a34.011429 34.011429 0 0 0-33.828571-33.828571 34.011429 34.011429 0 0 0-33.828572 33.828571v33.828572h33.828572a33.682286 33.682286 0 0 0 33.828571-33.828572z"></path>';
|
||||
zib_svgs['zhihu'] = '<path d="M578.958222 221.070222v595.114667h59.221334l21.504 74.638222 104.106666-74.638222H910.222222V221.070222z m264.021334 527.587556h-68.835556l-87.836444 66.787555-19.114667-66.787555h-18.090667V287.402667h193.877334zM544.540444 557.852444s0-63.601778-31.459555-67.128888-129.592889 0-129.592889 0V292.693333H529.066667s-1.706667-65.422222-29.752889-65.422222H262.883556l36.807111-108.088889s-59.505778 3.470222-80.611556 40.618667-89.315556 228.010667-89.315555 228.010667 22.755556 10.581333 61.326222-17.692445a153.6 153.6 0 0 0 50.801778-77.824l70.087111-3.470222 1.706666 201.557333s-120.888889-1.820444-145.294222 0-38.456889 67.128889-38.456889 67.128889h183.921778a620.088889 620.088889 0 0 1-63.032889 192.625778 551.424 551.424 0 0 1-136.533333 145.009778 154.851556 154.851556 0 0 0 127.772444-10.581334c63.032889-37.091556 109.568-200.419556 109.568-200.419555l147.911111 182.670222a266.24 266.24 0 0 0-2.389333-111.559111c-15.872-24.576-102.4-123.278222-102.4-123.278222l-37.660444 33.621333 26.851555-108.088889z"></path>';
|
||||
zib_svgs['douyin'] = '<path d="M466.375111 390.940444v165.831112a147.911111 147.911111 0 0 0-146.545778 29.525333 128 128 0 0 0-14.336 161.052444 138.24 138.24 0 0 0 250.311111-70.940444V56.888889h168.391112a225.109333 225.109333 0 0 0 229.888 215.267555v158.208a321.934222 321.934222 0 0 1-131.584-18.716444 564.736 564.736 0 0 1-97.564445-47.843556v326.769778a284.444444 284.444444 0 0 1-208.782222 260.437334A293.489778 293.489778 0 1 1 466.488889 391.054222z"></path>';
|
||||
zib_svgs['bilibili'] = '<path d="M755.904 52.16c20.8 23.232 21.12 49.344 1.152 70.976l-5.44 5.312-57.408 51.328 128 0.064c41.728 0 81.984 13.44 113.856 37.44l10.24 8.384 8.832 8.32a158.4 158.4 0 0 1 46.336 101.12l0.384 12.544v391.04c0 89.28-75.456 161.92-169.6 167.168l-16.384 0.256-0.128 2.432-0.64 4.48-1.088 4.352-2.88 8.512a68.8 68.8 0 0 1-54.592 41.984l-8.96 0.64-9.088-0.64a69.056 69.056 0 0 1-54.72-41.92 68.544 68.544 0 0 1-4.672-17.408l-0.128-2.432H348.544l-0.128 2.432-0.64 4.48-1.088 4.352-2.88 8.512a68.736 68.736 0 0 1-54.592 41.984l-8.96 0.64-9.152-0.64a68.864 68.864 0 0 1-59.328-59.328l-0.128-2.432h-5.44c-91.776 0-168.192-63.808-179.2-146.752L25.856 748.8l-0.32-10.24V347.392c0-89.344 75.456-161.984 169.6-167.232l11.008-0.32 126.976-0.064-57.408-51.392c-21.12-18.88-25.664-42.048-13.248-63.872l4.224-6.528 4.736-5.888c20.864-23.296 46.72-26.432 70.4-8.96l5.952 4.736 147.456 131.904h36.8l147.52-131.84c25.216-22.592 53.76-20.992 76.288 4.224z m66.304 240.448H206.208c-35.328 0-63.488 21.888-67.392 48.512l-0.448 6.272v391.232c0 27.328 25.728 51.136 59.84 54.4l8 0.384h615.04c35.264 0 63.488-21.824 67.328-48.512l0.448-6.272V346.688a46.016 46.016 0 0 0-14.208-33.472 73.792 73.792 0 0 0-52.608-20.608zM512 609.472a49.28 49.28 0 0 1 32.896 12.992l4.928 5.248 19.712 24.32 28.8-21.376c4.48-3.2 9.6-5.312 14.912-6.144l5.376-0.448 5.44 0.384a35.008 35.008 0 0 1 19.968 58.688l-4.16 3.776-44.224 33.024a49.216 49.216 0 0 1-62.976-3.2l-4.928-5.312-16.576-20.352-16.96 20.224a49.472 49.472 0 0 1-18.368 13.44l-7.232 2.496-7.616 1.28a49.472 49.472 0 0 1-29.44-6.592l-6.4-4.48-38.784-32a35.008 35.008 0 0 1 40-57.088l4.48 3.2 23.04 18.944 19.84-23.36a49.28 49.28 0 0 1 6.848-6.72l3.84-2.816 6.272-3.456A49.792 49.792 0 0 1 512 609.472zM388.672 404.544l6.72 0.768a50.56 50.56 0 0 1 40.704 39.424 51.392 51.392 0 0 1-32.384 58.752l-6.592 1.92-156.16 35.584A51.008 51.008 0 0 1 211.84 443.52l7.616-2.24 155.84-35.456a50.56 50.56 0 0 1 13.44-1.28z m243.392 0.704a50.56 50.56 0 0 1 13.44-0.576l6.656 1.088 155.584 35.392a51.008 51.008 0 0 1-13.44 100.8l-8.128-1.024-155.776-35.52a51.392 51.392 0 0 1-31.36-78.72 50.56 50.56 0 0 1 33.024-21.44z"></path>';
|
||||
zib_svgs['manual-service'] = '<path d="M927.616 465.6C923.328 236.704 745.888 51.808 528 51.808h-32c-217.888 0-395.328 184.896-399.616 413.76C58.112 487.744 32 528.672 32 576v64c0 70.592 57.408 128 128 128s128-57.408 128-128v-64a128.064 128.064 0 0 0-126.784-127.872C173.728 262.688 318.912 115.808 496 115.808h32c177.12 0 322.272 146.88 334.784 332.32A128.064 128.064 0 0 0 736 576v64c0 57.792 38.72 106.176 91.392 122.016a337.504 337.504 0 0 1-191.936 124.48A79.712 79.712 0 0 0 560 832a80 80 0 1 0 0 160 79.68 79.68 0 0 0 67.872-38.112 402.432 402.432 0 0 0 278.24-193.6C955.968 742.816 992 695.776 992 640v-64c0-47.328-26.112-88.256-64.384-110.4zM224 576v64c0 35.296-28.704 64-64 64s-64-28.704-64-64v-64c0-35.296 28.704-64 64-64s64 28.704 64 64z m704 64c0 34.304-27.2 62.176-61.12 63.712l-2.496-1.184c-0.224 0.512-0.576 0.928-0.8 1.408A64 64 0 0 1 800 640v-64c0-35.296 28.704-64 64-64s64 28.704 64 64v64z"></path>';
|
||||
zib_svgs['cart-color'] = '<path d="M662.664533 48.264533a68.266667 68.266667 0 0 0-96.529066 0l-98.269867 98.269867c-21.504 21.504-6.280533 58.2656 24.132267 58.2656h244.804266c30.378667 0 45.636267-36.7616 24.132267-58.2656l-98.269867-98.269867zM307.2 921.6a68.266667 68.266667 0 1 1-136.533333 0 68.266667 68.266667 0 0 1 136.533333 0z m614.4 0a68.266667 68.266667 0 1 1-136.533333 0 68.266667 68.266667 0 0 1 136.533333 0z" fill="#FFAA44"></path><path d="M68.266667 85.333333a51.2 51.2 0 1 0 0 102.4h26.7264l116.565333 553.6768A119.466667 119.466667 0 0 0 328.465067 836.266667H853.333333a51.2 51.2 0 0 0 0-102.4H328.465067a17.066667 17.066667 0 0 1-16.725334-13.550934L303.854933 682.666667h535.552a68.266667 68.266667 0 0 0 65.3312-48.5376l92.740267-307.2A68.266667 68.266667 0 0 0 932.078933 238.933333H210.397867l-18.056534-85.845333A85.333333 85.333333 0 0 0 108.8512 85.333333H68.266667z" fill="#FF7744"></path>';
|
||||
zib_svgs['stars'] = '<path d="M 473.73666,490.74259 C 417.74677,530.94046 269.11702,368.74073 200.19253,368.35146 131.26805,367.96219 -19.184302,528.47276 -74.71657,487.64503 -130.24884,446.81731 -21.916855,255.33954 -42.845473,189.66817 -63.77409,123.9968 -262.92104,30.508605 -241.25199,-34.92218 -219.58293,-100.35297 -4.0003267,-56.493013 51.989562,-96.690881 107.97945,-136.88875 135.35221,-355.1782 204.27669,-354.78892 c 68.92449,0.38927 93.82988,218.97398 149.36215,259.801704 55.53227,40.827721 271.59652,-0.594383 292.52514,65.076987 20.92861,65.671373 -179.26161,156.904199 -200.93067,222.334989 -21.66905,65.43078 84.49323,258.11996 28.50335,298.31783 z" transform="translate(308.53618,451.87188)"></path><path d="m 515.57711,682.82266 c 0,68.92559 1.89661,136.38831 -6.30807,136.34197 -68.92448,-0.38927 -219.37683,160.1213 -274.9091,119.29357 -55.53227,-40.82772 52.79971,-232.30549 31.8711,-297.97686 C 245.30242,574.80997 46.155472,481.32177 67.824522,415.89099 89.493582,350.4602 305.07618,394.32016 361.06607,354.12229 417.05596,313.92442 444.42762,96.024245 513.3532,96.024245 c 4.89415,0 -0.26694,216.611625 -0.26694,349.172885 0,104.27441 2.49085,170.38116 2.49085,237.62553 z" style="fill: var(--active-half-color, rgba(0,0,0,0%));stroke:rgba(0,0,0,0%)"></path>';
|
||||
zib_svgs['check-circle'] = '<path d="M512 981.333333C252.8 981.333333 42.666667 771.2 42.666667 512S252.8 42.666667 512 42.666667s469.333333 210.133333 469.333333 469.333333-210.133333 469.333333-469.333333 469.333333z m0-85.333333c212.074667 0 384-171.925333 384-384S724.074667 128 512 128 128 299.925333 128 512s171.925333 384 384 384z m-161.834667-414.165333L448 579.669333l225.834667-225.834666a42.666667 42.666667 0 0 1 60.330666 60.330666l-256 256a42.666667 42.666667 0 0 1-60.330666 0l-128-128a42.666667 42.666667 0 0 1 60.330666-60.330666z"></path>';
|
||||
zib_svgs['shopping-cart'] = '<path d="M789.488 724.2H359.632c-94.584 0-117.384-60.072-134.056-126.992L100.408 66.76H61.96a33.376 33.376 0 0 1 0-66.76h64.864a33.384 33.384 0 0 1 32.488 25.72l131.136 555.744c17.456 70.056 31.208 75.984 69.184 75.984h429.848c12.752 0 51.48 0 69.168-75.88l63.304-252.2c10.008-39.864 8.672-70.768-3.784-87.048-9.424-12.304-27.312-18.792-53.224-19.248H344.64a33.368 33.368 0 0 1-33.376-33.384 33.36 33.36 0 0 1 33.376-33.376h520.936c47.88 0.864 83.216 16.152 105.608 45.44 25.824 33.736 31.04 82.144 15.52 143.88l-63.176 251.616c-25.688 110.4-95.024 126.952-134.04 126.952zM295.448 1024c-68.864 0-124.88-56.032-124.88-124.88 0-68.84 56.016-124.872 124.88-124.872 68.84 0 124.88 56.032 124.88 124.872 0 68.848-56.032 124.88-124.88 124.88z m0-183c-32.04 0-58.12 26.08-58.12 58.12 0 32.048 26.08 58.128 58.12 58.128s58.12-26.08 58.12-58.128c0-32.04-26.072-58.12-58.12-58.12zM827.104 1024c-68.84 0-124.872-56.032-124.872-124.88 0-68.84 56.032-124.872 124.872-124.872 68.848 0 124.88 56.032 124.88 124.872 0 68.848-56.032 124.88-124.88 124.88z m0-183c-32.04 0-58.12 26.08-58.12 58.12 0 32.048 26.08 58.128 58.12 58.128 32.048 0 58.128-26.08 58.128-58.128-0.008-32.04-26.08-58.12-58.128-58.12z"></path>';
|
||||
zib_svgs['img-lists'] = '<path d="M362.73 362.49V163.46H163.71v199.03h199.02z m0-298.54c54.96 0 99.51 44.55 99.51 99.51v199.03c0 54.96-44.55 99.51-99.51 99.51H163.71c-54.96 0-99.51-44.55-99.51-99.51V163.46c0-54.96 44.55-99.51 99.51-99.51h199.02z m0 796.1V661.03H163.71v199.02h199.02z m0-298.54c26.39 0 51.7 10.49 70.36 29.15a99.493 99.493 0 0 1 29.15 70.37v199.02a99.51 99.51 0 0 1-99.51 99.51H163.71c-26.39 0-51.7-10.48-70.36-29.14a99.493 99.493 0 0 1-29.15-70.37V661.03c0-26.39 10.48-51.71 29.15-70.37a99.512 99.512 0 0 1 70.36-29.15h199.02z m248.78-348.3c-27.47 0-49.74-22.28-49.74-49.75s22.27-49.75 49.74-49.76h298.54c27.48 0.01 49.75 22.28 49.75 49.76 0 27.48-22.27 49.75-49.75 49.75H611.51z m298.54 99.52c27.48 0 49.75 22.28 49.75 49.76 0 27.48-22.28 49.76-49.75 49.76H611.51c-27.47 0-49.76-22.28-49.76-49.76 0-27.48 22.28-49.76 49.76-49.76h298.54z m0 298.53c27.48 0 49.75 22.28 49.75 49.76 0 27.48-22.28 49.75-49.75 49.75H611.51c-27.47 0-49.76-22.28-49.76-49.75 0-27.48 22.28-49.76 49.76-49.76h298.54z m0 199.03c27.48 0.01 49.75 22.28 49.75 49.76 0 27.48-22.27 49.76-49.75 49.76H611.51c-27.47 0-49.74-22.28-49.74-49.76 0-27.47 22.27-49.75 49.74-49.76h298.54z m0 0"></path>';
|
||||
zib_svgs['wallet'] = '<path d="M812 912H212c-71.68 0-130-58.32-130-130V242c0-16.57 13.43-30 30-30h700c71.68 0 130 58.32 130 130v440c0 71.68-58.32 130-130 130zM142 272v510c0 38.59 31.41 70 70 70h600c38.59 0 70-31.41 70-70V342c0-38.59-31.41-70-70-70H142z"></path><path d="M792 272H112c-16.57 0-30-13.43-30-30 0-71.68 58.32-130 130-130h480c71.68 0 130 58.32 130 130 0 16.57-13.44 30-30 30z m-643.24-60h606.48c-11.25-23.63-35.37-40-63.24-40H212c-27.87 0-51.98 16.37-63.24 40zM912 712H712c-82.71 0-150-67.29-150-150s67.29-150 150-150h200c16.56 0 30 13.43 30 30v240c0 16.56-13.44 30-30 30zM712 472c-49.63 0-90 40.37-90 90s40.37 90 90 90h170V472H712z"></path><path d="M708.33 562m-30 0a30 30 0 1 0 60 0 30 30 0 1 0-60 0Z"></path>';
|
||||
zib_svgs['gift'] = '<path d="M838.174758 140.444683 180.850951 140.444683c-50.327222 0-91.27482 40.977273-91.27482 91.304496l0 562.711985c0 50.327222 40.947598 91.27482 91.27482 91.27482l657.323806 0c50.327222 0 91.27482-40.947598 91.27482-91.27482l0-225.270627 0-23.254633 0-314.185702C929.449577 181.422979 888.503003 140.444683 838.174758 140.444683zM833.695746 197.597357c21.315468 0 38.632879 17.317411 38.632879 38.632879l0 151.072741-221.182518-0.361227-0.029676-189.344393L833.695746 197.597357zM591.498612 197.597357l0.060375 387.647831-55.288211-33.341363-5.65172-2.856048-0.330528 0.63138c-8.267291-2.795673-17.407462-1.923816-24.802896 2.52552-1.202385 0.751107-2.013867 1.593288-1.864464 1.804089l-53.18327 29.582759-0.060375-385.994168L591.498612 197.597357zM146.698107 236.229213c0-21.315468 17.317411-38.632879 38.632879-38.632879l205.428719 0 0.029676 189.735295-244.091274-0.390903L146.698107 236.229213zM872.327602 789.982152c0 21.315468-17.317411 38.632879-38.632879 38.632879L185.330986 828.615031c-21.315468 0-38.632879-17.317411-38.632879-38.632879L146.698107 446.528869l244.12095 0.361227 0.029676 187.209776c0 19.301602 19.180851 35.024701 38.422078 28.319999l0.51063 0.842181 91.454922-50.808176 84.811618 51.560306c13.709233 8.116865 32.800034 3.1569 40.857547-10.432607 2.885723-4.869914 4.118807-10.642384 3.698229-16.174378 0.029676-0.090051 0.060375-0.180102 0.090051-0.270153l0.480954-0.51063-0.029676-190.095499 221.182518 0.361227 0 99.287307 0 23.074531L872.327602 789.982152z"></path>';
|
||||
zib_svgs['transit'] = '<path d="M170.666667 810.666667h22.4a116.693333 116.693333 0 0 0 232.533333 0h236.8A117.034667 117.034667 0 0 0 896 800v-1.109333A84.970667 84.970667 0 0 0 938.666667 725.333333V192a85.333333 85.333333 0 0 0-85.333334-85.333333H384a85.333333 85.333333 0 0 0-85.333333 85.333333v85.333333H166.4L85.333333 452.266667V725.333333a85.333333 85.333333 0 0 0 85.333334 85.333334z m138.666666 42.666666a53.333333 53.333333 0 1 1 53.333334-53.333333 53.333333 53.333333 0 0 1-53.333334 53.333333z m469.333334 0a53.333333 53.333333 0 1 1 53.333333-53.333333 53.333333 53.333333 0 0 1-53.333333 53.333333zM149.333333 469.610667L203.093333 341.333333h127.573334a32 32 0 0 0 32-32V192a21.333333 21.333333 0 0 1 21.333333-21.333333h469.333333a21.333333 21.333333 0 0 1 21.333334 21.333333v533.333333a20.949333 20.949333 0 0 1-1.216 6.016 116.522667 116.522667 0 0 0-198.741334 15.317334H413.290667a116.437333 116.437333 0 0 0-207.914667 0H170.666667a21.333333 21.333333 0 0 1-21.333334-21.333334V469.610667z"></path><path d="M416 618.666667h-128a32 32 0 0 1-32-32v-128a32 32 0 0 1 64 0V554.666667h96a32 32 0 0 1 0 64z"></path>';
|
||||
zib_svgs['return'] = '<path d="M951.12173955 322.41304355c1.95652177 4.06956533 3.05217422 8.64782578 3.05217334 13.5v465.65217422a148.69565244 148.69565244 0 0 1-148.69565244 148.69565156H218.52173955a148.69565244 148.69565244 0 0 1-148.69565244-148.69565156V335.91304356c0-5.00869599 1.17391289-9.78260888 3.28695644-13.96956534l0.31304356-0.86086934 77.32173867-184.10869599A109.56521778 109.56521778 0 0 1 251.74347822 69.82608711h520.51304355a109.56521778 109.56521778 0 0 1 100.99565245 67.14782578l77.32173867 184.10869599 0.54782666 1.33043468zM891.56521777 367.21739112H132.43478223v434.34782665A86.08695645 86.08695645 0 0 0 218.52173955 887.65217422h586.9565209a86.08695645 86.08695645 0 0 0 86.08695732-86.08695645V367.21739112z m-76.03043555-206.02173868a46.95652177 46.95652177 0 0 0-43.27826044-28.76087022H251.74347822a46.95652177 46.95652177 0 0 0-43.27826044 28.76087022L148.20434756 304.60869599h727.55217422l-60.22173956-143.41304355z"></path><path d="M478.66086933 459.56521778A31.30434756 31.30434756 0 1 0 434.13043467 415.58260888l-94.34347822 95.51739112a35.21739112 35.21739112 0 0 0 25.04347822 59.98695644H551.13043467a86.08695645 86.08695645 0 1 1 0 172.1739129h-195.65217422a31.30434756 31.30434756 0 1 0 0 62.60869599h195.65217422a148.69565244 148.69565244 0 0 0 0-297.39130488H430.37391289l48.28695644-48.91304268z"></path>';
|
||||
zib_svgs['handbag'] = '<path d="M 331.34545,70.181818 H 733.56364 C 810.50964,70.18004 875.87959,126.46987 887.3,202.56364 l 85.90909,572.72727 C 987.316,869.28471 914.51924,953.82038 819.47273,953.81818 H 245.43636 C 150.38985,953.82038 77.593096,869.28471 91.7,775.29091 L 177.60909,202.56364 C 189.0295,126.46987 254.39945,70.18004 331.34545,70.181818 Z m 13.3618,75.172222 c -44.55961,-0.006 -79.98583,39.8842 -86.58876,83.95189 l -84.69438,537.50071 c -9.37709,57.61281 37.8843,111.84693 101.16528,111.83932 l 513.3009,1.21471 c 67.78584,0.007 117.28345,-55.57036 107.23882,-110.62462 L 805.57589,229.30593 c -6.60293,-44.06769 -44.45857,-81.52829 -89.01818,-81.52247 z" /><path d="m 315.63636,307.45455 c 0,119.74545 97.07281,216.81808 216.81819,216.81808 119.74537,0 216.81818,-97.07263 216.81818,-216.81808 0.003,-18.0769 -14.65039,-32.73266 -32.72728,-32.73266 -18.07688,0 -40.01851,14.65576 -40.01552,32.73266 6.7e-4,83.59636 -58.04966,138.00299 -141.64597,138.00299 -83.5963,0 -144.07606,-53.19192 -144.07538,-136.78829 0.003,-18.07688 -24.36807,-33.94733 -42.44494,-33.94733 -18.07687,0 -32.73024,14.65574 -32.72728,32.73263 z" />';
|
||||
zib_svgs['ucpan'] = '<path d="M742.570285 899.760318a240.183062 240.183062 0 1 0-217.137778 124.239682h3.943304l316.027649-0.358482A126.134516 126.134516 0 0 0 742.570285 899.760318z m-253.498114 34.158231l22.225895-119.118508-110.3613 0.409694 173.095682-186.205888-17.872897 122.908177 101.24561-0.409694z m-194.092496-395.405847l312.391616-312.033134-0.358482-0.819387A309.2677 309.2677 0 0 0 0.000051 309.442588h124.239682A423.879574 423.879574 0 0 0 271.934392 1004.949233a338.765662 338.765662 0 0 1-81.375455-220.722601v-2.765434a339.943532 339.943532 0 0 1 104.420738-242.948496z m624.783232 150.818575a62.529535 62.529535 0 1 0 0 125.05907 62.529535 62.529535 0 0 0 0-125.05907zM851.139175 271.597112a241.258509 241.258509 0 0 0 4.762692-48.395095A247.147859 247.147859 0 0 0 839.872592 135.527518l-307.270442 307.270441a340.609285 340.609285 0 0 1 294.160236 169.562073h181.596832a263.996521 263.996521 0 0 0 15.875639-90.542357A267.47892 267.47892 0 0 0 851.139175 271.597112z"></path>';
|
||||
zib_svgs['yidongyun'] = '<path d="M1020.16 266.88c-44.16 11.52-88.32 21.12-133.12 30.08-28.8 5.76-57.6 11.52-87.04 14.08-35.84 3.84-71.04 5.12-106.88 7.04-81.92 3.84-163.84 2.56-245.76 1.92-64.64-0.64-129.92 0-193.28 13.44-56.96 12.16-111.36 30.08-159.36 64-30.08 21.12-59.52 43.52-94.72 55.68 1.92 5.76 7.04 4.48 10.88 4.48 37.76 1.28 75.52-1.92 112.64-6.4 24.96-3.2 50.56-6.4 75.52-10.24 32-5.12 64-6.4 96-8.32 17.92-1.28 35.84-1.92 53.76 1.28 12.8 1.92 16.64 9.6 10.88 21.12-3.2 7.04-8.96 12.8-14.08 18.56-14.72 15.36-32 28.16-48 42.24-40.96 36.48-80.64 75.52-119.04 115.2-21.12 21.76-41.6 44.16-53.76 72.32-29.44 68.48-26.88 134.4 17.28 195.2 33.92 46.72 85.76 65.28 140.16 75.52 28.16 5.12 56.96 3.2 85.76 3.2 87.04 0 174.08-0.64 261.12 1.28 51.84 1.28 103.04 1.28 154.24-7.04 52.48-8.32 95.36-34.56 125.44-77.44 42.88-60.8 54.4-128.64 37.12-200.96-12.16-51.2-37.12-94.72-80.64-126.08-69.76-49.28-147.84-64-231.68-48.64-32.64 5.76-61.44 20.48-83.2 45.44-43.52 49.92-47.36 107.52-27.52 167.04 17.28 52.48 81.92 81.28 136.96 65.28 24.96-7.04 44.8-21.76 55.04-46.08 8.32-18.56 1.92-35.2-15.36-42.24-2.56 26.88-14.72 38.4-42.88 39.04H640a54.912 54.912 0 0 1-53.12-56.32c0-31.36 26.88-67.84 59.52-78.72 51.84-17.28 98.56-8.32 140.16 27.52 40.96 36.48 55.04 97.92 30.72 140.8-24.32 43.52-64 67.84-111.36 78.08-40.96 8.32-82.56 8.96-124.16 10.88-44.16 1.92-88.32 1.28-132.48-1.28-33.28-1.92-67.2-4.48-99.84-11.52-28.8-6.4-56.96-14.72-79.36-35.2a61.696 61.696 0 0 1-21.76-51.84c2.56-34.56 17.28-64.64 39.68-90.88a3790.08 3790.08 0 0 1 190.72-202.24c25.6-25.6 56.96-40.32 92.8-43.52 32-2.56 63.36-3.84 95.36-5.76 58.88-3.84 117.12-11.52 174.72-27.52 64-17.28 120.96-46.72 161.92-101.12 7.68-9.6 15.36-19.2 18.56-32h-3.84zM869.12 44.8c0 7.68-3.84 13.44-7.04 19.2-19.2 35.84-49.92 58.88-84.48 77.44-48 26.24-99.84 41.6-153.6 49.28-65.92 9.6-132.48 8.32-199.04 7.04-78.08-1.92-156.16 1.92-232.96 16.64-23.04 4.48-46.08 6.4-69.12 9.6-3.84 0-8.32 1.28-14.08 1.92 1.92-1.92 3.2-2.56 4.48-3.84 13.44-7.04 24.32-17.28 33.92-28.8 40.32-48.64 91.52-75.52 153.6-85.12 44.8-7.04 90.24-7.68 135.68-9.6 65.92-1.92 131.2-1.28 197.12-6.4 78.08-5.76 154.24-22.4 228.48-46.08 1.92 0 3.84-0.64 6.4-1.28z"></path>';
|
||||
zib_svgs['translate'] = '<path d="M938.666667 981.333333c-17.066667 0-29.866667-8.533333-38.4-25.6l-59.733334-119.466666h-277.333333l-59.733333 119.466666c-8.533333 21.333333-34.133333 29.866667-55.466667 17.066667-25.6-8.533333-34.133333-34.133333-21.333333-51.2l72.533333-140.8 145.066667-290.133333c12.8-21.333333 34.133333-38.4 59.733333-38.4s46.933333 12.8 59.733333 38.4l145.066667 290.133333 72.533333 140.8c8.533333 21.333333 0 46.933333-17.066666 55.466667-12.8 4.266667-17.066667 4.266667-25.6 4.266666z m-332.8-226.133333h192l-98.133334-192-93.866666 192zM85.333333 844.8c-17.066667 0-29.866667-8.533333-38.4-25.6-8.533333-21.333333 0-46.933333 21.333334-55.466667 93.866667-46.933333 179.2-110.933333 247.466666-187.733333-46.933333-64-85.333333-128-110.933333-192-8.533333-21.333333 4.266667-46.933333 25.6-55.466667 21.333333-8.533333 46.933333 4.266667 55.466667 25.6 21.333333 51.2 46.933333 102.4 81.066666 149.333334 59.733333-85.333333 102.4-179.2 128-281.6H85.333333c-25.6 0-42.666667-17.066667-42.666666-42.666667s17.066667-42.666667 42.666666-42.666667h243.2V85.333333c0-25.6 17.066667-42.666667 42.666667-42.666666s42.666667 17.066667 42.666667 42.666666v51.2h238.933333c25.6 0 42.666667 17.066667 42.666667 42.666667s-17.066667 42.666667-42.666667 42.666667h-68.266667c-25.6 128-85.333333 247.466667-162.133333 349.866666l25.6 25.6c17.066667 17.066667 17.066667 42.666667 0 59.733334-17.066667 17.066667-42.666667 17.066667-59.733333 0l-17.066667-17.066667c-72.533333 81.066667-162.133333 149.333333-264.533333 200.533333-8.533333 0-17.066667 4.266667-21.333334 4.266667z"></path>';
|
||||
zib_svgs['qqww'] = '';
|
||||
|
||||
function show_svg() {
|
||||
$('[data-svg]').each(function () {
|
||||
var _t = $(this),
|
||||
viewbox = _t.attr('data-viewbox'),
|
||||
svgclass = _t.attr('data-class'),
|
||||
svgname = _t.attr('data-svg'),
|
||||
svg_html = '<svg class="' + svgclass + '" viewBox="' + viewbox + '">' + zib_svgs[svgname] + '</svg>';
|
||||
_t.html(svg_html);
|
||||
});
|
||||
}
|
||||
|
||||
(function ($) {
|
||||
var svg = '';
|
||||
for (let key in zib_svgs) {
|
||||
svg += zib_svgs[key] ? '<symbol id="icon-' + key + '" viewBox="0 0 1024 1024">' + zib_svgs[key] + '</symbol>' : '';
|
||||
}
|
||||
|
||||
var i = '<svg id="svg-icons" aria-hidden="true" style="position:absolute;width:0px;height:0px;overflow:hidden;">' + svg + '</svg>';
|
||||
if (!$('svg#svg-icons').length) {
|
||||
$('body').prepend(i);
|
||||
}
|
||||
})(jQuery);
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Swiper 11.2.10
|
||||
* Most modern mobile touch slider and framework with hardware accelerated transitions
|
||||
* https://swiperjs.com
|
||||
*
|
||||
* Copyright 2014-2025 Vladimir Kharlampidi
|
||||
*
|
||||
* Released under the MIT License
|
||||
*
|
||||
* Released on: June 28, 2025
|
||||
*/
|
||||
|
||||
var Swiper=function(){"use strict";function e(e){return null!==e&&"object"==typeof e&&"constructor"in e&&e.constructor===Object}function t(s,a){void 0===s&&(s={}),void 0===a&&(a={});const i=["__proto__","constructor","prototype"];Object.keys(a).filter((e=>i.indexOf(e)<0)).forEach((i=>{void 0===s[i]?s[i]=a[i]:e(a[i])&&e(s[i])&&Object.keys(a[i]).length>0&&t(s[i],a[i])}))}const s={body:{},addEventListener(){},removeEventListener(){},activeElement:{blur(){},nodeName:""},querySelector:()=>null,querySelectorAll:()=>[],getElementById:()=>null,createEvent:()=>({initEvent(){}}),createElement:()=>({children:[],childNodes:[],style:{},setAttribute(){},getElementsByTagName:()=>[]}),createElementNS:()=>({}),importNode:()=>null,location:{hash:"",host:"",hostname:"",href:"",origin:"",pathname:"",protocol:"",search:""}};function a(){const e="undefined"!=typeof document?document:{};return t(e,s),e}const i={document:s,navigator:{userAgent:""},location:{hash:"",host:"",hostname:"",href:"",origin:"",pathname:"",protocol:"",search:""},history:{replaceState(){},pushState(){},go(){},back(){}},CustomEvent:function(){return this},addEventListener(){},removeEventListener(){},getComputedStyle:()=>({getPropertyValue:()=>""}),Image(){},Date(){},screen:{},setTimeout(){},clearTimeout(){},matchMedia:()=>({}),requestAnimationFrame:e=>"undefined"==typeof setTimeout?(e(),null):setTimeout(e,0),cancelAnimationFrame(e){"undefined"!=typeof setTimeout&&clearTimeout(e)}};function r(){const e="undefined"!=typeof window?window:{};return t(e,i),e}function n(e){return void 0===e&&(e=""),e.trim().split(" ").filter((e=>!!e.trim()))}function l(e,t){return void 0===t&&(t=0),setTimeout(e,t)}function o(){return Date.now()}function d(e,t){void 0===t&&(t="x");const s=r();let a,i,n;const l=function(e){const t=r();let s;return t.getComputedStyle&&(s=t.getComputedStyle(e,null)),!s&&e.currentStyle&&(s=e.currentStyle),s||(s=e.style),s}(e);return s.WebKitCSSMatrix?(i=l.transform||l.webkitTransform,i.split(",").length>6&&(i=i.split(", ").map((e=>e.replace(",","."))).join(", ")),n=new s.WebKitCSSMatrix("none"===i?"":i)):(n=l.MozTransform||l.OTransform||l.MsTransform||l.msTransform||l.transform||l.getPropertyValue("transform").replace("translate(","matrix(1, 0, 0, 1,"),a=n.toString().split(",")),"x"===t&&(i=s.WebKitCSSMatrix?n.m41:16===a.length?parseFloat(a[12]):parseFloat(a[4])),"y"===t&&(i=s.WebKitCSSMatrix?n.m42:16===a.length?parseFloat(a[13]):parseFloat(a[5])),i||0}function c(e){return"object"==typeof e&&null!==e&&e.constructor&&"Object"===Object.prototype.toString.call(e).slice(8,-1)}function p(){const e=Object(arguments.length<=0?void 0:arguments[0]),t=["__proto__","constructor","prototype"];for(let a=1;a<arguments.length;a+=1){const i=a<0||arguments.length<=a?void 0:arguments[a];if(null!=i&&(s=i,!("undefined"!=typeof window&&void 0!==window.HTMLElement?s instanceof HTMLElement:s&&(1===s.nodeType||11===s.nodeType)))){const s=Object.keys(Object(i)).filter((e=>t.indexOf(e)<0));for(let t=0,a=s.length;t<a;t+=1){const a=s[t],r=Object.getOwnPropertyDescriptor(i,a);void 0!==r&&r.enumerable&&(c(e[a])&&c(i[a])?i[a].__swiper__?e[a]=i[a]:p(e[a],i[a]):!c(e[a])&&c(i[a])?(e[a]={},i[a].__swiper__?e[a]=i[a]:p(e[a],i[a])):e[a]=i[a])}}}var s;return e}function u(e,t,s){e.style.setProperty(t,s)}function m(e){let{swiper:t,targetPosition:s,side:a}=e;const i=r(),n=-t.translate;let l,o=null;const d=t.params.speed;t.wrapperEl.style.scrollSnapType="none",i.cancelAnimationFrame(t.cssModeFrameID);const c=s>n?"next":"prev",p=(e,t)=>"next"===c&&e>=t||"prev"===c&&e<=t,u=()=>{l=(new Date).getTime(),null===o&&(o=l);const e=Math.max(Math.min((l-o)/d,1),0),r=.5-Math.cos(e*Math.PI)/2;let c=n+r*(s-n);if(p(c,s)&&(c=s),t.wrapperEl.scrollTo({[a]:c}),p(c,s))return t.wrapperEl.style.overflow="hidden",t.wrapperEl.style.scrollSnapType="",setTimeout((()=>{t.wrapperEl.style.overflow="",t.wrapperEl.scrollTo({[a]:c})})),void i.cancelAnimationFrame(t.cssModeFrameID);t.cssModeFrameID=i.requestAnimationFrame(u)};u()}function h(e){return e.querySelector(".swiper-slide-transform")||e.shadowRoot&&e.shadowRoot.querySelector(".swiper-slide-transform")||e}function f(e,t){void 0===t&&(t="");const s=r(),a=[...e.children];return s.HTMLSlotElement&&e instanceof HTMLSlotElement&&a.push(...e.assignedElements()),t?a.filter((e=>e.matches(t))):a}function g(e){try{return void console.warn(e)}catch(e){}}function v(e,t){void 0===t&&(t=[]);const s=document.createElement(e);return s.classList.add(...Array.isArray(t)?t:n(t)),s}function w(e){const t=r(),s=a(),i=e.getBoundingClientRect(),n=s.body,l=e.clientTop||n.clientTop||0,o=e.clientLeft||n.clientLeft||0,d=e===t?t.scrollY:e.scrollTop,c=e===t?t.scrollX:e.scrollLeft;return{top:i.top+d-l,left:i.left+c-o}}function b(e,t){return r().getComputedStyle(e,null).getPropertyValue(t)}function y(e){let t,s=e;if(s){for(t=0;null!==(s=s.previousSibling);)1===s.nodeType&&(t+=1);return t}}function E(e,t){const s=[];let a=e.parentElement;for(;a;)t?a.matches(t)&&s.push(a):s.push(a),a=a.parentElement;rLine truncated
|
||||
//# sourceMappingURL=swiper-bundle.min.js.map
|
||||
@@ -0,0 +1,263 @@
|
||||
/**
|
||||
* AKSRT Video Player
|
||||
*
|
||||
* Lightweight HTML5 video player wrapper with support for:
|
||||
* - Standard MP4/WebM playback
|
||||
* - HLS streaming (lazy-loaded)
|
||||
* - FLV streaming (lazy-loaded)
|
||||
* - Auto-quality selection
|
||||
* - Keyboard shortcuts
|
||||
*
|
||||
* Usage:
|
||||
* <div class="aksrt-video" data-aksrt-video data-src="video.mp4" data-poster="thumb.jpg"></div>
|
||||
* <div class="aksrt-video" data-aksrt-video data-src="stream.m3u8" data-type="hls"></div>
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var STYLE_ID = 'aksrt-video-player-style';
|
||||
var HLS_SRC = 'https://cdn.jsdelivr.net/npm/hls.js@1/dist/hls.min.js';
|
||||
var FLV_SRC = 'https://cdn.jsdelivr.net/npm/flv.js@1/dist/flv.min.js';
|
||||
|
||||
function injectStyle() {
|
||||
if (document.getElementById(STYLE_ID)) return;
|
||||
var style = document.createElement('style');
|
||||
style.id = STYLE_ID;
|
||||
style.textContent =
|
||||
'.aksrt-video{position:relative;background:#000;border-radius:12px;overflow:hidden;cursor:pointer;}' +
|
||||
'.aksrt-video video{display:block;width:100%;height:auto;max-height:70vh;}' +
|
||||
'.aksrt-video__overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,0.3);transition:opacity 0.3s;pointer-events:none;}' +
|
||||
'.aksrt-video.is-playing .aksrt-video__overlay{opacity:0;}' +
|
||||
'.aksrt-video__play{width:60px;height:60px;border-radius:50%;background:rgba(255,255,255,0.9);display:flex;align-items:center;justify-content:center;font-size:24px;color:#1a1a2e;box-shadow:0 4px 20px rgba(0,0,0,0.3);transition:transform 0.2s;}' +
|
||||
'.aksrt-video:hover .aksrt-video__play{transform:scale(1.1);}' +
|
||||
'.aksrt-video__badge{position:absolute;top:8px;right:8px;background:rgba(0,0,0,0.6);color:#fff;font-size:11px;padding:2px 8px;border-radius:4px;backdrop-filter:blur(4px);}' +
|
||||
'.aksrt-video.is-playing .aksrt-video__badge{display:none;}';
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
|
||||
function detectType(src) {
|
||||
if (!src) return 'mp4';
|
||||
if (/\.m3u8(\?|$)/i.test(src)) return 'hls';
|
||||
if (/\.flv(\?|$)/i.test(src)) return 'flv';
|
||||
return 'mp4';
|
||||
}
|
||||
|
||||
function loadScript(src) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var script = document.createElement('script');
|
||||
script.src = src;
|
||||
script.onload = resolve;
|
||||
script.onerror = reject;
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
}
|
||||
|
||||
function AksrtVideoPlayer(element) {
|
||||
this.el = typeof element === 'string' ? document.querySelector(element) : element;
|
||||
if (!this.el || this.el.dataset.aksrtVideoBound) return;
|
||||
this.el.dataset.aksrtVideoBound = '1';
|
||||
this.el._aksrtPlayer = this;
|
||||
|
||||
this.src = this.el.dataset.src || '';
|
||||
this.poster = this.el.dataset.poster || '';
|
||||
this.type = this.el.dataset.type || detectType(this.src);
|
||||
this.autoplay = this.el.dataset.autoplay === 'true';
|
||||
this.init();
|
||||
}
|
||||
|
||||
AksrtVideoPlayer.prototype.init = function () {
|
||||
var self = this;
|
||||
|
||||
// Create video element
|
||||
this.video = document.createElement('video');
|
||||
this.video.controls = true;
|
||||
this.video.playsInline = true;
|
||||
this.video.preload = this.autoplay ? 'auto' : 'metadata';
|
||||
if (this.poster) this.video.poster = this.poster;
|
||||
this.video.style.cssText = 'display:block;width:100%;height:auto;max-height:70vh;';
|
||||
|
||||
// Play overlay
|
||||
this.overlay = document.createElement('div');
|
||||
this.overlay.className = 'aksrt-video__overlay';
|
||||
this.overlay.innerHTML = '<div class="aksrt-video__play"><i class="fas fa-play" style="margin-left:3px;"></i></div>';
|
||||
|
||||
// Badge
|
||||
if (this.type === 'hls') {
|
||||
var badge = document.createElement('div');
|
||||
badge.className = 'aksrt-video__badge';
|
||||
badge.textContent = 'HLS';
|
||||
this.el.appendChild(badge);
|
||||
}
|
||||
|
||||
this.el.appendChild(this.video);
|
||||
this.el.appendChild(this.overlay);
|
||||
|
||||
// Events
|
||||
this.el.addEventListener('click', function (e) {
|
||||
if (e.target.closest('video') && self.video.controls) return;
|
||||
self.toggle();
|
||||
});
|
||||
|
||||
this.video.addEventListener('play', function () {
|
||||
self.el.classList.add('is-playing');
|
||||
});
|
||||
|
||||
this.video.addEventListener('pause', function () {
|
||||
self.el.classList.remove('is-playing');
|
||||
});
|
||||
|
||||
this.video.addEventListener('ended', function () {
|
||||
self.el.classList.remove('is-playing');
|
||||
});
|
||||
|
||||
// Keyboard shortcuts
|
||||
this.video.addEventListener('keydown', function (e) {
|
||||
switch (e.key) {
|
||||
case ' ': e.preventDefault(); self.toggle(); break;
|
||||
case 'ArrowLeft': self.video.currentTime -= 5; break;
|
||||
case 'ArrowRight': self.video.currentTime += 5; break;
|
||||
case 'f': self.toggleFullscreen(); break;
|
||||
case 'm': self.video.muted = !self.video.muted; break;
|
||||
}
|
||||
});
|
||||
|
||||
// Load source
|
||||
this.loadSource();
|
||||
};
|
||||
|
||||
AksrtVideoPlayer.prototype.loadSource = function () {
|
||||
var self = this;
|
||||
|
||||
if (this.type === 'hls') {
|
||||
if (window.Hls && Hls.isSupported()) {
|
||||
this.hls = new Hls();
|
||||
this.hls.loadSource(this.src);
|
||||
this.hls.attachMedia(this.video);
|
||||
} else if (this.video.canPlayType('application/vnd.apple.mpegurl')) {
|
||||
// Safari native HLS
|
||||
this.video.src = this.src;
|
||||
} else {
|
||||
// Load hls.js dynamically
|
||||
loadScript(HLS_SRC).then(function () {
|
||||
if (window.Hls && Hls.isSupported()) {
|
||||
self.hls = new Hls();
|
||||
self.hls.loadSource(self.src);
|
||||
self.hls.attachMedia(self.video);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (this.type === 'flv') {
|
||||
loadScript(FLV_SRC).then(function () {
|
||||
if (window.flvjs && flvjs.isSupported()) {
|
||||
self.flvPlayer = flvjs.createPlayer({ type: 'flv', url: self.src });
|
||||
self.flvPlayer.attachMediaElement(self.video);
|
||||
self.flvPlayer.load();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.video.src = this.src;
|
||||
}
|
||||
|
||||
if (this.autoplay) {
|
||||
this.video.play().catch(function () { /* autoplay blocked */ });
|
||||
}
|
||||
};
|
||||
|
||||
AksrtVideoPlayer.prototype.toggle = function () {
|
||||
if (this.video.paused) {
|
||||
this.video.play();
|
||||
} else {
|
||||
this.video.pause();
|
||||
}
|
||||
};
|
||||
|
||||
AksrtVideoPlayer.prototype.toggleFullscreen = function () {
|
||||
if (document.fullscreenElement) {
|
||||
document.exitFullscreen();
|
||||
} else if (this.el.requestFullscreen) {
|
||||
this.el.requestFullscreen();
|
||||
}
|
||||
};
|
||||
|
||||
AksrtVideoPlayer.prototype.destroy = function () {
|
||||
if (this.hls) { this.hls.destroy(); this.hls = null; }
|
||||
if (this.flvPlayer) { this.flvPlayer.destroy(); this.flvPlayer = null; }
|
||||
this.video.src = '';
|
||||
this.el.innerHTML = '';
|
||||
delete this.el.dataset.aksrtVideoBound;
|
||||
};
|
||||
|
||||
/**
|
||||
* 切换视频源(剧集切换)
|
||||
* @param {string} src - 新视频地址
|
||||
* @param {string} [type] - 可选类型 (mp4/hls/flv)
|
||||
* @param {string} [poster] - 可选封面
|
||||
*/
|
||||
AksrtVideoPlayer.prototype.switchSource = function (src, type, poster) {
|
||||
if (!src) return;
|
||||
|
||||
// 清理旧播放器
|
||||
if (this.hls) { this.hls.destroy(); this.hls = null; }
|
||||
if (this.flvPlayer) { this.flvPlayer.destroy(); this.flvPlayer = null; }
|
||||
|
||||
this.src = src;
|
||||
this.type = type || detectType(src);
|
||||
if (poster) {
|
||||
this.poster = poster;
|
||||
this.video.poster = poster;
|
||||
}
|
||||
|
||||
this.video.src = '';
|
||||
this.loadSource();
|
||||
};
|
||||
|
||||
// ── 剧集切换按钮事件委托 ──
|
||||
document.addEventListener('click', function (e) {
|
||||
var switchBtn = e.target.closest('.switch-video, .switch-iframe');
|
||||
if (!switchBtn) return;
|
||||
|
||||
var container = switchBtn.closest('.aksrt-video') || switchBtn.closest('[data-aksrt-video]');
|
||||
if (!container) return;
|
||||
|
||||
var src = switchBtn.dataset.src || switchBtn.getAttribute('href');
|
||||
if (!src) return;
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
// 检查是否已有播放器实例
|
||||
if (container._aksrtPlayer) {
|
||||
container._aksrtPlayer.switchSource(src, switchBtn.dataset.type);
|
||||
} else {
|
||||
container.dataset.src = src;
|
||||
if (switchBtn.dataset.type) container.dataset.type = switchBtn.dataset.type;
|
||||
new AksrtVideoPlayer(container);
|
||||
}
|
||||
|
||||
// 高亮当前集
|
||||
var siblings = container.parentElement ? container.parentElement.querySelectorAll('.switch-video, .switch-iframe') : [];
|
||||
siblings.forEach(function (btn) { btn.classList.remove('is-active'); });
|
||||
switchBtn.classList.add('is-active');
|
||||
});
|
||||
|
||||
// ── Public API ──
|
||||
|
||||
window.AksrtVideoPlayer = AksrtVideoPlayer;
|
||||
|
||||
// ── Auto-init ──
|
||||
|
||||
function init() {
|
||||
injectStyle();
|
||||
document.querySelectorAll('[data-aksrt-video]').forEach(function (el) {
|
||||
new AksrtVideoPlayer(el);
|
||||
});
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* AKSRT Waterfall — 瀑布流/异步列表
|
||||
*
|
||||
* 提供纯 CSS column-based 瀑布流布局和无限滚动加载能力。
|
||||
* 无外部依赖。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Initialize waterfall layout on a container.
|
||||
*
|
||||
* @param {HTMLElement} container - The container element
|
||||
* @param {Object} options
|
||||
* @param {number} options.columns - Number of columns (default: auto from CSS)
|
||||
* @param {string} options.itemSelector - Child item selector (default: '.waterfall-item')
|
||||
* @param {number} options.gap - Gap between items in px (default: 16)
|
||||
*/
|
||||
function Waterfall(container, options) {
|
||||
if (!container) return;
|
||||
|
||||
this.container = container;
|
||||
this.options = Object.assign({
|
||||
columns: 0,
|
||||
itemSelector: '.waterfall-item',
|
||||
gap: 16,
|
||||
}, options || {});
|
||||
|
||||
this._resizeHandler = this.layout.bind(this);
|
||||
window.addEventListener('resize', this._resizeHandler);
|
||||
this.layout();
|
||||
}
|
||||
|
||||
Waterfall.prototype.layout = function () {
|
||||
var items = this.container.querySelectorAll(this.options.itemSelector);
|
||||
if (items.length === 0) return;
|
||||
|
||||
var cols = this.options.columns;
|
||||
if (cols <= 0) {
|
||||
var containerWidth = this.container.offsetWidth;
|
||||
cols = Math.max(1, Math.floor(containerWidth / 280));
|
||||
}
|
||||
|
||||
var gap = this.options.gap;
|
||||
var colWidth = (this.container.offsetWidth - gap * (cols - 1)) / cols;
|
||||
var colHeights = new Array(cols).fill(0);
|
||||
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
var item = items[i];
|
||||
item.style.width = colWidth + 'px';
|
||||
item.style.position = 'absolute';
|
||||
|
||||
// Find shortest column
|
||||
var minHeight = Infinity;
|
||||
var minCol = 0;
|
||||
for (var c = 0; c < cols; c++) {
|
||||
if (colHeights[c] < minHeight) {
|
||||
minHeight = colHeights[c];
|
||||
minCol = c;
|
||||
}
|
||||
}
|
||||
|
||||
item.style.left = (minCol * (colWidth + gap)) + 'px';
|
||||
item.style.top = colHeights[minCol] + 'px';
|
||||
|
||||
colHeights[minCol] += item.offsetHeight + gap;
|
||||
}
|
||||
|
||||
// Set container height to tallest column
|
||||
var maxHeight = Math.max.apply(null, colHeights);
|
||||
this.container.style.height = maxHeight + 'px';
|
||||
this.container.style.position = 'relative';
|
||||
};
|
||||
|
||||
Waterfall.prototype.relayout = function () {
|
||||
this.layout();
|
||||
};
|
||||
|
||||
Waterfall.prototype.destroy = function () {
|
||||
window.removeEventListener('resize', this._resizeHandler);
|
||||
};
|
||||
|
||||
/**
|
||||
* Infinite scroll loader.
|
||||
*
|
||||
* @param {Object} options
|
||||
* @param {string} options.containerSelector - List container selector
|
||||
* @param {string} options.loadMoreSelector - Load-more button selector
|
||||
* @param {Function} options.loadMore - Async function that loads more items
|
||||
* @param {number} options.threshold - Distance from bottom to trigger (default: 200)
|
||||
*/
|
||||
function InfiniteScroll(options) {
|
||||
this.options = Object.assign({
|
||||
containerSelector: '.aksrt-infinite-list',
|
||||
loadMoreSelector: '.aksrt-load-more',
|
||||
loadMore: null,
|
||||
threshold: 200,
|
||||
}, options || {});
|
||||
|
||||
this.loading = false;
|
||||
this.hasMore = true;
|
||||
this._scrollHandler = this._check.bind(this);
|
||||
|
||||
window.addEventListener('scroll', this._scrollHandler);
|
||||
this._check();
|
||||
}
|
||||
|
||||
InfiniteScroll.prototype._check = function () {
|
||||
if (this.loading || !this.hasMore) return;
|
||||
|
||||
var loadMoreBtn = document.querySelector(this.options.loadMoreSelector);
|
||||
if (!loadMoreBtn) {
|
||||
this.hasMore = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var rect = loadMoreBtn.getBoundingClientRect();
|
||||
if (rect.top < window.innerHeight + this.options.threshold) {
|
||||
this._load();
|
||||
}
|
||||
};
|
||||
|
||||
InfiniteScroll.prototype._load = function () {
|
||||
if (!this.options.loadMore) return;
|
||||
|
||||
this.loading = true;
|
||||
var self = this;
|
||||
|
||||
this.options.loadMore().then(function (hasMore) {
|
||||
self.hasMore = hasMore !== false;
|
||||
self.loading = false;
|
||||
if (self.hasMore) {
|
||||
self._check();
|
||||
}
|
||||
}).catch(function () {
|
||||
self.loading = false;
|
||||
});
|
||||
};
|
||||
|
||||
InfiniteScroll.prototype.destroy = function () {
|
||||
window.removeEventListener('scroll', this._scrollHandler);
|
||||
};
|
||||
|
||||
// Auto-init
|
||||
var waterfallInstances = [];
|
||||
|
||||
function relayoutAll() {
|
||||
waterfallInstances.forEach(function (instance) {
|
||||
if (instance && typeof instance.relayout === 'function') {
|
||||
instance.relayout();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function autoInit() {
|
||||
document.querySelectorAll('[data-aksrt-waterfall]').forEach(function (el) {
|
||||
var cols = parseInt(el.dataset.aksrtWaterfallColumns) || 0;
|
||||
var gap = parseInt(el.dataset.aksrtWaterfallGap) || 16;
|
||||
waterfallInstances.push(new Waterfall(el, { columns: cols, gap: gap }));
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('post_ajax.ed', relayoutAll);
|
||||
document.addEventListener('aksrt:posts:rendered', relayoutAll);
|
||||
document.addEventListener('lazyloaded', relayoutAll, true);
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', autoInit);
|
||||
} else {
|
||||
autoInit();
|
||||
}
|
||||
|
||||
// Export to global
|
||||
window.AksrtWaterfall = Waterfall;
|
||||
window.AksrtInfiniteScroll = InfiniteScroll;
|
||||
})();
|
||||
@@ -0,0 +1,481 @@
|
||||
/**
|
||||
* AKSRT Weixin Share
|
||||
*
|
||||
* Bridge-first WeChat share helper with QR fallback.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Local QR code data URL generator — no third-party services.
|
||||
* Uses canvas rendering with a minimal QR matrix encoder.
|
||||
*/
|
||||
function buildQRCodeDataUrl(text, size) {
|
||||
size = size || 160;
|
||||
try {
|
||||
var matrix = generateQRMatrix(text || ' ');
|
||||
if (!matrix) return '';
|
||||
var canvas = document.createElement('canvas');
|
||||
var moduleCount = matrix.length;
|
||||
var scale = Math.floor(size / (moduleCount + 8));
|
||||
var margin = Math.floor((size - scale * moduleCount) / 2);
|
||||
canvas.width = size;
|
||||
canvas.height = size;
|
||||
var ctx = canvas.getContext('2d');
|
||||
ctx.fillStyle = '#ffffff';
|
||||
ctx.fillRect(0, 0, size, size);
|
||||
ctx.fillStyle = '#000000';
|
||||
for (var r = 0; r < moduleCount; r++) {
|
||||
for (var c = 0; c < moduleCount; c++) {
|
||||
if (matrix[r][c]) {
|
||||
ctx.fillRect(margin + c * scale, margin + r * scale, scale, scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
return canvas.toDataURL('image/png');
|
||||
} catch (e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Minimal QR Code matrix generator (Version 1-6, Byte mode, Error Correction L).
|
||||
* Returns a 2D boolean array or null on failure.
|
||||
*/
|
||||
function generateQRMatrix(text) {
|
||||
var data = encodeUTF8(text);
|
||||
// Choose version based on data length (EC level L, Byte mode)
|
||||
var version = 1;
|
||||
var capacities = [0, 17, 32, 53, 78, 106, 134];
|
||||
for (var v = 1; v <= 6; v++) {
|
||||
if (data.length <= capacities[v]) { version = v; break; }
|
||||
if (v === 6) return null; // data too long for small versions
|
||||
}
|
||||
var moduleCount = version * 4 + 17;
|
||||
var matrix = createMatrix(moduleCount);
|
||||
var reserved = createMatrix(moduleCount);
|
||||
|
||||
// Place finder patterns
|
||||
placeFinder(matrix, reserved, 0, 0);
|
||||
placeFinder(matrix, reserved, moduleCount - 7, 0);
|
||||
placeFinder(matrix, reserved, 0, moduleCount - 7);
|
||||
|
||||
// Place alignment patterns (version >= 2)
|
||||
if (version >= 2) {
|
||||
var alignPos = getAlignmentPositions(version);
|
||||
for (var i = 0; i < alignPos.length; i++) {
|
||||
for (var j = 0; j < alignPos.length; j++) {
|
||||
if (isInFinder(alignPos[i], alignPos[j], moduleCount)) continue;
|
||||
placeAlignment(matrix, reserved, alignPos[i], alignPos[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Place timing patterns
|
||||
for (var i = 8; i < moduleCount - 8; i++) {
|
||||
if (!reserved[6][i]) { matrix[6][i] = (i % 2 === 0); reserved[6][i] = true; }
|
||||
if (!reserved[i][6]) { matrix[i][6] = (i % 2 === 0); reserved[i][6] = true; }
|
||||
}
|
||||
|
||||
// Reserve format info areas
|
||||
for (var i = 0; i < 8; i++) {
|
||||
reserved[8][i] = true; reserved[i][8] = true;
|
||||
reserved[8][moduleCount - 1 - i] = true; reserved[moduleCount - 1 - i][8] = true;
|
||||
}
|
||||
reserved[8][8] = true;
|
||||
if (version >= 2) {
|
||||
for (var i = moduleCount - 11; i < moduleCount - 8; i++) {
|
||||
for (var j = 0; j < 6; j++) { reserved[j][i] = true; reserved[i][j] = true; }
|
||||
}
|
||||
}
|
||||
|
||||
// Dark module
|
||||
matrix[moduleCount - 8][8] = true;
|
||||
reserved[moduleCount - 8][8] = true;
|
||||
|
||||
// Encode data
|
||||
var dataBits = encodeData(data, version);
|
||||
placeData(matrix, reserved, dataBits, moduleCount);
|
||||
|
||||
// Apply best mask
|
||||
var bestMask = 0;
|
||||
var bestPenalty = Infinity;
|
||||
for (var m = 0; m < 8; m++) {
|
||||
var masked = applyMask(matrix, reserved, m, moduleCount);
|
||||
var penalty = calcPenalty(masked, moduleCount);
|
||||
if (penalty < bestPenalty) { bestPenalty = penalty; bestMask = m; }
|
||||
}
|
||||
matrix = applyMask(matrix, reserved, bestMask, moduleCount);
|
||||
|
||||
// Place format info
|
||||
placeFormatInfo(matrix, bestMask, moduleCount);
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
function createMatrix(n) {
|
||||
var m = [];
|
||||
for (var i = 0; i < n; i++) { m[i] = []; for (var j = 0; j < n; j++) m[i][j] = false; }
|
||||
return m;
|
||||
}
|
||||
|
||||
function encodeUTF8(str) {
|
||||
var bytes = [];
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
var c = str.charCodeAt(i);
|
||||
if (c < 0x80) bytes.push(c);
|
||||
else if (c < 0x800) { bytes.push(0xc0 | (c >> 6)); bytes.push(0x80 | (c & 0x3f)); }
|
||||
else { bytes.push(0xe0 | (c >> 12)); bytes.push(0x80 | ((c >> 6) & 0x3f)); bytes.push(0x80 | (c & 0x3f)); }
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function placeFinder(m, r, row, col) {
|
||||
for (var dr = -1; dr <= 7; dr++) {
|
||||
for (var dc = -1; dc <= 7; dc++) {
|
||||
var rr = row + dr, cc = col + dc;
|
||||
if (rr < 0 || rr >= m.length || cc < 0 || cc >= m.length) continue;
|
||||
var val = (dr >= 0 && dr <= 6 && (dc === 0 || dc === 6)) || (dc >= 0 && dc <= 6 && (dr === 0 || dr === 6)) || (dr >= 2 && dr <= 4 && dc >= 2 && dc <= 4);
|
||||
m[rr][cc] = val;
|
||||
r[rr][cc] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function placeAlignment(m, r, row, col) {
|
||||
for (var dr = -2; dr <= 2; dr++) {
|
||||
for (var dc = -2; dc <= 2; dc++) {
|
||||
var val = Math.abs(dr) === 2 || Math.abs(dc) === 2 || (dr === 0 && dc === 0);
|
||||
m[row + dr][col + dc] = val;
|
||||
r[row + dr][col + dc] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getAlignmentPositions(v) {
|
||||
if (v <= 1) return [];
|
||||
if (v === 2) return [6, 18];
|
||||
if (v === 3) return [6, 22];
|
||||
if (v === 4) return [6, 26];
|
||||
if (v === 5) return [6, 30];
|
||||
return [6, 34];
|
||||
}
|
||||
|
||||
function isInFinder(row, col, n) {
|
||||
return (row < 9 && col < 9) || (row < 9 && col >= n - 8) || (row >= n - 8 && col < 9);
|
||||
}
|
||||
|
||||
function encodeData(data, version) {
|
||||
var bits = [];
|
||||
// Mode indicator: Byte = 0100
|
||||
bits.push(0, 1, 0, 0);
|
||||
// Character count
|
||||
var ccBits = version <= 9 ? 8 : 16;
|
||||
for (var i = ccBits - 1; i >= 0; i--) bits.push((data.length >> i) & 1);
|
||||
// Data
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
for (var j = 7; j >= 0; j--) bits.push((data[i] >> j) & 1);
|
||||
}
|
||||
// Terminator
|
||||
var capacities = [0, 152, 272, 440, 640, 864, 1088];
|
||||
var cap = capacities[version] || 152;
|
||||
for (var i = 0; i < 4 && bits.length < cap; i++) bits.push(0);
|
||||
// Pad to byte boundary
|
||||
while (bits.length % 8 !== 0) bits.push(0);
|
||||
// Pad bytes
|
||||
var padBytes = [0xEC, 0x11];
|
||||
var pi = 0;
|
||||
while (bits.length < cap) {
|
||||
var pb = padBytes[pi % 2];
|
||||
for (var j = 7; j >= 0; j--) bits.push((pb >> j) & 1);
|
||||
pi++;
|
||||
}
|
||||
return bits;
|
||||
}
|
||||
|
||||
function placeData(matrix, reserved, bits, n) {
|
||||
var bitIndex = 0;
|
||||
for (var right = n - 1; right >= 1; right -= 2) {
|
||||
if (right === 6) right = 5;
|
||||
for (var vert = 0; vert < n; vert++) {
|
||||
for (var j = 0; j < 2; j++) {
|
||||
var col = right - j;
|
||||
var upward = ((right + 1) & 2) === 0;
|
||||
var row = upward ? n - 1 - vert : vert;
|
||||
if (!reserved[row][col] && bitIndex < bits.length) {
|
||||
matrix[row][col] = bits[bitIndex] === 1;
|
||||
bitIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function applyMask(matrix, reserved, maskNum, n) {
|
||||
var result = createMatrix(n);
|
||||
for (var r = 0; r < n; r++) {
|
||||
for (var c = 0; c < n; c++) {
|
||||
result[r][c] = matrix[r][c];
|
||||
if (!reserved[r][c]) {
|
||||
var invert = false;
|
||||
switch (maskNum) {
|
||||
case 0: invert = (r + c) % 2 === 0; break;
|
||||
case 1: invert = r % 2 === 0; break;
|
||||
case 2: invert = c % 3 === 0; break;
|
||||
case 3: invert = (r + c) % 3 === 0; break;
|
||||
case 4: invert = (Math.floor(r / 2) + Math.floor(c / 3)) % 2 === 0; break;
|
||||
case 5: invert = (r * c) % 2 + (r * c) % 3 === 0; break;
|
||||
case 6: invert = ((r * c) % 2 + (r * c) % 3) % 2 === 0; break;
|
||||
case 7: invert = ((r + c) % 2 + (r * c) % 3) % 2 === 0; break;
|
||||
}
|
||||
if (invert) result[r][c] = !result[r][c];
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function calcPenalty(matrix, n) {
|
||||
var penalty = 0;
|
||||
// Rule 1: consecutive same-color modules in row/column
|
||||
for (var r = 0; r < n; r++) {
|
||||
var run = 1;
|
||||
for (var c = 1; c < n; c++) {
|
||||
if (matrix[r][c] === matrix[r][c - 1]) { run++; } else { run = 1; }
|
||||
if (run === 5) penalty += 3;
|
||||
else if (run > 5) penalty += 1;
|
||||
}
|
||||
}
|
||||
for (var c = 0; c < n; c++) {
|
||||
var run = 1;
|
||||
for (var r = 1; r < n; r++) {
|
||||
if (matrix[r][c] === matrix[r - 1][c]) { run++; } else { run = 1; }
|
||||
if (run === 5) penalty += 3;
|
||||
else if (run > 5) penalty += 1;
|
||||
}
|
||||
}
|
||||
return penalty;
|
||||
}
|
||||
|
||||
function placeFormatInfo(matrix, maskNum, n) {
|
||||
var formatInfo = getFormatInfo(maskNum);
|
||||
// Place around top-left finder
|
||||
var positions = [
|
||||
[8, 0], [8, 1], [8, 2], [8, 3], [8, 4], [8, 5], [8, 7], [8, 8],
|
||||
[7, 8], [5, 8], [4, 8], [3, 8], [2, 8], [1, 8], [0, 8]
|
||||
];
|
||||
for (var i = 0; i < 15; i++) {
|
||||
var r = positions[i][0], c = positions[i][1];
|
||||
matrix[r][c] = formatInfo[i] === 1;
|
||||
}
|
||||
// Place around bottom-left and top-right finders
|
||||
var positions2 = [
|
||||
[n - 1, 8], [n - 2, 8], [n - 3, 8], [n - 4, 8], [n - 5, 8], [n - 6, 8], [n - 7, 8],
|
||||
[8, n - 8], [8, n - 7], [8, n - 6], [8, n - 5], [8, n - 4], [8, n - 3], [8, n - 2], [8, n - 1]
|
||||
];
|
||||
for (var i = 0; i < 15; i++) {
|
||||
var r = positions2[i][0], c = positions2[i][1];
|
||||
matrix[r][c] = formatInfo[i] === 1;
|
||||
}
|
||||
}
|
||||
|
||||
function getFormatInfo(maskNum) {
|
||||
// EC level L = 01, mask number = maskNum
|
||||
var data = (0x01 << 3) | maskNum; // 5 bits
|
||||
var bits = data << 10;
|
||||
// BCH(15,5) error correction
|
||||
var gen = 0x537; // generator polynomial
|
||||
for (var i = 14; i >= 10; i--) {
|
||||
if (bits & (1 << i)) bits ^= gen << (i - 10);
|
||||
}
|
||||
var formatBits = (data << 10) | bits;
|
||||
// XOR with mask pattern
|
||||
formatBits ^= 0x5412;
|
||||
var result = [];
|
||||
for (var i = 14; i >= 0; i--) result.push((formatBits >> i) & 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
function isWeixinEnv() {
|
||||
return /micromessenger/i.test(window.navigator.userAgent || '') || !!window.WeixinJSBridge;
|
||||
}
|
||||
|
||||
function normalizePayload(payload) {
|
||||
payload = payload || {};
|
||||
return {
|
||||
title: payload.title || document.title,
|
||||
url: payload.url || window.location.href,
|
||||
desc: payload.desc || '',
|
||||
image: payload.image || ''
|
||||
};
|
||||
}
|
||||
|
||||
function hideQrFallback(qrBox) {
|
||||
if (!qrBox) return;
|
||||
qrBox.classList.remove('is-visible');
|
||||
qrBox.setAttribute('aria-hidden', 'true');
|
||||
}
|
||||
|
||||
function showQrFallback(payload) {
|
||||
var qrBox = payload.qrBox;
|
||||
var qrImage = payload.qrImage;
|
||||
if (!qrBox || !qrImage || !payload.url) {
|
||||
return Promise.resolve({
|
||||
mode: 'error',
|
||||
message: '当前页面缺少微信二维码容器'
|
||||
});
|
||||
}
|
||||
|
||||
if (qrImage.dataset.qrValue !== payload.url || !qrImage.getAttribute('src')) {
|
||||
qrImage.dataset.qrValue = payload.url;
|
||||
var dataUrl = buildQRCodeDataUrl(payload.url, 160);
|
||||
if (dataUrl) {
|
||||
qrImage.src = dataUrl;
|
||||
} else {
|
||||
qrImage.alt = '二维码生成失败,请直接复制链接分享';
|
||||
}
|
||||
}
|
||||
|
||||
qrBox.classList.add('is-visible');
|
||||
qrBox.setAttribute('aria-hidden', 'false');
|
||||
|
||||
return Promise.resolve({
|
||||
mode: 'qr',
|
||||
message: '请使用微信扫一扫分享'
|
||||
});
|
||||
}
|
||||
|
||||
function bridgeWithWxSdk(payload) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
if (!window.wx || typeof window.wx.ready !== 'function') {
|
||||
reject(new Error('wx sdk unavailable'));
|
||||
return;
|
||||
}
|
||||
|
||||
var done = false;
|
||||
var timer = window.setTimeout(function () {
|
||||
if (done) return;
|
||||
done = true;
|
||||
reject(new Error('微信分享桥接未就绪'));
|
||||
}, 1200);
|
||||
|
||||
function finishSuccess() {
|
||||
if (done) return;
|
||||
done = true;
|
||||
window.clearTimeout(timer);
|
||||
resolve({
|
||||
mode: 'bridge',
|
||||
message: '已同步微信分享信息,请使用右上角菜单继续分享'
|
||||
});
|
||||
}
|
||||
|
||||
function finishError(error) {
|
||||
if (done) return;
|
||||
done = true;
|
||||
window.clearTimeout(timer);
|
||||
reject(error instanceof Error ? error : new Error('微信分享桥接失败'));
|
||||
}
|
||||
|
||||
try {
|
||||
if (typeof window.wx.error === 'function') {
|
||||
window.wx.error(function (error) {
|
||||
finishError(new Error((error && error.errMsg) || '微信签名校验失败'));
|
||||
});
|
||||
}
|
||||
|
||||
window.wx.ready(function () {
|
||||
try {
|
||||
if (typeof window.wx.updateAppMessageShareData === 'function') {
|
||||
window.wx.updateAppMessageShareData({
|
||||
title: payload.title,
|
||||
desc: payload.desc,
|
||||
link: payload.url,
|
||||
imgUrl: payload.image
|
||||
});
|
||||
}
|
||||
|
||||
if (typeof window.wx.updateTimelineShareData === 'function') {
|
||||
window.wx.updateTimelineShareData({
|
||||
title: payload.title,
|
||||
link: payload.url,
|
||||
imgUrl: payload.image
|
||||
});
|
||||
}
|
||||
|
||||
finishSuccess();
|
||||
} catch (error) {
|
||||
finishError(error);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
finishError(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function bridgeWithWeixinJsBridge(payload) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var bridge = window.WeixinJSBridge;
|
||||
if (!bridge || typeof bridge.invoke !== 'function') {
|
||||
reject(new Error('WeixinJSBridge unavailable'));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
bridge.invoke('sendAppMessage', {
|
||||
title: payload.title,
|
||||
desc: payload.desc,
|
||||
link: payload.url,
|
||||
img_url: payload.image
|
||||
}, function (response) {
|
||||
var errMsg = response && response.err_msg ? response.err_msg : '';
|
||||
if (!errMsg || /:ok$/i.test(errMsg)) {
|
||||
resolve({
|
||||
mode: 'bridge',
|
||||
message: '已调起微信分享面板'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
reject(new Error(errMsg));
|
||||
});
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function openWeixinShare(payload) {
|
||||
var data = normalizePayload(payload);
|
||||
data.qrBox = payload && payload.qrBox ? payload.qrBox : null;
|
||||
data.qrImage = payload && payload.qrImage ? payload.qrImage : null;
|
||||
|
||||
if (!isWeixinEnv()) {
|
||||
return showQrFallback(data);
|
||||
}
|
||||
|
||||
return bridgeWithWxSdk(data)
|
||||
.catch(function () {
|
||||
return bridgeWithWeixinJsBridge(data);
|
||||
})
|
||||
.catch(function (error) {
|
||||
return showQrFallback(data).then(function (result) {
|
||||
result.message = (error && error.message ? error.message + ',' : '') + '已切换为二维码分享';
|
||||
return result;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
window.AksrtShare = Object.assign({}, window.AksrtShare || {}, {
|
||||
isWeixinEnv: isWeixinEnv,
|
||||
hideQrFallback: hideQrFallback,
|
||||
showQrFallback: showQrFallback,
|
||||
openWeixinShare: openWeixinShare,
|
||||
// Exposed so the unified share-data-builder can render poster QR codes
|
||||
// without a second encoder.
|
||||
buildQrDataUrl: buildQRCodeDataUrl
|
||||
});
|
||||
})();
|
||||
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* AKSRT Widget Set
|
||||
*
|
||||
* Handles widget-local interactions and floating QR widgets.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function initWidgetTabs() {
|
||||
document.querySelectorAll('.widget-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;
|
||||
|
||||
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');
|
||||
} else {
|
||||
panel.setAttribute('hidden', '');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
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();
|
||||
initFloatingQRCodes();
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* AKSRT Yiyan — 一言轮播组件
|
||||
*
|
||||
* Fetches random quotes from hitokoto.cn API and auto-rotates.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function initYiyan(el) {
|
||||
if (el.dataset.yiyanBound) return;
|
||||
el.dataset.yiyanBound = '1';
|
||||
|
||||
var count = parseInt(el.dataset.count || '5', 10);
|
||||
var interval = parseInt(el.dataset.interval || '5', 10) * 1000;
|
||||
var type = el.dataset.type || 'a';
|
||||
var textEl = el.querySelector('.aksrt-yiyan__text');
|
||||
var fromEl = el.querySelector('.aksrt-yiyan__from');
|
||||
var dotsEl = el.querySelector('.aksrt-yiyan__dots');
|
||||
var quotes = [];
|
||||
var currentIndex = 0;
|
||||
var timer = null;
|
||||
|
||||
function showQuote(index) {
|
||||
if (!quotes.length || !textEl) return;
|
||||
var q = quotes[index % quotes.length];
|
||||
textEl.style.opacity = '0';
|
||||
setTimeout(function () {
|
||||
textEl.textContent = '"' + q.text + '"';
|
||||
textEl.style.opacity = '1';
|
||||
if (fromEl) {
|
||||
fromEl.textContent = q.from ? '—— ' + q.from : '';
|
||||
}
|
||||
}, 200);
|
||||
|
||||
// Update dots
|
||||
if (dotsEl) {
|
||||
dotsEl.querySelectorAll('.aksrt-yiyan__dot').forEach(function (dot, i) {
|
||||
dot.classList.toggle('is-active', i === index % quotes.length);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function nextQuote() {
|
||||
currentIndex = (currentIndex + 1) % quotes.length;
|
||||
showQuote(currentIndex);
|
||||
}
|
||||
|
||||
function fetchQuotes() {
|
||||
var url = 'https://v1.hitokoto.cn/?c=' + encodeURIComponent(type) + '&encode=json&count=' + count;
|
||||
fetch(url)
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (data) {
|
||||
// API returns single object or array
|
||||
if (Array.isArray(data)) {
|
||||
quotes = data.map(function (item) {
|
||||
return { text: item.hitokoto || '', from: item.from || '' };
|
||||
});
|
||||
} else if (data && data.hitokoto) {
|
||||
quotes = [{ text: data.hitokoto, from: data.from || '' }];
|
||||
}
|
||||
|
||||
if (!quotes.length) {
|
||||
if (textEl) textEl.textContent = '暂无内容';
|
||||
return;
|
||||
}
|
||||
|
||||
// Build dots
|
||||
if (dotsEl && quotes.length > 1) {
|
||||
dotsEl.innerHTML = '';
|
||||
quotes.forEach(function (_, i) {
|
||||
var dot = document.createElement('span');
|
||||
dot.className = 'aksrt-yiyan__dot' + (i === 0 ? ' is-active' : '');
|
||||
dotsEl.appendChild(dot);
|
||||
});
|
||||
}
|
||||
|
||||
showQuote(0);
|
||||
|
||||
// Auto-rotate
|
||||
if (quotes.length > 1) {
|
||||
timer = setInterval(nextQuote, interval);
|
||||
}
|
||||
})
|
||||
.catch(function () {
|
||||
if (textEl) textEl.textContent = '加载失败,请稍后再试';
|
||||
});
|
||||
}
|
||||
|
||||
// Pause on hover
|
||||
el.addEventListener('mouseenter', function () {
|
||||
if (timer) clearInterval(timer);
|
||||
});
|
||||
el.addEventListener('mouseleave', function () {
|
||||
if (quotes.length > 1) {
|
||||
timer = setInterval(nextQuote, interval);
|
||||
}
|
||||
});
|
||||
|
||||
fetchQuotes();
|
||||
}
|
||||
|
||||
// Auto-init all yiyan widgets
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
document.querySelectorAll('[data-aksrt-yiyan]').forEach(initYiyan);
|
||||
});
|
||||
})();
|
||||
Reference in new issue
Block a user