fix(skeleton): align the homepage tab and sort loaders with the reference 1:1

首页「更多栏目」tab 与「排序方式」切换的骨架占位与参考主题 zibll 有实质差异,
根因不是几何宽度,而是三处结构/契约错位:

1. 骨架块自身结构与参考主题不同。card 分支用了 `<posts>` 元素 + `.post-graphic`
   包裹层(列表变体,带 margin-right:20px),而参考主题 card 骨架是
   `<div class="posts-item card">` 且 `.item-thumbnail` 是直接子元素。
   → card 骨架右侧多出一条真实卡片没有的 20px 沟槽。

2. 骨架块被错误地打上 `ajax-item`。参考主题的占位块没有该类。它会让
   `find('.ajax-item')` / ajax-list 的 `inject()` 把骨架当成真实条目。

3. 排序切换的骨架被预渲染节点顶替。aksrt_render_pagination() 在 .ajax-pag 内
   渲染了一个写死 2 条、写死 list 形状的 .post_ajax_loader;runtime post_ajax()
   会先在容器内 find('.post_ajax_loader'),找到就复用并丢弃调用方按视口动态
   拼出的骨架 → 切排序永远是 2 条 list 骨架,card 布局下也是、与视口宽度无关。
   参考主题 zib_paging() 根本没有 loader 兄弟节点。

改动:
- inc/helpers/posts-renderer/markup.php:aksrt_render_placeholder() 的
  card/list 分支改为与 zib_get_post_placeholder() 逐字等价的结构;去掉
  ajax-item 类、card 分支的 .post-graphic 包裹层,元素改用 <div>。
- inc/helpers/template-tags/pagination-permissions.php:删除预渲染 loader,
  与参考主题 zib_paging() 一致 —— 只渲染翻页控件。
- assets/js/core/pagination.js:找不到骨架节点时构造与 runtime/main.js 同款
  的文章骨架(卡片 8/6/4 条、列表 4/3 条,按视口与参考主题同阈值),
  不再退化为「转圈 + 文案」这个第二套加载语言;仅评论等非文章面保留该兜底。
- assets/js/core/pagination.js:为排序菜单(.ajax-option)与 tab 触发器
  (.post_ajax_trigger)增加避让 —— 它们归 legacy runtime 管线,
  否则一次点击发两个请求(与 ajax-list.js 的既有避让对称)。
- assets/js/runtime/main.js:post_ajax 的显隐由 fadeIn()/hide() 改为
  .is-loading 类切换。前者写 inline display,优先级高于类规则,一旦残留
  骨架永远打不开,正是骨架契约明令禁止的失败模式。

归档/分类筛选面原本另有一套独立加载语言(spinner 遮罩 + opacity 淡出),
本次一并统一到同一条 .post_ajax_loader + .is-loading 契约:
- inc/helpers/aksrt-archive.php:删除 show_loading 标记位与遮罩 DOM,
  改为在分页之后渲染文章骨架。
- assets/js/core/archive.js:showLoading/hideLoading 只切 .is-loading;
  fetchPosts() 清空内容时保留骨架与分页节点(与参考主题 success 只 hide
  不删的生命周期一致),原先会连带删掉骨架。
- assets/css/frontend/layout.css:删除 .archive__ajax-wrap.is-loading
  的 opacity 淡出与 spinner 遮罩规则。
- category.php / tag.php:删除已失效的 show_loading 实参。

