feat: rewrite schema-driven widget system

This commit is contained in:
kate522 committed 2026-08-17 17:29:54 +08:00
1 parent 6c6c462df8
commit ad99ab53ce
28 files changed
+3489

No files matched your search

+166
View File
@@ -0,0 +1,166 @@
.aksrt-widget-form {
--aksrt-field-border: #dcdcde;
--aksrt-field-accent: #2271b1;
display: grid;
gap: 14px;
padding: 4px 0 10px;
}
.aksrt-widget-field {
min-width: 0;
}
.aksrt-widget-field[hidden] {
display: none !important;
}
.aksrt-widget-field__label {
display: block;
margin-bottom: 6px;
font-weight: 600;
}
.aksrt-widget-field .description {
margin: -2px 0 7px;
}
.aksrt-widget-switch {
display: inline-flex;
cursor: pointer;
}
.aksrt-widget-switch input {
position: absolute;
opacity: 0;
}
.aksrt-widget-switch span {
position: relative;
width: 38px;
height: 22px;
border-radius: 999px;
background: #8c8f94;
transition: background .18s ease;
}
.aksrt-widget-switch span::after {
content: "";
position: absolute;
top: 3px;
left: 3px;
width: 16px;
height: 16px;
border-radius: 50%;
background: #fff;
transition: transform .18s ease;
}
.aksrt-widget-switch input:checked + span { background: var(--aksrt-field-accent); }
.aksrt-widget-switch input:checked + span::after { transform: translateX(16px); }
.aksrt-widget-switch input:focus-visible + span { outline: 2px solid #72aee6; outline-offset: 2px; }
.aksrt-widget-choices {
display: flex;
flex-wrap: wrap;
gap: 6px;
}
.aksrt-widget-choices label input {
position: absolute;
opacity: 0;
}
.aksrt-widget-choices label span {
display: block;
padding: 5px 9px;
border: 1px solid var(--aksrt-field-border);
border-radius: 5px;
background: #fff;
cursor: pointer;
}
.aksrt-widget-choices label input:checked + span {
border-color: var(--aksrt-field-accent);
color: var(--aksrt-field-accent);
box-shadow: 0 0 0 1px var(--aksrt-field-accent);
}
.aksrt-widget-number,
.aksrt-widget-icon,
.aksrt-widget-link,
.aksrt-widget-background {
display: grid;
gap: 7px;
}
.aksrt-widget-number {
grid-template-columns: minmax(0, 1fr) 50px;
align-items: center;
}
.aksrt-widget-upload {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 7px;
}
.aksrt-widget-upload img {
width: 100%;
max-height: 150px;
border-radius: 6px;
object-fit: cover;
}
.aksrt-widget-upload .widefat { flex: 1 1 100%; }
.aksrt-widget-spacing {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 6px;
}
.aksrt-widget-spacing label span {
display: block;
margin-bottom: 3px;
color: #646970;
text-align: center;
}
.aksrt-widget-repeater__row,
.aksrt-widget-nested {
margin-bottom: 9px;
border: 1px solid var(--aksrt-field-border);
border-radius: 6px;
background: #fff;
}
.aksrt-widget-repeater__bar {
display: flex;
align-items: center;
gap: 7px;
padding: 8px 10px;
border-bottom: 1px solid var(--aksrt-field-border);
background: #f6f7f7;
}
.aksrt-widget-repeater__bar .dashicons { cursor: move; }
.aksrt-widget-repeater__bar strong { flex: 1; }
.aksrt-widget-repeater__fields,
.aksrt-widget-nested__body { display: grid; gap: 12px; padding: 10px; }
.aksrt-widget-nested > summary { padding: 9px 10px; font-weight: 600; cursor: pointer; }
.aksrt-widget-form-lazy {
padding: 14px;
border: 1px dashed #c3c4c7;
border-radius: 6px;
text-align: center;
}
.aksrt-widget-form-lazy__status { margin-top: 0; color: #646970; }
@media (prefers-reduced-motion: reduce) {
.aksrt-widget-switch span,
.aksrt-widget-switch span::after { transition: none; }
}
+129
View File
@@ -0,0 +1,129 @@
(function ($) {
'use strict';
const config = window.aksrtWidgetAdmin || {};
function initForm(root) {
const $root = $(root);
$root.find('.aksrt-widget-color').wpColorPicker();
$root.find('.aksrt-widget-repeater__rows').sortable({
handle: '.dashicons-move',
axis: 'y',
update: renumberRepeaters,
});
$root.find('input[type="range"]').each(function () {
const output = this.parentElement.querySelector('output');
if (output) this.addEventListener('input', () => { output.textContent = this.value; });
});
evaluateDependencies($root);
}
function loadForm(container) {
const $container = $(container);
if ($container.data('loading') || $container.data('loaded')) return;
$container.data('loading', true).find('.aksrt-widget-form-lazy__status').text(config.i18n?.loading || 'Loading…');
$.post(config.ajaxUrl, {
action: config.action,
nonce: config.nonce,
id_base: $container.data('id-base'),
widget_number: $container.data('widget-number'),
}).done((response) => {
if (!response?.success || !response.data?.html) throw new Error('Invalid response');
const $form = $(response.data.html);
$container.replaceWith($form);
initForm($form);
}).fail(() => {
$container.data('loading', false).find('.aksrt-widget-form-lazy__status').text(config.i18n?.error || 'Failed to load.');
});
}
function renumberRepeaters(_event, ui) {
const $form = $(ui?.item || this).closest('.aksrt-widget-form');
$form.find('.aksrt-widget-repeater__rows').each(function () {
$(this).children('.aksrt-widget-repeater__row').each(function (index) {
this.dataset.rowIndex = String(index);
});
});
$form.find('[name]').each(function () {
const rowIndexes = $(this).parents('.aksrt-widget-repeater__row').get().reverse().map((row) => Number(row.dataset.rowIndex || 0));
if (!rowIndexes.length) return;
let foundWidgetNumber = false;
let cursor = 0;
this.name = this.name.replace(/\[(\d+|__index_[a-f0-9]+__)\]/g, (match, index) => {
if (!foundWidgetNumber && /^\d+$/.test(index)) {
foundWidgetNumber = true;
return match;
}
return cursor < rowIndexes.length ? `[${rowIndexes[cursor++]}]` : match;
});
});
}
function fieldValue($form, id) {
const $field = $form.find(`.aksrt-widget-field[data-field-id="${CSS.escape(id)}"]`).first();
const $checked = $field.find('input:checked').first();
if ($checked.length) return String($checked.val());
return String($field.find('input,select,textarea').first().val() ?? '');
}
function evaluateDependencies($form) {
$form.find('[data-dependency]').each(function () {
let rule;
try { rule = JSON.parse(this.dataset.dependency || '[]'); } catch (_error) { return; }
if (!Array.isArray(rule) || rule.length < 3) return;
const $row = $(this).closest('.aksrt-widget-repeater__row');
const current = fieldValue($row.length ? $row : $form, String(rule[0]));
const expected = String(rule[2]);
const visible = rule[1] === '==' ? current === expected : current !== expected;
this.hidden = !visible;
});
}
$(document)
.on('click', '.aksrt-widget-form-lazy__load', function () { loadForm($(this).closest('.aksrt-widget-form-lazy')); })
.on('click', '.widget.open .aksrt-widget-form-lazy', function () { loadForm(this); })
.on('change input', '.aksrt-widget-form input, .aksrt-widget-form select, .aksrt-widget-form textarea', function () { evaluateDependencies($(this).closest('.aksrt-widget-form')); })
.on('click', '.aksrt-widget-repeater__add', function () {
const $repeater = $(this).closest('.aksrt-widget-repeater');
const max = Number($repeater.data('max-items') || 50);
const $rows = $repeater.children('.aksrt-widget-repeater__rows');
if ($rows.children().length >= max) return;
const index = $rows.children().length;
const token = String($repeater.data('index-token') || '__index__');
const html = $repeater.children('template').html().replaceAll(token, String(index));
const $row = $(html).appendTo($rows);
initForm($row);
renumberRepeaters.call($rows[0]);
})
.on('click', '.aksrt-widget-repeater__remove', function () {
const $rows = $(this).closest('.aksrt-widget-repeater__rows');
$(this).closest('.aksrt-widget-repeater__row').remove();
renumberRepeaters.call($rows[0]);
})
.on('click', '.aksrt-widget-upload__choose', function () {
const $wrap = $(this).closest('.aksrt-widget-upload');
const frame = wp.media({ title: '选择媒体', multiple: false });
frame.on('select', () => {
const attachment = frame.state().get('selection').first().toJSON();
$wrap.find('input[type="url"]').val(attachment.url).trigger('change');
let $image = $wrap.find('img');
if (!$image.length) $image = $('<img alt="">').prependTo($wrap);
$image.attr('src', attachment.url);
});
frame.open();
})
.on('click', '.aksrt-widget-upload__remove', function () {
const $wrap = $(this).closest('.aksrt-widget-upload');
$wrap.find('input[type="url"]').val('').trigger('change');
$wrap.find('img').remove();
});
$(document).on('widget-added widget-updated', function (_event, widget) {
$(widget).find('.aksrt-widget-form-lazy').each(function () { loadForm(this); });
});
$(function () {
$('.aksrt-widget-form').each(function () { initForm(this); });
$('.widget.open .aksrt-widget-form-lazy').each(function () { loadForm(this); });
});
})(jQuery);
+135
View File
@@ -0,0 +1,135 @@
.aksrt-widget {
--aksrt-widget-bg-light: transparent;
--aksrt-widget-bg-dark: transparent;
--aksrt-widget-radius: 12px;
margin: var(--aksrt-widget-space-top, 0) var(--aksrt-widget-space-right, 0) var(--aksrt-widget-space-bottom, 20px) var(--aksrt-widget-space-left, 0);
background-color: var(--aksrt-widget-bg-light);
background-image: var(--aksrt-widget-bg-image-light, none);
background-position: center;
background-size: cover;
color: var(--theme-color, #2d2d35);
}
.dark-theme .aksrt-widget,
[data-theme="dark"] .aksrt-widget { background-color: var(--aksrt-widget-bg-dark); background-image: var(--aksrt-widget-bg-image-dark, none); color: #e7e7ea; }
.aksrt-widget *, .aksrt-widget *::before, .aksrt-widget *::after { box-sizing: border-box; }
.aksrt-widget img, .aksrt-widget video { max-width: 100%; }
.aksrt-widget a { color: inherit; text-decoration: none; }
.aksrt-widget button, .aksrt-widget input { font: inherit; }
.aksrt-widget__header { display: flex; align-items: flex-end; justify-content: space-between; gap: 18px; margin-bottom: 16px; }
.aksrt-widget__header--big { display: block; text-align: center; margin-bottom: 30px; }
.aksrt-widget__title { margin: 0; font-size: 20px; line-height: 1.35; font-weight: 700; }
.aksrt-widget__header--big .aksrt-widget__title { font-size: clamp(27px, 4vw, 42px); }
.aksrt-widget__title mark { padding: 0; background: transparent; color: var(--focus-color, #ff5473); }
.aksrt-widget__subtitle { margin: 7px 0 0; color: var(--muted-color, #8a8c98); }
.aksrt-widget__title-links { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
.aksrt-widget__title-links a { padding: 5px 11px; border-radius: 999px; background: #f2f3f5; font-size: 13px; }
.dark-theme .aksrt-widget__title-links a, [data-theme="dark"] .aksrt-widget__title-links a { background: #292a30; }
.aksrt-widget-grid { display: grid; grid-template-columns: repeat(var(--aksrt-cols, 3), minmax(0, 1fr)); gap: 16px; }
.aksrt-widget__empty, .aksrt-widget-request-error { padding: 28px 18px; border: 1px dashed rgba(127,127,127,.25); border-radius: var(--aksrt-widget-radius); color: var(--muted-color, #8a8c98); text-align: center; }
.aksrt-widget-request-error button { margin-left: 10px; padding: 5px 12px; border: 0; border-radius: 999px; cursor: pointer; }
.aksrt-widget--affix { position: sticky; top: 76px; }
.aksrt-widget--only-mobile { display: none; }
.aksrt-widget-search { display: flex; min-height: 46px; padding: 5px; border: 1px solid rgba(127,127,127,.18); border-radius: 10px; background: var(--main-bg, #fff); box-shadow: 0 8px 25px rgba(31,35,48,.06); }
.aksrt-widget-search label { flex: 1; display: flex; }
.aksrt-widget-search input { width: 100%; padding: 8px 12px; border: 0; outline: 0; background: transparent; color: inherit; }
.aksrt-widget-search button { display: flex; align-items: center; gap: 7px; padding: 8px 16px; border: 0; border-radius: 8px; background: var(--focus-color, #ff5473); color: #fff; cursor: pointer; }
.aksrt-widget-search--compact button span { display: none; }
.aksrt-widget-search--large { min-height: 58px; border-radius: 14px; }
.aksrt-widget-toc { padding: 14px 16px; border-radius: var(--aksrt-widget-radius); background: var(--main-bg, #fff); box-shadow: 0 8px 30px rgba(31,35,48,.06); }
.aksrt-widget-toc__toggle { display: flex; width: 100%; align-items: center; justify-content: space-between; padding: 0; border: 0; background: transparent; color: inherit; font-weight: 700; cursor: pointer; }
.aksrt-widget-toc__list { margin: 14px 0 0; padding-left: 20px; max-height: 55vh; overflow: auto; }
.aksrt-widget-toc__list li { margin: 7px 0; color: var(--muted-color, #737582); }
.aksrt-widget-toc__list .level-h3 { padding-left: 12px; font-size: 14px; }
.aksrt-widget-toc__list .level-h4 { padding-left: 24px; font-size: 13px; }
.aksrt-widget-toc.is-collapsed .aksrt-widget-toc__list { display: none; }
.aksrt-widget-quote { position: relative; min-height: 130px; margin: 0; padding: 24px 48px 24px 25px; overflow: hidden; border-radius: var(--aksrt-widget-radius); background: linear-gradient(135deg, #6772e5, #8b5cf6); color: #fff; }
.aksrt-widget-quote > i { opacity: .35; font-size: 26px; }
.aksrt-widget-quote blockquote { margin: 12px 0 0; font-size: 16px; line-height: 1.8; }
.aksrt-widget-quote button { position: absolute; right: 13px; bottom: 13px; width: 30px; height: 30px; border: 0; border-radius: 50%; background: rgba(255,255,255,.16); color: #fff; cursor: pointer; }
.aksrt-widget-icon-card, .aksrt-widget-icon-cards .icon-card, .aksrt-widget-icon-cards .icon-cover-card { min-height: 130px; padding: 22px; border-radius: var(--aksrt-widget-radius); background: var(--main-bg, #fff); box-shadow: 0 10px 32px rgba(31,35,48,.07); transition: transform .25s, box-shadow .25s; }
.aksrt-widget-icon-card:hover, .aksrt-widget-icon-cards .icon-card:hover, .aksrt-widget-icon-cards .icon-cover-card:hover { transform: translateY(-4px); box-shadow: 0 16px 40px rgba(31,35,48,.12); }
.aksrt-widget-icon-card { display: flex; flex-direction: column; gap: 12px; text-align: center; }
.aksrt-widget-icon-cards--cover .aksrt-widget-icon-card { flex-direction: row; align-items: center; text-align: left; }
.aksrt-widget-icon-card > i { font-size: 34px; color: var(--focus-color, #ff5473); }
.aksrt-widget-icon-card span { display: flex; flex-direction: column; gap: 5px; }
.aksrt-widget-icon-card small { color: var(--muted-color, #8a8c98); }
.aksrt-widget-video { position: relative; overflow: hidden; border-radius: var(--aksrt-widget-radius); background: #000; aspect-ratio: 16 / 9; }
.aksrt-widget-video--4-3 { aspect-ratio: 4 / 3; }.aksrt-widget-video--1-1 { aspect-ratio: 1; }.aksrt-widget-video--auto { aspect-ratio: auto; }
.aksrt-widget-video video, .aksrt-widget-video__player, .aksrt-widget-video .dplayer { width: 100%; height: 100%; }
.aksrt-widget-media-error { position: absolute; inset: auto 15px 15px; color: #fff; }
.aksrt-widget-embed { position: relative; height: 0; padding-bottom: var(--aksrt-embed-ratio, 56.25%); overflow: hidden; border-radius: var(--aksrt-widget-radius); background: #111; }
.aksrt-widget-embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.aksrt-media-card { position: relative; display: block; overflow: hidden; min-height: 180px; border-radius: var(--aksrt-widget-radius); background: var(--main-bg, #fff); box-shadow: 0 8px 28px rgba(31,35,48,.07); }
.aksrt-media-card__media { display: block; aspect-ratio: 16 / 9; overflow: hidden; background: #eceef2; }
.aksrt-media-card__media img, .aksrt-media-card__media video { width: 100%; height: 100%; object-fit: cover; transition: transform .35s; }
.aksrt-media-card:hover .aksrt-media-card__media img { transform: scale(1.04); }
.aksrt-media-card__image--dark { display: none; }
.dark-theme .aksrt-media-card__image--dark, [data-theme="dark"] .aksrt-media-card__image--dark { display: block; }
.dark-theme .aksrt-media-card__image--dark ~ .aksrt-media-card__image, [data-theme="dark"] .aksrt-media-card__image--dark ~ .aksrt-media-card__image { display: none; }
.aksrt-media-card__body { display: flex; flex-direction: column; gap: 5px; padding: 14px 16px 16px; }
.aksrt-media-card__body small { color: var(--muted-color, #8a8c98); }
.aksrt-widget-partners { overflow: hidden; padding: 5px 0; }
.aksrt-widget-partners__track { display: grid; grid-auto-flow: column; grid-template-rows: repeat(var(--aksrt-partner-rows), 76px); grid-auto-columns: 210px; gap: 12px; width: max-content; animation: aksrt-partners var(--aksrt-partner-speed) linear infinite; }
.aksrt-widget-partners:hover .aksrt-widget-partners__track { animation-play-state: paused; }
.aksrt-widget-partners .aksrt-media-card { display: flex; min-height: 76px; align-items: center; }
.aksrt-widget-partners .aksrt-media-card__media { width: 64px; aspect-ratio: 1; margin-left: 8px; border-radius: 9px; }
.aksrt-widget-partners .aksrt-media-card__body { padding: 10px; }
@keyframes aksrt-partners { to { transform: translateX(-50%); } }
.aksrt-combo-card { overflow: hidden; border-radius: var(--aksrt-widget-radius); background: var(--main-bg,#fff); box-shadow: 0 8px 28px rgba(31,35,48,.07); }
.aksrt-combo-card .aksrt-media-card { box-shadow: none; }
.aksrt-combo-card__tags { display: flex; flex-wrap: wrap; gap: 5px; padding: 0 16px 16px; }
.aksrt-combo-card__tags span { padding: 3px 8px; border-radius: 999px; background: rgba(127,127,127,.1); font-size: 12px; }
.aksrt-widget-text-title { padding: 18px 0; }.aksrt-widget-text-title.is-center { text-align: center; }.aksrt-widget-text-title.is-right { text-align: right; }
.aksrt-widget-text-title h2 { margin: 0; font-size: clamp(26px,4vw,44px); line-height: 1.25; }.aksrt-widget-text-title p { margin: 12px 0 0; color: var(--muted-color,#8a8c98); line-height: 1.8; }
.aksrt-widget-buttons { display: flex; flex-wrap: wrap; gap: var(--aksrt-button-gap,10px); }.aksrt-widget-buttons.is-center { justify-content: center; }.aksrt-widget-buttons.is-right { justify-content: flex-end; }
.aksrt-widget-button { display: inline-flex; min-height: 40px; padding: 9px 18px; align-items: center; justify-content: center; gap: 7px; border: 0; border-radius: 9px; background: var(--focus-color,#ff5473); color: #fff !important; font-weight: 600; cursor: pointer; transition: filter .2s, transform .2s; }
.aksrt-widget-button:hover { filter: brightness(1.07); transform: translateY(-1px); }.aksrt-widget-button.is-ghost { background: rgba(127,127,127,.12); color: inherit !important; }
.aksrt-widget-gap { height: var(--aksrt-gap); }
.aksrt-widget-tag-cloud { display: flex; flex-wrap: wrap; gap: 8px; }.aksrt-widget-tag-cloud a { padding: 6px 11px; border-radius: 6px; background: rgba(127,127,127,.1); font-size: 13px; transition: background .2s,color .2s; }.aksrt-widget-tag-cloud a:hover { background: var(--focus-color,#ff5473); color: #fff; }.aksrt-widget-tag-cloud small { margin-left: 5px; opacity: .65; }
.aksrt-widget-comments { display: grid; gap: 15px; margin: 0; padding: 0; list-style: none; }.aksrt-widget-comments li { display: flex; gap: 11px; }.aksrt-widget-comments__avatar img { width: 42px; height: 42px; border-radius: 50%; }.aksrt-widget-comments p { margin: 3px 0; color: var(--muted-color,#8a8c98); font-size: 13px; line-height: 1.55; }.aksrt-widget-comments__source { font-size: 12px; opacity: .65; }
.aksrt-widget-links { display: grid; grid-template-columns: repeat(4,minmax(0,1fr)); gap: 10px; }.aksrt-widget-links a { display: flex; flex-direction: column; gap: 4px; padding: 14px; border-radius: 9px; background: var(--main-bg,#fff); box-shadow: 0 6px 20px rgba(31,35,48,.06); }.aksrt-widget-links small { color: var(--muted-color,#8a8c98); }.aksrt-widget-links--simple { display: flex; flex-wrap: wrap; }.aksrt-widget-links--simple a { padding: 5px 9px; box-shadow: none; background: transparent; }
.aksrt-widget-notice { display: flex; height: 48px; align-items: center; gap: 12px; padding: 0 16px; overflow: hidden; border-radius: 9px; background: var(--main-bg,#fff); box-shadow: 0 7px 22px rgba(31,35,48,.06); }.aksrt-widget-notice .swiper { height: 48px; flex: 1; }.aksrt-widget-notice .swiper-slide, .aksrt-widget-notice .swiper-slide a { display: flex; height: 48px; align-items: center; gap: 10px; }.aksrt-widget-notice .swiper-slide span { overflow: hidden; color: var(--muted-color,#8a8c98); text-overflow: ellipsis; white-space: nowrap; }
.aksrt-term-card { display: block; overflow: hidden; border-radius: var(--aksrt-widget-radius); background: var(--main-bg,#fff); box-shadow: 0 8px 28px rgba(31,35,48,.07); }.aksrt-term-card__media { display: block; aspect-ratio: 16/9; background: linear-gradient(135deg,#667eea,#764ba2); }.aksrt-term-card__media img { width: 100%; height: 100%; object-fit: cover; }.aksrt-term-card__body { display: flex; flex-direction: column; gap: 5px; padding: 14px; }.aksrt-term-card__body small { min-height: 38px; color: var(--muted-color,#8a8c98); }.aksrt-term-card__body em { font-size: 12px; color: var(--focus-color,#ff5473); font-style: normal; }
.aksrt-term-aggregation { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); gap: 16px; }.aksrt-term-aggregation__card { padding: 16px; border-radius: var(--aksrt-widget-radius); background: var(--main-bg,#fff); box-shadow: 0 8px 28px rgba(31,35,48,.07); }.aksrt-term-aggregation header a { display: flex; justify-content: space-between; }.aksrt-term-aggregation header span { color: var(--muted-color,#8a8c98); font-size: 13px; }.aksrt-term-aggregation ul { display: grid; gap: 10px; margin: 14px 0 0; padding: 0; list-style: none; }.aksrt-term-aggregation li a { display: flex; align-items: center; gap: 10px; }.aksrt-term-aggregation li img { width: 55px; height: 42px; border-radius: 6px; object-fit: cover; }
.aksrt-widget-items { position: relative; min-height: 40px; }.aksrt-widget-items.is-loading { opacity: .72; pointer-events: none; }.aksrt-widget-skeleton { height: 180px; border-radius: 10px; background: linear-gradient(90deg,rgba(127,127,127,.08),rgba(127,127,127,.17),rgba(127,127,127,.08)); background-size: 200% 100%; animation: aksrt-shimmer 1.2s infinite; }.aksrt-widget-load-more { display: block; min-width: 120px; margin: 18px auto 0; padding: 9px 18px; border: 0; border-radius: 999px; background: rgba(127,127,127,.12); color: inherit; cursor: pointer; }.aksrt-widget-pagination { display:flex;justify-content:center;gap:6px;margin-top:18px; }.aksrt-widget-pagination button { min-width:34px;height:34px;border:0;border-radius:8px;background:rgba(127,127,127,.1);color:inherit;cursor:pointer; }.aksrt-widget-pagination button[aria-current="page"] { background:var(--focus-color,#ff5473);color:#fff; }@keyframes aksrt-shimmer { to { background-position: -200% 0; } }
.aksrt-widget-oneline .swiper-slide { width: min(300px,78vw); }.aksrt-widget-tabs__nav { display: flex; gap: 8px; margin-bottom: 15px; overflow-x: auto; }.aksrt-widget-tabs__nav button { flex: none; padding: 7px 14px; border: 0; border-radius: 999px; background: rgba(127,127,127,.1); color: inherit; cursor: pointer; }.aksrt-widget-tabs__nav button[aria-selected="true"] { background: var(--focus-color,#ff5473); color: #fff; }
.aksrt-post-pay { padding: 20px; border-radius: var(--aksrt-widget-radius); text-align: center; }.aksrt-post-pay.is-authorized { background: rgba(34,197,94,.1); }.aksrt-post-pay > i { display: block; margin-bottom: 9px; color: #22c55e; font-size: 30px; }.aksrt-post-pay p { color: var(--muted-color,#8a8c98); }
.aksrt-pricing-card { position: relative; display: flex; flex-direction: column; padding: 25px; border: 1px solid rgba(127,127,127,.13); border-radius: 16px; background: var(--main-bg,#fff); box-shadow: 0 10px 35px rgba(31,35,48,.06); }.aksrt-pricing-card.is-featured { border-color: var(--focus-color,#ff5473); transform: translateY(-8px); }.aksrt-pricing-card__badge { position: absolute; top: 12px; right: 12px; padding: 4px 9px; border-radius: 999px; background: var(--focus-color,#ff5473); color: #fff; font-size: 12px; }.aksrt-pricing-card h3 { margin: 0 0 12px; }.aksrt-pricing-card__price { font-size: 34px; font-weight: 800; }.aksrt-pricing-card p { color: var(--muted-color,#8a8c98); }.aksrt-pricing-card ul { flex: 1; display: grid; gap: 9px; margin: 15px 0 22px; padding: 0; list-style: none; }.aksrt-pricing-card li i { margin-right: 8px; color: #22c55e; }
.aksrt-reviews .swiper-slide { width: min(390px,86vw); height: auto; }.aksrt-review-card { height: 100%; padding: 22px; border-radius: 14px; background: var(--main-bg,#fff); box-shadow: 0 8px 28px rgba(31,35,48,.07); }.aksrt-review-card__rating { color: #f6b73c; }.aksrt-review-card blockquote { min-height: 80px; margin: 15px 0; line-height: 1.75; }.aksrt-review-card footer { display: flex; align-items: center; gap: 11px; }.aksrt-review-card__avatar { width: 44px; height: 44px; border-radius: 50%; object-fit: cover; }.aksrt-review-card footer span { display: flex; flex-direction: column; }.aksrt-review-card footer small { color: var(--muted-color,#8a8c98); }
.aksrt-faq { max-width: 880px; margin: auto; }.aksrt-faq__search { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; padding: 10px 14px; border: 1px solid rgba(127,127,127,.16); border-radius: 10px; }.aksrt-faq__search input { width: 100%; border: 0; outline: 0; background: transparent; color: inherit; }.aksrt-faq__items { display: grid; gap: 10px; }.aksrt-faq__item { overflow: hidden; border: 1px solid rgba(127,127,127,.13); border-radius: 10px; background: var(--main-bg,#fff); }.aksrt-faq__item > button { display: flex; width: 100%; justify-content: space-between; padding: 15px 17px; border: 0; background: transparent; color: inherit; text-align: left; cursor: pointer; }.aksrt-faq__item > div { padding: 0 17px 17px; color: var(--muted-color,#8a8c98); line-height: 1.75; }
.aksrt-stat { padding: 22px; text-align: center; }.aksrt-stat > strong { display: block; color: var(--focus-color,#ff5473); font-size: clamp(32px,5vw,52px); }.aksrt-stat h3 { margin: 5px 0; }.aksrt-stat p { margin: 0; color: var(--muted-color,#8a8c98); }.aksrt-highlight--large { grid-column: span 2; }.aksrt-tilt-case { transform-style: preserve-3d; }.aksrt-tilt-case .aksrt-media-card__body { transform: translateZ(20px); }
.aksrt-feature-intro__tabs { display: flex; justify-content: center; gap: 8px; margin-bottom: 18px; }.aksrt-feature-intro__tabs button { padding: 7px 14px; border: 0; border-radius: 999px; background: rgba(127,127,127,.1); color: inherit; cursor: pointer; }.aksrt-feature-intro__tabs button[aria-selected="true"] { background: var(--focus-color,#ff5473); color: #fff; }.aksrt-feature-intro__panels article { display: grid; grid-template-columns: 1.15fr 1fr; align-items: center; gap: 34px; }.aksrt-feature-intro__copy p, .aksrt-feature-intro__copy li { color: var(--muted-color,#8a8c98); line-height: 1.7; }
.aksrt-slider { height: var(--aksrt-slider-height); overflow: hidden; border-radius: var(--aksrt-widget-radius); background: #111; }.aksrt-slider .swiper-slide, .aksrt-slider .swiper-slide > a { position: relative; display: block; width: 100%; height: 100%; overflow: hidden; }.aksrt-slider .swiper-slide > img, .aksrt-slider .swiper-slide > video, .aksrt-slider .swiper-slide > a > img, .aksrt-slider .swiper-slide > a > video { width: 100%; height: 100%; object-fit: cover; }.aksrt-slide-copy { position: absolute; z-index: 2; right: 8%; bottom: 12%; left: 8%; color: #fff; text-shadow: 0 2px 12px rgba(0,0,0,.4); }.aksrt-slide-copy.is-center { top: 50%; bottom: auto; text-align: center; transform: translateY(-50%); }.aksrt-slide-copy.is-right-bottom { text-align: right; }.aksrt-slide-copy h3 { margin: 0; font-size: clamp(25px,4vw,44px); }.aksrt-slide-copy p { margin: 8px 0 0; }.aksrt-slide-layer { position: absolute; z-index: 1; inset: 0; width: 100%; height: 100%; object-fit: contain; pointer-events: none; }.aksrt-slider-combo { display: grid; grid-template-columns: minmax(0,2fr) minmax(240px,1fr); gap: 15px; }.aksrt-slider-combo__side { display: grid; gap: 15px; }.aksrt-slider-combo__side .aksrt-media-card { min-height: 0; }.aksrt-slider-combo__side .aksrt-media-card__media { aspect-ratio: 2/1; }
.aksrt-user-card { position: relative; overflow: hidden; border-radius: 14px; background: var(--main-bg,#fff); box-shadow: 0 9px 30px rgba(31,35,48,.07); text-align: center; }.aksrt-user-card__cover { height: 105px; background: linear-gradient(135deg,#667eea,#764ba2); background-position: center; background-size: cover; }.aksrt-user-card__body { position: relative; padding: 18px; }.aksrt-user-card__avatar { display: inline-block; margin-top: -62px; padding: 4px; border-radius: 50%; background: var(--main-bg,#fff); }.aksrt-user-card__avatar img { display: block; width: 84px; height: 84px; border-radius: 50%; object-fit: cover; }.aksrt-user-card.is-guest .aksrt-user-card__avatar { margin-top: -58px; }.aksrt-user-card h3 { margin: 7px 0; }.aksrt-user-card__identity { margin: 6px 0; }.aksrt-user-card__body > p { color: var(--muted-color,#8a8c98); }.aksrt-user-card__stats { display: flex; justify-content: center; gap: 24px; margin: 16px 0; }.aksrt-user-card__stats span { display: flex; flex-direction: column; font-size: 12px; color: var(--muted-color,#8a8c98); }.aksrt-user-card__stats b { color: inherit; font-size: 17px; }.aksrt-user-card__actions { display: flex; justify-content: center; gap: 9px; }.aksrt-user-card__follow { position: absolute; top: 14px; right: 14px; padding: 5px 12px; border: 0; border-radius: 999px; background: var(--focus-color,#ff5473); color: #fff; cursor: pointer; }.aksrt-user-card__follow.is-following { background: rgba(0,0,0,.5); }.aksrt-user-card__posts { padding: 0 16px 16px; text-align: left; }
.aksrt-user-ranking { display: grid; gap: 11px; margin: 0; padding: 0; list-style: none; }.aksrt-user-ranking li { display: flex; align-items: center; gap: 9px; }.aksrt-user-ranking__index { width: 24px; text-align: center; color: var(--muted-color,#8a8c98); font-weight: 700; }.aksrt-user-ranking__index.is-top { color: #f59e0b; }.aksrt-user-tile { display: flex; min-width: 0; flex: 1; align-items: center; gap: 10px; }.aksrt-user-tile img { width: 44px; height: 44px; border-radius: 50%; object-fit: cover; }.aksrt-user-tile span { display: flex; min-width: 0; flex-direction: column; }.aksrt-user-tile strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }.aksrt-user-tile small { color: var(--muted-color,#8a8c98); }.aksrt-user-list { --aksrt-cols: 4; }.aksrt-user-list article { padding: 14px; border-radius: 10px; background: var(--main-bg,#fff); box-shadow: 0 6px 20px rgba(31,35,48,.06); }
.aksrt-user-card.no-cover .aksrt-user-card__avatar { margin-top: 0; }.aksrt-user-card__oauth { margin-top: 14px; }
@media (max-width: 767px) {
.aksrt-widget { margin: var(--aksrt-widget-space-m-top,0) var(--aksrt-widget-space-m-right,0) var(--aksrt-widget-space-m-bottom,15px) var(--aksrt-widget-space-m-left,0); }
.aksrt-widget--only-pc { display: none; }.aksrt-widget--only-mobile { display: block; }
.aksrt-widget-grid { grid-template-columns: repeat(var(--aksrt-cols-m,1),minmax(0,1fr)); gap: 10px; }
.aksrt-widget__header { align-items: flex-start; flex-direction: column; }.aksrt-widget__title-links { justify-content: flex-start; }
.aksrt-widget-links { grid-template-columns: repeat(2,minmax(0,1fr)); }
.aksrt-widget-partners__track { grid-template-rows: repeat(var(--aksrt-partner-rows-m),70px); }
.aksrt-term-aggregation, .aksrt-feature-intro__panels article, .aksrt-slider-combo { grid-template-columns: 1fr; }
.aksrt-highlight--large { grid-column: auto; }
.aksrt-slider { height: var(--aksrt-slider-height-m); }.aksrt-slide--hide-mobile { display: none !important; }
.aksrt-widget-gap { height: var(--aksrt-gap-m); }.aksrt-pricing-card.is-featured { transform: none; }
.aksrt-user-list { --aksrt-cols-m: 1; }
}
@media (prefers-reduced-motion: reduce) {
.aksrt-widget *, .aksrt-widget *::before, .aksrt-widget *::after { scroll-behavior: auto !important; animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
}
.aksrt-widget--animate { animation: aksrt-widget-fade .55s both; }.aksrt-widget--animate-slideup { animation-name: aksrt-widget-slideup; }.aksrt-widget--animate-slidedown { animation-name: aksrt-widget-slidedown; }.aksrt-widget--animate-slideright { animation-name: aksrt-widget-slideright; }.aksrt-widget--animate-slideleft { animation-name: aksrt-widget-slideleft; }.aksrt-widget--animate-zoomin { animation-name: aksrt-widget-zoomin; }.aksrt-widget--animate-zoomout { animation-name: aksrt-widget-zoomout; }.aksrt-widget--animate-repeat { animation-iteration-count: infinite; animation-duration: 2s; }
@keyframes aksrt-widget-fade { from { opacity: 0; } }@keyframes aksrt-widget-slideup { from { opacity:0;transform:translateY(25px); } }@keyframes aksrt-widget-slidedown { from { opacity:0;transform:translateY(-25px); } }@keyframes aksrt-widget-slideright { from { opacity:0;transform:translateX(-25px); } }@keyframes aksrt-widget-slideleft { from { opacity:0;transform:translateX(25px); } }@keyframes aksrt-widget-zoomin { from { opacity:0;transform:scale(.9); } }@keyframes aksrt-widget-zoomout { from { opacity:0;transform:scale(1.1); } }
+290
View File
@@ -0,0 +1,290 @@
(function () {
'use strict';
var config = window.aksrtWidgets || {};
var reducedMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
function once(el, key) {
var name = 'aksrt' + key;
if (el.dataset[name]) return false;
el.dataset[name] = '1';
return true;
}
function initSwiper(el) {
if (!once(el, 'Swiper') || typeof window.Swiper !== 'function') return;
var kind = el.dataset.aksrtSwiper || 'cards';
var vertical = kind === 'notice' || el.dataset.direction === 'vertical';
var options = {
direction: vertical ? 'vertical' : 'horizontal',
loop: el.dataset.loop === '1' || kind === 'notice',
speed: Number(el.dataset.speed || 500),
spaceBetween: Number(el.dataset.space || 16),
observer: true,
observeParents: true,
watchOverflow: true,
navigation: {
nextEl: el.querySelector('.swiper-button-next'),
prevEl: el.querySelector('.swiper-button-prev')
},
pagination: { el: el.querySelector('.swiper-pagination'), clickable: true }
};
if (kind === 'scroll' || kind === 'cards') {
options.slidesPerView = 'auto';
options.freeMode = kind === 'scroll';
}
if (kind === 'slider') {
options.effect = el.dataset.effect || 'slide';
options.parallax = !!el.querySelector('[data-swiper-parallax]');
}
if (!reducedMotion && (el.dataset.autoplay === '1' || kind === 'notice')) {
options.autoplay = { delay: Number(el.dataset.interval || 4000), disableOnInteraction: false, pauseOnMouseEnter: true };
}
try {
el.aksrtSwiper = new window.Swiper(el, options);
} catch (error) {
el.classList.add('is-fallback');
}
}
function videoType(url) {
if (/\.m3u8(?:\?|$)/i.test(url)) return 'hls';
if (/\.flv(?:\?|$)/i.test(url)) return 'flv';
if (/\.mpd(?:\?|$)/i.test(url)) return 'dash';
return 'auto';
}
function initVideo(el) {
if (!once(el, 'Video')) return;
var fallback = el.querySelector('video');
if (fallback) {
fallback.addEventListener('error', function () {
var message = el.querySelector('.aksrt-widget-media-error');
if (message) message.hidden = false;
});
}
if (typeof window.DPlayer !== 'function') return;
var holder = document.createElement('div');
holder.className = 'aksrt-widget-video__player';
el.insertBefore(holder, fallback || el.firstChild);
try {
el.aksrtPlayer = new window.DPlayer({
container: holder,
autoplay: el.dataset.autoplay === '1' && !reducedMotion,
video: {
url: el.dataset.videoUrl || '',
pic: el.dataset.videoPoster || '',
type: videoType(el.dataset.videoUrl || '')
}
});
if (el.dataset.muted === '1' && el.aksrtPlayer.video) el.aksrtPlayer.video.muted = true;
if (fallback) fallback.hidden = true;
} catch (error) {
holder.remove();
}
}
function initToc(toc) {
if (!once(toc, 'Toc')) return;
var scope = document.querySelector('.article-content, .wp-posts-content, article .entry-content');
var headings = scope ? Array.prototype.slice.call(scope.querySelectorAll('h2,h3,h4')) : [];
var minimum = Number(toc.dataset.minHeadings || 3);
var list = toc.querySelector('.aksrt-widget-toc__list');
if (headings.length < minimum || !list) {
toc.hidden = true;
return;
}
headings.forEach(function (heading, index) {
if (!heading.id) heading.id = 'aksrt-heading-' + (index + 1);
var item = document.createElement('li');
item.className = 'level-' + heading.tagName.toLowerCase();
var link = document.createElement('a');
link.href = '#' + heading.id;
link.textContent = heading.textContent.trim();
link.addEventListener('click', function (event) {
event.preventDefault();
window.scrollTo({ top: heading.getBoundingClientRect().top + window.scrollY - Number(toc.dataset.scrollOffset || 70), behavior: reducedMotion ? 'auto' : 'smooth' });
history.replaceState(null, '', link.href);
});
item.appendChild(link);
list.appendChild(item);
});
var empty = toc.querySelector('.aksrt-widget-toc__empty');
if (empty) empty.remove();
var toggle = toc.querySelector('.aksrt-widget-toc__toggle');
if (toggle) toggle.addEventListener('click', function () {
var expanded = toggle.getAttribute('aria-expanded') === 'true';
toggle.setAttribute('aria-expanded', expanded ? 'false' : 'true');
toc.classList.toggle('is-collapsed', expanded);
});
}
function updateQuote(figure) {
if (figure.dataset.source !== 'api' || !config.quoteUrl) return Promise.resolve();
var button = figure.querySelector('button');
if (button) button.disabled = true;
return fetch(config.quoteUrl, { credentials: 'same-origin', headers: { Accept: 'application/json' } })
.then(function (response) { if (!response.ok) throw new Error('quote'); return response.json(); })
.then(function (data) {
if (data && data.text) figure.querySelector('blockquote').textContent = data.text;
})
.catch(function () {})
.finally(function () { if (button) button.disabled = false; });
}
function initQuote(figure) {
if (!once(figure, 'Quote')) return;
var button = figure.querySelector('button');
if (button) button.addEventListener('click', function () { updateQuote(figure); });
if (!reducedMotion && figure.dataset.source === 'api') {
window.setInterval(function () { if (!document.hidden) updateQuote(figure); }, Math.max(5, Number(figure.dataset.interval || 30)) * 1000);
}
}
function errorMarkup() {
var i18n = config.i18n || {};
return '<div class="aksrt-widget-request-error" role="alert"><span>' + (i18n.error || '加载失败,请重试。') + '</span><button type="button" data-widget-retry>' + (i18n.retry || '重试') + '</button></div>';
}
function itemsUrl(widget, instance, page, segment) {
var base = String(config.restUrl || '').replace(/\/$/, '');
var url = base + '/' + encodeURIComponent(widget) + '/items?instance=' + encodeURIComponent(instance) + '&page=' + encodeURIComponent(page);
if (segment !== undefined && segment !== '') url += '&segment=' + encodeURIComponent(segment);
return url;
}
function loadItems(container, page, append) {
var owner = container.closest('[data-widget]') || container;
var widget = owner.dataset.widget || container.dataset.widget;
var instance = owner.dataset.instance || container.dataset.instance;
var segment = container.dataset.segment || owner.dataset.segment || '';
if (!widget || !instance || !config.restUrl || container.dataset.loading === '1') return;
container.dataset.loading = '1';
container.classList.add('is-loading');
fetch(itemsUrl(widget, instance, page, segment), { credentials: 'same-origin', headers: { Accept: 'application/json' } })
.then(function (response) { if (!response.ok) throw new Error('items'); return response.json(); })
.then(function (data) {
var oldPagination = container.querySelector('.aksrt-widget-pagination, .aksrt-widget-load-more');
if (oldPagination) oldPagination.remove();
var fragment = document.createElement('div');
fragment.innerHTML = String(data.html || '');
if (append) {
var target = container.querySelector('.aksrt-widget-posts, .posts-row, .swiper-wrapper') || container;
var source = fragment.querySelector('.aksrt-widget-posts, .posts-row, .swiper-wrapper');
Array.prototype.slice.call((source || fragment).children).forEach(function (node) { target.appendChild(node); });
} else {
container.innerHTML = fragment.innerHTML;
}
if (data.paginate_html) container.insertAdjacentHTML('beforeend', data.paginate_html);
container.dataset.page = String(data.page || page);
scan(container);
})
.catch(function () { container.innerHTML = errorMarkup(); })
.finally(function () { delete container.dataset.loading; container.classList.remove('is-loading'); });
}
function initItems(container) {
if (!once(container, 'Items')) return;
if (container.classList.contains('is-loading')) loadItems(container, 1, false);
container.addEventListener('click', function (event) {
var retry = event.target.closest('[data-widget-retry]');
var more = event.target.closest('.aksrt-widget-load-more');
var pageButton = event.target.closest('[data-widget-page]');
if (retry) loadItems(container, Number(container.dataset.page || 1), false);
if (more) loadItems(container, Number(more.dataset.nextPage || 2), true);
if (pageButton) loadItems(container, Number(pageButton.dataset.widgetPage || 1), false);
});
if ('IntersectionObserver' in window) {
var observer = new IntersectionObserver(function (entries) {
entries.forEach(function (entry) {
var more = container.querySelector('.aksrt-widget-load-more[data-mode="infinite"]');
if (entry.isIntersecting && more) loadItems(container, Number(more.dataset.nextPage || 2), true);
});
}, { rootMargin: '240px' });
observer.observe(container);
}
}
function initTabs(tabs) {
if (!once(tabs, 'Tabs')) return;
tabs.addEventListener('click', function (event) {
var button = event.target.closest('[data-segment]');
if (!button) return;
tabs.querySelectorAll('[role="tab"]').forEach(function (tab) { tab.setAttribute('aria-selected', tab === button ? 'true' : 'false'); });
var panel = tabs.querySelector('[data-widget-items]');
panel.dataset.segment = button.dataset.segment;
loadItems(panel, 1, false);
});
}
function initFaq(faq) {
if (!once(faq, 'Faq')) return;
faq.addEventListener('click', function (event) {
var button = event.target.closest('.aksrt-faq__item > button');
if (!button) return;
var expanded = button.getAttribute('aria-expanded') === 'true';
button.setAttribute('aria-expanded', expanded ? 'false' : 'true');
var panel = document.getElementById(button.getAttribute('aria-controls'));
if (panel) panel.hidden = expanded;
});
var search = faq.querySelector('input[type="search"]');
if (search) search.addEventListener('input', function () {
var needle = search.value.trim().toLowerCase();
faq.querySelectorAll('.aksrt-faq__item').forEach(function (item) { item.hidden = needle && String(item.dataset.search || '').toLowerCase().indexOf(needle) === -1; });
});
}
function initFeatures(features) {
if (!once(features, 'Features')) return;
features.addEventListener('click', function (event) {
var button = event.target.closest('[data-feature-index]');
if (!button) return;
var index = button.dataset.featureIndex;
features.querySelectorAll('[data-feature-index]').forEach(function (tab) { tab.setAttribute('aria-selected', tab === button ? 'true' : 'false'); });
features.querySelectorAll('[data-feature-panel]').forEach(function (panel) { panel.hidden = panel.dataset.featurePanel !== index; });
});
}
function initCount(el) {
if (!once(el, 'Count') || reducedMotion) return;
var raw = el.dataset.countUp || '';
var match = raw.match(/-?[0-9]+(?:\.[0-9]+)?/);
if (!match) return;
var target = Number(match[0]);
var prefix = raw.slice(0, match.index);
var suffix = raw.slice(match.index + match[0].length);
var start = performance.now();
function frame(now) {
var progress = Math.min(1, (now - start) / 900);
el.textContent = prefix + Math.round(target * (1 - Math.pow(1 - progress, 3))) + suffix;
if (progress < 1) requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
}
function scan(root) {
var scope = root || document;
scope.querySelectorAll('[data-aksrt-swiper]').forEach(initSwiper);
scope.querySelectorAll('.aksrt-widget-video[data-video-url]').forEach(initVideo);
scope.querySelectorAll('.aksrt-widget-toc').forEach(initToc);
scope.querySelectorAll('.aksrt-widget-quote').forEach(initQuote);
scope.querySelectorAll('[data-widget-items]').forEach(initItems);
scope.querySelectorAll('.aksrt-widget-tabs').forEach(initTabs);
scope.querySelectorAll('.aksrt-faq').forEach(initFaq);
scope.querySelectorAll('.aksrt-feature-intro').forEach(initFeatures);
scope.querySelectorAll('[data-count-up]').forEach(initCount);
if (typeof window.VanillaTilt !== 'undefined') scope.querySelectorAll('[data-aksrt-tilt]').forEach(function (el) { if (once(el, 'Tilt')) window.VanillaTilt.init(el); });
}
function ready() {
scan(document);
if ('MutationObserver' in window) {
new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) { mutation.addedNodes.forEach(function (node) { if (node.nodeType === 1) scan(node); }); });
}).observe(document.body, { childList: true, subtree: true });
}
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', ready);
else ready();
})();