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

228 lines
9.6 KiB
JavaScript

/** 消息管理:详情、选择与批量操作、发送计数及角色群发确认。仅本页入队。 */
(function () {
'use strict';
var root = document.querySelector('.jio-messages-admin');
if (!root) return;
var compose = document.getElementById('jio-msg-compose');
var detail = document.getElementById('jio-msg-detail');
var confirmDialog = document.getElementById('jio-msg-confirm');
if (!compose || !detail || !confirmDialog || typeof compose.showModal !== 'function') return;
function text(element, key, values) {
var value = element.getAttribute('data-i18n-' + key) || '';
return value.replace(/\{(\w+)\}/g, function (match, name) {
return values && values[name] !== undefined ? String(values[name]) : match;
});
}
function syncScroll() {
document.documentElement.classList.toggle('jio-msg-modal-open', !!root.querySelector('dialog[open]'));
}
function open(dialog) {
if (!dialog.open) dialog.showModal();
syncScroll();
}
root.querySelectorAll('.jio-msg-dialog').forEach(function (dialog) {
var outsideStart = false;
function outside(event) {
var rect = dialog.getBoundingClientRect();
return event.clientX < rect.left || event.clientX > rect.right || event.clientY < rect.top || event.clientY > rect.bottom;
}
dialog.querySelectorAll('[data-jio-dialog-close]').forEach(function (button) {
button.addEventListener('click', function () { dialog.close(); });
});
dialog.addEventListener('pointerdown', function (event) {
outsideStart = event.target === dialog && outside(event);
});
dialog.addEventListener('click', function (event) {
if (outsideStart && event.target === dialog && outside(event)) dialog.close();
outsideStart = false;
});
dialog.addEventListener('close', syncScroll);
});
var pending = null;
var confirmButton = confirmDialog.querySelector('[data-jio-msg-confirm]');
function ask(title, message, label, danger, callback) {
pending = callback;
confirmDialog.querySelector('[data-jio-dialog-title]').textContent = title;
confirmDialog.querySelector('#jio-msg-confirm-text').textContent = message;
confirmButton.textContent = label;
confirmButton.classList.toggle('jio-messages-admin__danger', danger);
confirmButton.classList.toggle('button-primary', !danger);
open(confirmDialog);
confirmDialog.querySelector('[data-jio-dialog-close][autofocus]').focus();
}
confirmDialog.addEventListener('cancel', function () { pending = null; });
confirmDialog.addEventListener('close', function () { pending = null; });
confirmButton.addEventListener('click', function () {
var callback = pending;
pending = null;
confirmDialog.close();
if (callback) callback();
});
root.querySelectorAll('[data-jio-msg-view]').forEach(function (button) {
button.addEventListener('click', function () {
var template = document.getElementById('jio-msg-detail-' + button.getAttribute('data-jio-msg-view'));
if (!template) return;
detail.querySelector('[data-jio-msg-detail-body]').replaceChildren(template.content.cloneNode(true));
open(detail);
});
});
var list = root.querySelector('[data-jio-msg-list]');
var listSubmitting = false;
var syncSelection;
if (list) {
var checks = Array.from(list.querySelectorAll('[data-jio-msg-check]'));
var checkAll = list.querySelector('[data-jio-msg-check-all]');
var selection = list.querySelector('[data-jio-msg-selection]');
var bulkButtons = list.querySelectorAll('[data-jio-msg-action]:not([data-id])');
function selected() { return checks.filter(function (check) { return check.checked; }); }
syncSelection = function () {
var count = selected().length;
selection.textContent = selection.getAttribute('data-label').replace('%d', String(count));
checkAll.checked = count > 0 && count === checks.length;
checkAll.indeterminate = count > 0 && count < checks.length;
checkAll.disabled = listSubmitting || checks.length === 0;
bulkButtons.forEach(function (button) { button.disabled = listSubmitting || count === 0; });
checks.forEach(function (check) { check.closest('tr').classList.toggle('is-selected', check.checked); });
};
checkAll.addEventListener('change', function () {
checks.forEach(function (check) { check.checked = checkAll.checked; });
syncSelection();
});
checks.forEach(function (check) { check.addEventListener('change', syncSelection); });
function mutate(op, id) {
if (listSubmitting) return;
list.elements.bulk_action.value = op;
list.elements.message_id.value = id || '';
list.requestSubmit();
}
list.querySelectorAll('[data-jio-msg-action]').forEach(function (button) {
button.addEventListener('click', function () {
if (listSubmitting) return;
var op = button.getAttribute('data-jio-msg-action');
var id = button.getAttribute('data-id');
var count = id ? 1 : selected().length;
if (!count) return;
if (op === 'delete') {
ask(text(confirmDialog, 'delete-title'), text(confirmDialog, 'delete-text', { count: count }), text(confirmDialog, 'delete-send'), true, function () { mutate(op, id); });
} else {
mutate(op, id);
}
});
});
list.addEventListener('submit', function (event) {
if (listSubmitting || !list.elements.bulk_action.value || (!list.elements.message_id.value && !selected().length)) {
event.preventDefault();
return;
}
listSubmitting = true;
// 只锁操作按钮,不禁用复选框,否则 ids[] 不会随表单提交。
list.querySelectorAll('button').forEach(function (button) { button.disabled = true; });
syncSelection();
});
syncSelection();
}
var form = compose.querySelector('[data-jio-msg-compose]');
var send = form.querySelector('[data-jio-msg-send]');
var role = form.elements.role;
var counters = form.querySelectorAll('[data-count-limit]');
var sending = false;
var approved = '';
function clearApproval() {
approved = '';
form.elements.confirmed_role.value = '';
form.elements.confirmed_count.value = '';
}
function syncCounters() {
counters.forEach(function (field) {
// 与 PHP mb_strlen 一致按 Unicode 码点计数,emoji 不占两个字。
var count = Array.from(field.value).length;
var limit = Number(field.getAttribute('data-count-limit'));
var counter = form.querySelector('[data-count-for="' + field.name + '"]');
counter.textContent = count + ' / ' + limit;
counter.classList.toggle('is-over', count > limit);
field.setCustomValidity(count > limit ? text(form, 'count-error', { count: limit }) : '');
});
}
function syncRole() {
var option = role.options[role.selectedIndex];
var count = option ? Number(option.getAttribute('data-count')) : 0;
form.querySelector('[data-jio-msg-role-hint]').textContent = count > 0 && !option.disabled ? text(form, 'role-hint', { count: count }) : '';
}
function mode() { return form.querySelector('input[name="recipient_mode"]:checked').value; }
function syncMode() {
clearApproval();
form.querySelectorAll('[data-jio-msg-pane]').forEach(function (pane) {
var active = pane.getAttribute('data-jio-msg-pane') === mode();
pane.hidden = !active;
pane.querySelectorAll('input, select, textarea').forEach(function (field) { field.disabled = !active; });
});
syncRole();
}
form.querySelectorAll('input[name="recipient_mode"]').forEach(function (radio) { radio.addEventListener('change', syncMode); });
role.addEventListener('change', function () { clearApproval(); syncRole(); });
form.addEventListener('input', function () { clearApproval(); syncCounters(); });
function snapshot() {
return JSON.stringify([role.value, role.options[role.selectedIndex].getAttribute('data-count'), form.elements.title.value, form.elements.content.value, form.elements.target_url.value]);
}
form.addEventListener('submit', function (event) {
syncCounters();
if (sending || !form.reportValidity()) {
event.preventDefault();
return;
}
if (mode() === 'role' && approved !== snapshot()) {
event.preventDefault();
var option = role.options[role.selectedIndex];
if (!option || option.disabled || !role.value) return;
var count = Number(option.getAttribute('data-count'));
var current = snapshot();
ask(text(form, 'role-title'), text(form, 'role-confirm', { role: option.getAttribute('data-label'), count: count }), text(form, 'role-send'), false, function () {
if (mode() !== 'role' || current !== snapshot()) return;
approved = current;
form.elements.confirmed_role.value = role.value;
form.elements.confirmed_count.value = String(count);
form.requestSubmit(send);
});
return;
}
sending = true;
send.disabled = true;
});
root.querySelectorAll('[data-jio-dialog-open]').forEach(function (button) {
button.addEventListener('click', function () {
open(compose);
var field = mode() === 'role' ? role : form.elements.users;
field.focus();
});
});
window.addEventListener('pageshow', function () {
sending = false;
send.disabled = false;
clearApproval();
if (list) {
listSubmitting = false;
list.elements.bulk_action.value = '';
list.elements.message_id.value = '';
list.querySelectorAll('button[data-id], button[data-jio-msg-view]').forEach(function (button) { button.disabled = false; });
syncSelection();
}
syncCounters();
});
syncMode();
syncCounters();
if (compose.hasAttribute('data-jio-dialog-autoopen')) open(compose);
})();