验证:php -l 全部通过;php tools/audit-admin-contracts.php errors=0;
契约测试 post-visual(22) / asset-ledger(16) / message-center(8) /
lazyload(7) / frontend-lifecycle(13) / zibll-modern-widgets(10) /
page-display(18) / a11y 全绿;已重跑 build:public 刷新产物。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-10-04 03:04:02 +08:00
co-authored by Claude Fable 5
parent f61142ee9a
commit 38bbd917a9
14 changed files with 118 additions and 143 deletions
+4 -38
View File
@@ -3896,44 +3896,10 @@ body.site-layout-3 .sidebar,
overflow: hidden; overflow: hidden;
} }
/* AJAX 筛选加载状态 */ /* 归档面 AJAX 筛选的加载态与首页共用同一套骨架契约:
.archive__ajax-wrap { .post_ajax_loader 容器 + .is-loading 开关(见 frontend/modal-runtime.css)。
position: relative; 原先本文件另有一套独立 spinner 遮罩与 opacity 淡出,已删除 ——
transition: opacity 0.2s ease; 全站只有一套加载语言。 */
}
.archive__ajax-wrap.is-loading {
opacity: 0.5;
pointer-events: none;
}
.archive__ajax-loading {
display: none;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
align-items: center;
justify-content: center;
z-index: 5;
background: rgba(255, 255, 255, 0.6);
backdrop-filter: blur(1px);
}
.archive__ajax-loading.is-loading {
display: flex;
}
.archive__ajax-spinner {
display: inline-block;
width: 28px;
height: 28px;
border: 3px solid var(--surface-3, #e8e8e8);
border-top-color: var(--color-primary, #f04494);
border-radius: 50%;
animation: aksrt-spin 0.6s linear infinite;
}
@media (max-width: 767px) { @media (max-width: 767px) {
.term-page-header__body { .term-page-header__body {
+1 -1
View File
File diff suppressed because one or more lines are too long
+4 -38
View File
@@ -483,44 +483,10 @@ body.site-layout-3 .sidebar,
overflow: hidden; overflow: hidden;
} }
/* AJAX 筛选加载状态 */ /* 归档面 AJAX 筛选的加载态与首页共用同一套骨架契约:
.archive__ajax-wrap { .post_ajax_loader 容器 + .is-loading 开关(见 frontend/modal-runtime.css)。
position: relative; 原先本文件另有一套独立 spinner 遮罩与 opacity 淡出,已删除 ——
transition: opacity 0.2s ease; 全站只有一套加载语言。 */
}
.archive__ajax-wrap.is-loading {
opacity: 0.5;
pointer-events: none;
}
.archive__ajax-loading {
display: none;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
align-items: center;
justify-content: center;
z-index: 5;
background: rgba(255, 255, 255, 0.6);
backdrop-filter: blur(1px);
}
.archive__ajax-loading.is-loading {
display: flex;
}
.archive__ajax-spinner {
display: inline-block;
width: 28px;
height: 28px;
border: 3px solid var(--surface-3, #e8e8e8);
border-top-color: var(--color-primary, #f04494);
border-radius: 50%;
animation: aksrt-spin 0.6s linear infinite;
}
@media (max-width: 767px) { @media (max-width: 767px) {
.term-page-header__body { .term-page-header__body {
+12 -6
View File
@@ -15,7 +15,9 @@
var wrap = scope.querySelector("[data-ajax-wrap]"); var wrap = scope.querySelector("[data-ajax-wrap]");
if (!wrap) return; if (!wrap) return;
var loading = wrap.querySelector(".archive__ajax-loading"); // 归档面与首页共用同一套骨架契约:.post_ajax_loader + .is-loading,
// 不再使用独立 spinner 遮罩 / opacity 淡出。
var loading = wrap.querySelector(".post_ajax_loader");
var REST_BASE = "/wp-json/aksrt/v1/archive/posts"; var REST_BASE = "/wp-json/aksrt/v1/archive/posts";
var emptyText = archiveType === "tag" ? "该标签下暂无文章" : "该分类下暂无文章"; var emptyText = archiveType === "tag" ? "该标签下暂无文章" : "该分类下暂无文章";
@@ -73,12 +75,10 @@
function showLoading() { function showLoading() {
if (loading) loading.classList.add("is-loading"); if (loading) loading.classList.add("is-loading");
wrap.classList.add("is-loading");
} }
function hideLoading() { function hideLoading() {
if (loading) loading.classList.remove("is-loading"); if (loading) loading.classList.remove("is-loading");
wrap.classList.remove("is-loading");
} }
function rebuildEmptyState() { function rebuildEmptyState() {
@@ -102,9 +102,15 @@
.then(function (data) { .then(function (data) {
hideLoading(); hideLoading();
if (data.html !== undefined) { if (data.html !== undefined) {
var children = Array.from(wrap.children); // 只清真实内容;骨架(.post_ajax_loader)与分页控件保留复用 ——
children.forEach(function (child) { // 与参考主题 post_ajax success 只 hide 不删的生命周期一致。
if (child !== loading) wrap.removeChild(child); var keep = function (node) {
return node === loading ||
node.classList.contains("post_ajax_loader") ||
node.classList.contains("ajax-pag");
};
Array.from(wrap.children).forEach(function (child) {
if (!keep(child)) wrap.removeChild(child);
}); });
if (data.html) { if (data.html) {
var temp = document.createElement("div"); var temp = document.createElement("div");
+48 -2
View File
@@ -50,7 +50,48 @@
target = container.parentElement.querySelector(".post-grid, .comment-list, .commentlist, .content-stream__list"); target = container.parentElement.querySelector(".post-grid, .comment-list, .commentlist, .content-stream__list");
} }
// 参考主题兜底 loader:DOM 里没有骨架时补一个 .loading 转圈 + 文案, // 文章骨架:与 runtime/main.js 的 .ajax-next 处理器、aksrt_render_placeholder()
// 同源同款(1:1 对齐参考主题 zib_get_post_placeholder)。刻意不写 ajax-item:
// 否则会被 inject() / find('.ajax-item') 当成真实条目删除或定位。
var CARD_ITEM =
'<div class="posts-item card"><div class="item-thumbnail">' +
'<div class="radius8 item-thumbnail placeholder"></div> </div>' +
'<div class="item-body "> <h2 class="item-excerpt placeholder t1 item-heading"></h2>' +
' <p class="mt10 placeholder k2"></p><i class="flex jsb"><i class="placeholder s1"></i>' +
'<i class="placeholder s1 ml10"></i></i></div></div>';
var LIST_ITEM =
'<div class="posts-item list flex"><div class="post-graphic">' +
'<div class="radius8 item-thumbnail placeholder"></div> </div>' +
'<div class="item-body flex xx flex1 jsb"> <p class="placeholder t1"></p>' +
' <h4 class="item-excerpt placeholder k1"></h4><p class="placeholder k2"></p>' +
'<i><i class="placeholder s1"></i><i class="placeholder s1 ml10"></i></i></div></div>';
// 视口阈值与参考主题 .ajax-next 处理器一致:宽 + 无侧栏 → 8,宽 + 有侧栏 → 6,
// 窄屏 → 4;list 模式宽屏 4、窄屏 3。
function skeletonCount(style) {
var wide = window.innerWidth > 766;
if (style === "card") {
if (!wide) return 4;
return window.innerWidth > 992 && !document.querySelector(".sidebar") ? 8 : 6;
}
return wide ? 4 : 3;
}
// 从列表首张真实卡片判断形状;无卡片时退化为 list。
function postSkeleton() {
var first = target && target.querySelector
? target.querySelector(".posts-item.card, .posts-item.list")
: null;
var isCard = !!first && /(^|\s)card(\s|$)/.test(first.className || "");
var tpl = isCard ? CARD_ITEM : LIST_ITEM;
var out = "";
for (var i = 0, n = skeletonCount(isCard ? "card" : "list"); i < n; i++) {
out += tpl;
}
return '<div class="mb20">' + out + '</div>';
}
// 兜底(非文章列表面,例如评论区没有 .posts-item 时):转圈 + 文案,
// 绝不用按钮自身文字来表达加载态。 // 绝不用按钮自身文字来表达加载态。
function fallbackLoader() { function fallbackLoader() {
var text = (window.aksrtData && aksrtData.ajaxLoading) || "加载中..."; var text = (window.aksrtData && aksrtData.ajaxLoading) || "加载中...";
@@ -67,7 +108,7 @@
if (!loader) { if (!loader) {
loader = document.createElement("div"); loader = document.createElement("div");
loader.className = "post_ajax_loader"; loader.className = "post_ajax_loader";
loader.innerHTML = fallbackLoader(); loader.innerHTML = postSkeleton() || fallbackLoader();
} }
// 参考主题 beforeSend:骨架每次翻页都挪到列表末尾(分页控件之前), // 参考主题 beforeSend:骨架每次翻页都挪到列表末尾(分页控件之前),
// 紧贴最后一张卡片、位于「加载更多」按钮上方。 // 紧贴最后一张卡片、位于「加载更多」按钮上方。
@@ -231,6 +272,11 @@
if (loadMoreBtn) { if (loadMoreBtn) {
clickTarget.addEventListener("click", function(e) { clickTarget.addEventListener("click", function(e) {
// 排序菜单(.ajax-option)与 tab pane 触发器(.post_ajax_trigger)归 legacy
// runtime post_ajax() 管线;本引擎避开,否则一次点击发两个请求。
if (e.target.closest && e.target.closest(".ajax-option, .post_ajax_trigger")) {
return;
}
e.preventDefault(); e.preventDefault();
if (loadMoreBtn.dataset.jumpComments === "1") { if (loadMoreBtn.dataset.jumpComments === "1") {
var jumpInput = container.querySelector(".jump-input"); var jumpInput = container.querySelector(".jump-input");
+5 -2
View File
@@ -1781,7 +1781,9 @@ function post_ajax(_this, con, jcon, item, loader, pag, next, trigger, replace,
$con.append($loader); $con.append($loader);
} }
$loader.fadeIn(); // 显隐只走 .is-loading 类(modal-runtime.css);fadeIn()/hide() 会写
// inline display,而内联优先级高于类规则,残留后骨架永远打不开。
$loader.addClass('is-loading');
swiper_tab_AutoHeight($con); swiper_tab_AutoHeight($con);
}, },
success: function (a) { success: function (a) {
@@ -1837,7 +1839,8 @@ function post_ajax(_this, con, jcon, item, loader, pag, next, trigger, replace,
} }
$con.removeAttr('ing').trigger('post_ajax.ed', jQuery(a)); $con.removeAttr('ing').trigger('post_ajax.ed', jQuery(a));
find('.post_ajax_loader', $con).hide(); // 同 beforeSend:只切换 .is-loading,不写 inline display。
find('.post_ajax_loader', $con).removeClass('is-loading');
if (!_this.attr('no-scroll')) { if (!_this.attr('no-scroll')) {
var _scroll_To = replace ? $con : jQuery(c_c[0]); var _scroll_To = replace ? $con : jQuery(c_c[0]);
+1 -1
View File
File diff suppressed because one or more lines are too long
-1
View File
@@ -139,7 +139,6 @@ if (function_exists('aksrt_archive_open_shell')) {
'stream_class' => 'archive__ajax-wrap content-stream--archive content-stream--category', 'stream_class' => 'archive__ajax-wrap content-stream--archive content-stream--category',
'empty_text' => __('该分类下暂无文章', 'aksrt'), 'empty_text' => __('该分类下暂无文章', 'aksrt'),
'ajax_enabled' => $ajax_filter, 'ajax_enabled' => $ajax_filter,
'show_loading' => $ajax_filter,
]); ]);
} }
?> ?>
+11 -6
View File
@@ -178,7 +178,6 @@ if (!function_exists('aksrt_archive_render_stream')) :
'stream_class' => '', 'stream_class' => '',
'ajax_enabled' => false, 'ajax_enabled' => false,
'ajax_attrs' => '', 'ajax_attrs' => '',
'show_loading' => false,
]); ]);
$classes = [ $classes = [
@@ -211,10 +210,6 @@ if (!function_exists('aksrt_archive_render_stream')) :
<?php endif; ?> <?php endif; ?>
<?php echo $args['ajax_attrs']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> <?php echo $args['ajax_attrs']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
> >
<?php if (!empty($args['show_loading'])) : ?>
<div class="archive__ajax-loading" aria-hidden="true"><span class="archive__ajax-spinner"></span></div>
<?php endif; ?>
<?php if ($has_posts) : ?> <?php if ($has_posts) : ?>
<?php <?php
// legacy 契约:分页渲染在 .ajaxpager 内部(zib_paging 位置), // legacy 契约:分页渲染在 .ajaxpager 内部(zib_paging 位置),
@@ -226,9 +221,19 @@ if (!function_exists('aksrt_archive_render_stream')) :
]); ]);
$pagination_html = (string) ob_get_clean(); $pagination_html = (string) ob_get_clean();
// 归档面与首页共用同一套骨架契约:.post_ajax_loader + .is-loading。
// 挂在分页之后(列表末尾),archive.js 靠它在 wrap 内定位加载态。
$loader_html = '<div class="post_ajax_loader" role="status" aria-label="'
. esc_attr__('正在加载', 'aksrt') . '">'
. aksrt_render_placeholder(
(string) $render_config['mode'] === 'card' ? 'card' : 'list',
4
)
. '</div>';
aksrt_render_post_list(array_merge($render_config, [ aksrt_render_post_list(array_merge($render_config, [
'wrapper_class' => 'content-stream__list', 'wrapper_class' => 'content-stream__list',
'append_inner_html' => $pagination_html, 'append_inner_html' => $pagination_html . $loader_html,
]), $query); ]), $query);
?> ?>
<?php else : ?> <?php else : ?>
+13 -6
View File
@@ -208,11 +208,18 @@ if (!function_exists('aksrt_render_mini_list')) {
if (!function_exists('aksrt_render_placeholder')) { if (!function_exists('aksrt_render_placeholder')) {
/** /**
* 骨架屏占位(legacy zib_get_post_placeholder parity)。 * 骨架屏占位,1:1 对齐参考主题 `zib_get_post_placeholder()`。
* *
* 骨架块复用真实卡片的 posts-item / post-graphic / item-body 结构与尺寸, * 骨架块复用真实卡片的 posts-item / post-graphic / item-body 结构与尺寸,
* 只是把内容换成 .placeholder。列表模式四行(标题 k1、摘要 k2、两枚 s1), * 只是把内容换成 .placeholder。列表模式四行(标题 t1、摘要 k1、k2、两枚 s1),
* 卡片模式三行(标题 t1、摘要 k2、两枚 s1),对应参考主题 1:1。 * 卡片模式三行(标题 t1、摘要 k2、两枚 s1)。
*
* 刻意与真实条目不同的两点(均与参考主题一致):
* - **不写 `ajax-item`**:否则 `find('.ajax-item')` / ajax-list 的 `inject()`
* 会把骨架当成真实条目删除或定位。
* - **元素是 `<div>` 而非 `<posts>`**,且 card 分支的缩略图是
* `.item-thumbnail` 直接子元素(不经 `.post-graphic`,那个带 20px 右边距,
* 是列表变体的 wrapper)。
* *
* @param string $mode list|card|mini|mini_thumb。 * @param string $mode list|card|mini|mini_thumb。
* @param int $count 重复数量,1–12。 * @param int $count 重复数量,1–12。
@@ -222,11 +229,11 @@ if (!function_exists('aksrt_render_placeholder')) {
if ($mode === 'mini') { if ($mode === 'mini') {
$item = '<div class="posts-mini"><div class="placeholder k1"></div></div>'; $item = '<div class="posts-mini"><div class="placeholder k1"></div></div>';
} elseif ($mode === 'mini_thumb') { } elseif ($mode === 'mini_thumb') {
$item = '<div class="posts-mini"><div class="mr10"><div class="item-thumbnail placeholder"></div></div><div class="posts-mini-con flex xx flex1 jsb"><div class="placeholder t1"></div><div class="placeholder s1"></div></div></div>'; $item = '<div class="posts-mini "><div class="mr10"><div class="item-thumbnail placeholder"></div></div><div class="posts-mini-con flex xx flex1 jsb"><div class="placeholder t1"></div><div class="placeholder s1"></div></div></div>';
} elseif ($mode === 'card') { } elseif ($mode === 'card') {
$item = '<posts class="posts-item card ajax-item"><div class="post-graphic"><div class="radius8 item-thumbnail placeholder"></div></div><div class="item-body"><h2 class="item-heading item-excerpt placeholder t1"></h2><p class="mt10 placeholder k2"></p><i class="flex jsb"><i class="placeholder s1"></i><i class="placeholder s1 ml10"></i></i></div></posts>'; $item = '<div class="posts-item card"><div class="item-thumbnail"><div class="radius8 item-thumbnail placeholder"></div> </div><div class="item-body "> <h2 class="item-excerpt placeholder t1 item-heading"></h2> <p class="mt10 placeholder k2"></p><i class="flex jsb"><i class="placeholder s1"></i><i class="placeholder s1 ml10"></i></i></div></div>';
} else { } else {
$item = '<posts class="posts-item list flex ajax-item"><div class="post-graphic"><div class="radius8 item-thumbnail placeholder"></div></div><div class="item-body flex xx flex1 jsb"><p class="placeholder t1"></p><h4 class="item-excerpt placeholder k1"></h4><p class="placeholder k2"></p><i><i class="placeholder s1"></i><i class="placeholder s1 ml10"></i></i></div></posts>'; $item = '<div class="posts-item list flex"><div class="post-graphic"><div class="radius8 item-thumbnail placeholder"></div> </div><div class="item-body flex xx flex1 jsb"> <p class="placeholder t1"></p> <h4 class="item-excerpt placeholder k1"></h4><p class="placeholder k2"></p><i><i class="placeholder s1"></i><i class="placeholder s1 ml10"></i></i></div></div>';
} }
return str_repeat($item, $count); return str_repeat($item, $count);
} }
@@ -124,7 +124,10 @@ if (!function_exists('aksrt_render_pagination')) {
<div class="next-page order-ajax-next ias-btn<?php echo $auto_load ? ' lazyload' : ''; ?>"<?php echo $auto_load ? ' lazyload-action="ias"' : ''; ?>> <div class="next-page order-ajax-next ias-btn<?php echo $auto_load ? ' lazyload' : ''; ?>"<?php echo $auto_load ? ' lazyload-action="ias"' : ''; ?>>
<a href="<?php echo esc_url(add_query_arg($page_var, $current_page + 1)); ?>" data-aksrt-load-more><?php echo wp_kses_post($trigger_text); ?></a> <a href="<?php echo esc_url(add_query_arg($page_var, $current_page + 1)); ?>" data-aksrt-load-more><?php echo wp_kses_post($trigger_text); ?></a>
</div> </div>
<div class="post_ajax_loader" aria-hidden="true"><?php echo function_exists('aksrt_render_placeholder') ? aksrt_render_placeholder('list', 2) : ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></div> <?php // 参考主题 zib_paging() 只渲染翻页控件,不在此处预渲染骨架;否则 runtime
// post_ajax() 会先在容器内找到它并复用,丢弃调用方按视口动态拼出的骨架,
// 排序切换于是永远是写死 2 条 list 形状。
// 骨架由 assets/js/core/pagination.js 在请求时按视口创建。 ?>
</div><?php </div><?php
} }
} }
-1
View File
@@ -120,7 +120,6 @@ if (function_exists('aksrt_archive_open_shell')) {
'stream_class' => 'archive__ajax-wrap content-stream--archive content-stream--tag', 'stream_class' => 'archive__ajax-wrap content-stream--archive content-stream--tag',
'empty_text' => __('该标签下暂无文章', 'aksrt'), 'empty_text' => __('该标签下暂无文章', 'aksrt'),
'ajax_enabled' => $ajax_filter, 'ajax_enabled' => $ajax_filter,
'show_loading' => $ajax_filter,
]); ]);
} }
?> ?>
@@ -332,7 +332,14 @@ test('AJAX pagination can recover, caps auto loading and rehydrates appended med
assert.doesNotMatch(php, /next-page ajax-next/); assert.doesNotMatch(php, /next-page ajax-next/);
assert.match(php, /lazyload-action="ias"/); assert.match(php, /lazyload-action="ias"/);
assert.match(js, /lazybeforeunveil/); assert.match(js, /lazybeforeunveil/);
assert.match(php, /class="post_ajax_loader"/); // 1:1 对齐参考主题 zib_paging():.ajax-pag 内只渲染翻页控件,不预渲染 loader。
// 预渲染的 loader 会被 runtime post_ajax() 复用并丢弃动态骨架,导致排序切换
// 永远是写死 2 条 list 骨架。骨架改由 pagination.js 在请求时按视口创建。
assert.doesNotMatch(php, /post_ajax_loader/);
assert.match(js, /posts-item card/);
assert.match(js, /posts-item list flex/);
// 排序菜单与 tab 触发器归 legacy runtime 管线,本引擎必须避让,否则双请求。
assert.match(js, /closest\("\.ajax-option, \.post_ajax_trigger"\)/);
assert.match(php, /data-page-var/); assert.match(php, /data-page-var/);
assert.match(admin, /'author', 'author_name'/); assert.match(admin, /'author', 'author_name'/);
assert.match(admin, /'category__in'.*'tag__in'/s); assert.match(admin, /'category__in'.*'tag__in'/s);
+7 -39
View File
@@ -1,5 +1,5 @@
{ {
"generated_at": "2026-10-03T16:24:36+00:00", "generated_at": "2026-10-03T18:57:46+00:00",
"errors": [], "errors": [],
"warnings": [ "warnings": [
"customPage tools-update section 'tools/update' not in PHP schema (ok if pure operational page)", "customPage tools-update section 'tools/update' not in PHP schema (ok if pure operational page)",
@@ -57,12 +57,12 @@
"enum incomplete parse for 'user_sign_type' (php subset of js): php=[modal] js=[modal,page]", "enum incomplete parse for 'user_sign_type' (php subset of js): php=[modal] js=[modal,page]",
"enum incomplete parse for 'user_signin_nopas_active' (php subset of js): php=[nopas] js=[nopas,pas,only_nopas]", "enum incomplete parse for 'user_signin_nopas_active' (php subset of js): php=[nopas] js=[nopas,pas,only_nopas]",
"enum incomplete parse for 'wechat_payment_type' (php subset of js): php=[native] js=[native,h5]", "enum incomplete parse for 'wechat_payment_type' (php subset of js): php=[native] js=[native,h5]",
"enum incomplete parse for 'weixingzh_gzh_type' (php subset of js): php=[service] js=[service,subscribe]" "enum incomplete parse for 'weixingzh_gzh_type' (php subset of js): php=[service] js=[service,subscribe]",
"assets/admin/build/ missing — run: cd assets/admin && npm run build"
], ],
"info": [ "info": [
"PHP schema domains: global, page_display, post_list, permissions, users, payment, extensions, tools, ExtensionsAudit, ExtensionsIP, ExtensionsPush, ToolsBackup, ToolsHealth, ToolsImportExport", "PHP schema domains: global, page_display, post_list, permissions, users, payment, extensions, tools, ExtensionsAudit, ExtensionsIP, ExtensionsPush, ToolsBackup, ToolsHealth, ToolsImportExport",
"Menu pages discovered: 60", "Menu pages discovered: 60"
"admin build ok; chunks=31"
], ],
"domains": { "domains": {
"global": { "global": {
@@ -228,41 +228,9 @@
}, },
"page_count": 60, "page_count": 60,
"build": { "build": {
"present": true, "present": false,
"entry": true, "entry": false,
"missing_chunks": [], "missing_chunks": [],
"chunks": [ "chunks": []
"SchemaPage.Bai0uPL7.js",
"vendor-vue.BYzo-2I-.js",
"FaIcon.B3OOcphx.js",
"AksMediaField.DJPSTsh8.js",
"FaIconPicker.ZNRF6_J7.js",
"shared-api.D5VInyXf.js",
"vendor-misc.buu8cFA9.js",
"vendor-draggable.YNevSrwY.js",
"level.E3ANSDAX.js",
"badge.CKTsmH1z.js",
"vendor-naive.D3KCxD1U.js",
"DeferredPage.BR2FUrUF.js",
"NativeOpsRedirect.DMOc4MZt.js",
"FloatingButtonsSettings.CLilEe8k.js",
"PageHeader.jmNZVzHG.js",
"FooterTabbarSettings.BFZnXJRS.js",
"PostPageSettings.B9iQMeXd.js",
"CommentSettings.B3EoTCwT.js",
"PermissionsCapabilities.Dwo7ED9D.js",
"CmsCredits.BeYe9Q4u.js",
"ThemeInfoPage.BEUFF9-H.js",
"ThemeAuthorizationPage.DqXs-wcM.js",
"DocsPage.C9brbZ0-.js",
"UsersVerify.DF6GIMJm.js",
"UsersLevel.r4FMbDJx.js",
"UsersBadge.DQwTkMyA.js",
"UsersWechatTemplate.-k8FkSa8.js",
"ToolsImportExport.BcC8WeEX.js",
"ToolsHealth.pQpCqHX1.js",
"ToolsUpdate.Dl-oC250.js",
"ExtensionAI.B5qc_0CR.js"
]
} }
} }