Files
kate522andClaude Opus 5 35bb96e82f refactor: rename the theme brand and every identifier from AKSRT to Jio
Full-project rename. `git grep -i aksrt` is now empty apart from the
DBMigrator 3.3.0 changelog note that documents the rename itself.

Code identifiers
- PHP namespace AKSRT\ -> Jio\ (composer PSR-4 + 378 declarations)
- global constants AKSRT_* -> JIO_* (VERSION/DIR/URI, PAY_TYPE_*, CAPTCHA_*)
- procedural functions, hooks, options, meta keys, table names,
  cookies, query vars, ajax actions and nonces: aksrt_ -> jio_
- text domain aksrt -> jio; Theme Name -> Jio
- JS globals: aksrtData/aksrtAdminData/... -> jioData/jioAdminData/...,
  window.AKSRTCaptcha & friends -> window.JioCaptcha, Aksrt* -> Jio*
- Vue components Aks*.vue -> Jio*.vue (15 files renamed + imports)
- CSS classes/data-attrs/custom properties: aksrt- -> jio-
- REST namespace aksrt/v1 -> jio/v1 (incl. payment gateway callbacks)

Storage layer
- DB tables {prefix}aksrt_* -> {prefix}jio_*; SCHEMA_VERSION 3.2.0 -> 3.3.0
  so dbDelta creates the new names on install
- widget id_base aksrt_widget_* -> jio_widget_*
- uninstall.php drop list rebuilt from the actual migrator tables
  (dropped 3 stale entries, added the 17 missing ones)

Removed
- hardcoded https://api.aksrt.com/version.json default update endpoint;
  get_endpoint() now reads the 「更新端点」 setting and do_check() no-ops
  when it is empty

Files renamed: inc/helpers/aksrt-*.php -> jio-*.php (54),
assets/admin/src/components/form/Aks*.vue -> Jio*.vue (15).
Build artifacts regenerated: assets/css/build, assets/js/runtime,
assets/admin/build.

Verified: audit-psr4-paths errors=0, audit-admin-contracts errors=0
(warnings=56, unchanged baseline), 813/813 widget-system tests,
44/44 phpunit, php -l clean across all PHP.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-11-01 20:05:04 +08:00

243 lines
7.5 KiB
JavaScript

