feat(widgets): rebuild admin widgets page to match reference theme
- Replace transfer modal/admin-post flow with reference-style AJAX export/import/template dialogs (admin-transfer.js, TransferController) - Customizer "移出模块" action, reference lazy form loading with t-notice - Common fields use reference labels, dependencies, compact/inline rows, top/bottom-only extra spacing; form header with description/reminder - Remove placement hint, template preview and legacy transfer code - Fix widget audit (current_datetime stub, honor catalog common flags) and regenerate stale golden fixtures for posts_toc, quote, posts Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ea80cd96cc
commit
a579a5b00a
14 files changed
+698
-446
No files matched your search
+18
-126
@@ -22,7 +22,6 @@
|
||||
});
|
||||
evaluateDependencies($root);
|
||||
updateWidgetTitle($root);
|
||||
updatePlacementWarning($root);
|
||||
updateRepeaterControls($root);
|
||||
}
|
||||
|
||||
@@ -54,82 +53,6 @@
|
||||
}).first().replaceWith(`${title} `);
|
||||
}
|
||||
|
||||
function updatePlacementWarning(root) {
|
||||
const $widget = $(root).closest('.widget');
|
||||
const $hint = $widget.find('.aksrt-widget-placement-hint').first();
|
||||
if (!$hint.length) return;
|
||||
const size = String($hint.data('widget-size') || 'any');
|
||||
const area = String($widget.closest('.widgets-sortables').attr('id') || '');
|
||||
const isSidebar = /sidebar/.test(area);
|
||||
$hint.toggleClass('is-warning', (size === 'wide' && isSidebar) || (size === 'sidebar' && !isSidebar && area !== ''));
|
||||
}
|
||||
|
||||
function injectTransferToolbar($anchor, sidebarId) {
|
||||
if (!$anchor?.length || !sidebarId || $anchor.next('.aksrt-widget-transfer-toolbar').length) return;
|
||||
const $toolbar = $('<div class="aksrt-widget-transfer-toolbar" role="group"></div>');
|
||||
[
|
||||
['export', config.i18n?.export || '导出'],
|
||||
['import', config.i18n?.import || '导入'],
|
||||
['template', config.i18n?.template || '应用模板'],
|
||||
].forEach(([action, label]) => {
|
||||
$('<button type="button" class="button button-small"></button>')
|
||||
.text(label)
|
||||
.attr('data-aksrt-transfer-action', action)
|
||||
.attr('data-sidebar-id', sidebarId)
|
||||
.appendTo($toolbar);
|
||||
});
|
||||
$anchor.after($toolbar);
|
||||
}
|
||||
|
||||
function scanWidgetAreas() {
|
||||
$('.widgets-holder-wrap:not(#available-widgets):not(.inactive-sidebar)').each(function () {
|
||||
const $wrap = $(this);
|
||||
const $sortables = $wrap.find('.widgets-sortables').first();
|
||||
const sidebarId = String($sortables.attr('id') || '');
|
||||
if (!sidebarId) return;
|
||||
const $description = $sortables.find('.sidebar-description .description').first();
|
||||
const $anchor = $description.length ? $description : $sortables.find('.description').first();
|
||||
if ($anchor.length) injectTransferToolbar($anchor, sidebarId);
|
||||
});
|
||||
|
||||
$('.control-section-sidebar').each(function () {
|
||||
const $section = $(this);
|
||||
const sectionId = String($section.attr('id') || '');
|
||||
const prefix = 'sub-accordion-section-sidebar-widgets-';
|
||||
if (!sectionId.startsWith(prefix)) return;
|
||||
const sidebarId = sectionId.slice(prefix.length);
|
||||
const $description = $section.find('.section-meta .description').first();
|
||||
const $anchor = $description.length ? $description : $section.find('.accordion-section-title, .customize-section-title').first();
|
||||
if ($anchor.length) injectTransferToolbar($anchor, sidebarId);
|
||||
});
|
||||
|
||||
$('.customize-control-widget_form').each(function () {
|
||||
const $control = $(this);
|
||||
const $nav = $control.find('.widget-reorder-nav').first();
|
||||
if (!$nav.length || $nav.find('.aksrt-widget-customizer-remove').length) return;
|
||||
$('<button type="button" class="button-link-delete aksrt-widget-customizer-remove" aria-label="移除此小工具">移除</button>').appendTo($nav);
|
||||
});
|
||||
}
|
||||
|
||||
function openTransferModal(action, sidebarId) {
|
||||
const $modal = $('#aksrt-widget-transfer-modal');
|
||||
if (!$modal.length) return;
|
||||
const sidebars = config.sidebars || {};
|
||||
const areaName = sidebars[sidebarId] || sidebarId;
|
||||
$modal.find('.aksrt-widget-transfer-modal__area').text(areaName);
|
||||
$modal.find('input[name="sidebar"], input[name="target_sidebar"]').val(sidebarId);
|
||||
$modal.find('[data-transfer-tab]').removeClass('is-active');
|
||||
$modal.find(`[data-transfer-tab="${action}"]`).addClass('is-active');
|
||||
$modal.find('[data-transfer-panel]').prop('hidden', true);
|
||||
$modal.find(`[data-transfer-panel="${action}"]`).prop('hidden', false);
|
||||
$modal.prop('hidden', false).addClass('is-open').attr('aria-hidden', 'false');
|
||||
$modal.find('[data-transfer-panel="' + action + '"] button, [data-transfer-panel="' + action + '"] input, [data-transfer-panel="' + action + '"] select').filter(':visible').first().trigger('focus');
|
||||
}
|
||||
|
||||
function closeTransferModal() {
|
||||
$('#aksrt-widget-transfer-modal').removeClass('is-open').attr('aria-hidden', 'true').prop('hidden', true);
|
||||
}
|
||||
|
||||
function loadForm(container) {
|
||||
const $container = $(container);
|
||||
if ($container.data('loading') || $container.data('loaded')) return;
|
||||
@@ -138,7 +61,8 @@
|
||||
const number = core.resolveWidgetNumber(inputName, $widget.attr('id'), $container.data('widget-number'));
|
||||
// New-widget templates use __i__ until WordPress assigns a real instance number.
|
||||
if (!number) return;
|
||||
$container.data('loading', true).find('.aksrt-widget-form-lazy__status').text(config.i18n?.loading || 'Loading…');
|
||||
$container.data('loading', true);
|
||||
setLazyStatus($container, 'loading', config.i18n?.loading || '正在加载模块配置…');
|
||||
$.post(config.ajaxUrl, {
|
||||
action: config.action,
|
||||
nonce: config.nonce,
|
||||
@@ -146,17 +70,25 @@
|
||||
widget_number: number,
|
||||
}).done((response) => {
|
||||
if (!response?.success || !response.data?.html) {
|
||||
$container.data('loading', false).find('.aksrt-widget-form-lazy__status').text(response?.data?.message || config.i18n?.error || 'Failed to load.');
|
||||
$container.data('loading', false);
|
||||
setLazyStatus($container, 'error', response?.data?.message || config.i18n?.error || '加载失败,请刷新页面后重试');
|
||||
return;
|
||||
}
|
||||
const $form = $(response.data.html);
|
||||
$container.replaceWith($form);
|
||||
$container.data('loaded', true).replaceWith($form);
|
||||
initForm($form);
|
||||
}).fail(() => {
|
||||
$container.data('loading', false).find('.aksrt-widget-form-lazy__status').text(config.i18n?.error || 'Failed to load.');
|
||||
}).fail((xhr) => {
|
||||
$container.data('loading', false);
|
||||
setLazyStatus($container, 'error', xhr?.responseJSON?.data?.message || config.i18n?.error || '加载失败,请刷新页面后重试');
|
||||
});
|
||||
}
|
||||
|
||||
/* Lazy placeholder status uses the reference t-notice box (t-loading / t-error). */
|
||||
function setLazyStatus($container, type, message) {
|
||||
const $notice = $('<div class="t-notice"></div>').addClass(`t-${type}`).text(message);
|
||||
$container.find('.aksrt-widget-form-lazy__status').empty().append($notice);
|
||||
}
|
||||
|
||||
function renumberRepeaters(_event, ui) {
|
||||
const $form = $(ui?.item || this).closest('.aksrt-widget-form');
|
||||
$form.find('.aksrt-widget-repeater__rows').each(function () {
|
||||
@@ -216,24 +148,10 @@
|
||||
}
|
||||
|
||||
$(document)
|
||||
.on('click', '[data-aksrt-transfer-action]', function () {
|
||||
openTransferModal(String($(this).data('aksrt-transfer-action')), String($(this).data('sidebar-id')));
|
||||
.on('click', '.widget-top', function () {
|
||||
const $widget = $(this).closest('.widget, .customize-control-widget_form');
|
||||
window.setTimeout(() => $widget.find('.aksrt-widget-form-lazy').each(function () { loadForm(this); }), 20);
|
||||
})
|
||||
.on('click', '[data-aksrt-transfer-close]', closeTransferModal)
|
||||
.on('click', '[data-transfer-tab]', function () {
|
||||
const $modal = $(this).closest('.aksrt-widget-transfer-modal');
|
||||
const panel = String($(this).data('transfer-tab'));
|
||||
$modal.find('[data-transfer-tab]').removeClass('is-active');
|
||||
$(this).addClass('is-active');
|
||||
$modal.find('[data-transfer-panel]').prop('hidden', true);
|
||||
$modal.find(`[data-transfer-panel="${panel}"]`).prop('hidden', false);
|
||||
})
|
||||
.on('click', '.aksrt-widget-customizer-remove', function (event) {
|
||||
event.preventDefault();
|
||||
$(this).closest('.customize-control-widget_form').find('.widget-control-remove').first().trigger('click');
|
||||
})
|
||||
.on('click', '.aksrt-widget-form-lazy__load', function () { loadForm($(this).closest('.aksrt-widget-form-lazy')); })
|
||||
.on('click', '.widget.open .aksrt-widget-form-lazy, .customize-control-widget_form .aksrt-widget-form-lazy', function () { loadForm(this); })
|
||||
.on('change input', '.aksrt-widget-form input, .aksrt-widget-form select, .aksrt-widget-form textarea', function () {
|
||||
const $form = $(this).closest('.aksrt-widget-form');
|
||||
evaluateDependencies($form);
|
||||
@@ -300,31 +218,10 @@
|
||||
const $wrap = $(this).closest('.aksrt-widget-upload');
|
||||
$wrap.find('input[type="url"]').val('').trigger('change');
|
||||
$wrap.find('img').remove();
|
||||
})
|
||||
.on('click', '.aksrt-widget-template-preview', function () {
|
||||
const $form = $(this).closest('form');
|
||||
const $output = $('.aksrt-widget-template-preview-output').first();
|
||||
$output.prop('hidden', false).html('<p>正在生成预览…</p>');
|
||||
$.post(config.ajaxUrl, {
|
||||
action: 'aksrt_widgets_template_preview',
|
||||
nonce: config.transferNonce,
|
||||
template: $form.find('[name="template"]').val(),
|
||||
}).done((response) => {
|
||||
if (!response?.success || !response.data) {
|
||||
$output.empty().append($('<p class="notice notice-error"></p>').text(response?.data?.message || config.i18n?.error || '预览加载失败,请重试。'));
|
||||
return;
|
||||
}
|
||||
$output.html(response.data.html || '<p>模板为空。</p>');
|
||||
}).fail((xhr) => {
|
||||
const message = xhr?.responseJSON?.data?.message || config.i18n?.error || '预览加载失败,请重试。';
|
||||
$output.empty().append($('<p class="notice notice-error"></p>').text(message));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('widget-added widget-updated', function (_event, widget) {
|
||||
$(widget).find('.aksrt-widget-form-lazy').each(function () { loadForm(this); });
|
||||
updatePlacementWarning(widget);
|
||||
scanWidgetAreas();
|
||||
});
|
||||
|
||||
if (window.wp?.customize?.bind) {
|
||||
@@ -332,7 +229,6 @@
|
||||
$('#customize-theme-controls').on('expanded', function (_event, section) {
|
||||
if (!section || !String(section.id || section).includes('sidebar-widgets')) return;
|
||||
window.setTimeout(function () {
|
||||
scanWidgetAreas();
|
||||
$('.customize-control-widget_form .aksrt-widget-form-lazy').each(function () { loadForm(this); });
|
||||
}, 100);
|
||||
});
|
||||
@@ -340,10 +236,6 @@
|
||||
}
|
||||
|
||||
$(function () {
|
||||
scanWidgetAreas();
|
||||
$(document).on('keydown', function (event) {
|
||||
if (event.key === 'Escape') closeTransferModal();
|
||||
});
|
||||
$('.aksrt-widget-form').each(function () { initForm(this); });
|
||||
$('.widget.open .aksrt-widget-form-lazy').each(function () { loadForm(this); });
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user