/**
* Jio 文章导航页 — admin settings modal + HTML5 drag-sort (no SortableJS dependency).
* TOC generation is handled by section-navs.js via [data-nav] + .posts-nav-box.
*
* @package Jio
*/
(function () {
'use strict';
function qs(sel, root) {
return (root || document).querySelector(sel);
}
function qsa(sel, root) {
return Array.prototype.slice.call((root || document).querySelectorAll(sel));
}
function ajaxUrl() {
if (window.jioData && window.jioData.ajaxUrl) return window.jioData.ajaxUrl;
if (window.ajaxurl) return window.ajaxurl;
return '/wp-admin/admin-ajax.php';
}
function initModal() {
var modal = qs('#post-navs-sz');
if (!modal) return;
function openModal(e) {
if (e) e.preventDefault();
modal.classList.add('is-open', 'show');
modal.setAttribute('aria-hidden', 'false');
}
function closeModal(e) {
if (e) e.preventDefault();
modal.classList.remove('is-open', 'show');
modal.setAttribute('aria-hidden', 'true');
}
qsa('[data-toggle="modal"][data-target="#post-navs-sz"], a[href="#post-navs-sz"]').forEach(function (el) {
el.addEventListener('click', openModal);
});
// Title [设置] uses data-target.
qsa('[data-target="#post-navs-sz"]').forEach(function (el) {
el.addEventListener('click', openModal);
});
qsa('[data-dismiss="modal"]', modal).forEach(function (btn) {
btn.addEventListener('click', closeModal);
});
modal.addEventListener('click', function (e) {
if (e.target === modal) closeModal(e);
});
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape' && modal.classList.contains('is-open')) closeModal(e);
});
}
function initDragSort() {
var left = qs('#cat-sortable');
var right = qs('#cat-sortable-ok');
if (!left || !right) return;
var dragEl = null;
function onDragStart(e) {
dragEl = e.currentTarget;
dragEl.classList.add('is-dragging');
try {
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text/plain', dragEl.getAttribute('data-id') || '');
} catch (err) { /* IE */ }
}
function onDragEnd() {
if (dragEl) dragEl.classList.remove('is-dragging');
dragEl = null;
qsa('.cat-group').forEach(function (g) {
g.classList.remove('is-drop-target');
});
}
function bindItem(el) {
el.setAttribute('draggable', 'true');
el.addEventListener('dragstart', onDragStart);
el.addEventListener('dragend', onDragEnd);
}
qsa('.sortable-cat-item', left).forEach(bindItem);
qsa('.sortable-cat-item', right).forEach(bindItem);
[left, right].forEach(function (group) {
group.addEventListener('dragover', function (e) {
e.preventDefault();
group.classList.add('is-drop-target');
if (!dragEl) return;
var after = getDragAfterElement(group, e.clientY);
if (after == null) {
group.appendChild(dragEl);
} else {
group.insertBefore(dragEl, after);
}
});
group.addEventListener('dragleave', function () {
group.classList.remove('is-drop-target');
});
group.addEventListener('drop', function (e) {
e.preventDefault();
group.classList.remove('is-drop-target');
});
});
function getDragAfterElement(container, y) {
var els = qsa('.sortable-cat-item:not(.is-dragging)', container);
var closest = { offset: Number.NEGATIVE_INFINITY, element: null };
els.forEach(function (child) {
var box = child.getBoundingClientRect();
var offset = y - box.top - box.height / 2;
if (offset < 0 && offset > closest.offset) {
closest = { offset: offset, element: child };
}
});
return closest.element;
}
}
function initSave() {
var form = qs('#jio-posts-navs-settings');
if (!form) return;
form.addEventListener('submit', function (e) {
e.preventDefault();
var ids = [];
qsa('#cat-sortable-ok .sortable-cat-item').forEach(function (item) {
var id = item.getAttribute('data-id');
if (id) ids.push(id);
});
if (!ids.length) {
notyf('请选择需要显示的分类', 'danger');
return;
}
var fd = new FormData(form);
fd.set('action', 'jio_post_navs_settings');
// PHP accepts array; append each.
fd.delete('navs_show_cat_id');
ids.forEach(function (id) {
fd.append('navs_show_cat_id[]', id);
});
var btn = qs('button[type="submit"]', form);
if (btn) btn.disabled = true;
fetch(ajaxUrl(), {
method: 'POST',
body: fd,
credentials: 'same-origin',
})
.then(function (r) { return r.json(); })
.then(function (data) {
if (!data || data.error) {
notyf((data && data.msg) || '保存失败', 'danger');
return;
}
notyf(data.msg || '保存成功', 'success');
if (data.reload) {
window.setTimeout(function () { window.location.reload(); }, 400);
}
})
.catch(function () {
notyf('网络错误', 'danger');
})
.finally(function () {
if (btn) btn.disabled = false;
});
});
}
/**
* Build simple TOC into .posts-nav-box if section-navs hasn't already.
* Uses category h2 headings inside .posts-navs.
*/
function initFallbackToc() {
var box = qs('.posts-nav-box');
var root = qs('.posts-navs[data-nav]');
if (!box || !root) return;
if (box.querySelector('.posts-nav-lists, .jio-section-nav, .toc-list')) return;
var headings = qsa('.title-theme h2, h2', root);
if (headings.length < 1) return;
var title = box.getAttribute('data-title') || '导航目录';
var list = '';
headings.forEach(function (h, i) {
if (!h.id) h.id = 'navs-sec-' + i;
list += '<li class="n-H2"><a class="text-ellipsis" href="#' + h.id + '">' + (h.textContent || '').trim() + '</a></li>';
});
box.innerHTML =
'<div class="box-body notop"><div class="title-theme">' + title + '</div></div>' +
'<div class="jio-panel"><div class="posts-nav-lists scroll-y mini-scrollbar list-unstyled">' +
'<ul class="bl relative nav">' + list + '</ul></div></div>';
qsa('a[href^="#"]', box).forEach(function (a) {
a.addEventListener('click', function (e) {
var id = a.getAttribute('href');
var el = id ? document.getElementById(id.replace(/^#/, '')) : null;
if (!el) return;
e.preventDefault();
var top = el.getBoundingClientRect().top + window.pageYOffset - 90;
window.scrollTo({ top: top, behavior: 'smooth' });
});
});
function highlight() {
var y = window.pageYOffset + 120;
var current = headings[0];
headings.forEach(function (h) {
if (h.offsetTop <= y) current = h;
});
qsa('li', box).forEach(function (li) {
var a = li.querySelector('a');
if (a && current && a.getAttribute('href') === '#' + current.id) {
li.classList.add('active');
} else {
li.classList.remove('active');
}
});
}
window.addEventListener('scroll', highlight, { passive: true });
highlight();
}
function init() {
initModal();
initDragSort();
initSave();
// Defer so section-navs.js can own TOC first.
window.setTimeout(initFallbackToc, 50);
}
jQuery(document).off('auto_fun.jio-posts-navs-page').on('auto_fun.jio-posts-navs-page', function () { init(document); });
})();