feat(admin): replicate reference post-page settings page 1:1

- rewrite post_list.page schema (JS+PHP 2.0.0) with the reference field set:
  three cover types with option fieldsets (image 20-200% / slide CFS_Module::slide
  full config with nested dependsOn / video 0-200%), hide-time, p_indent,
  breadcrumbs (home-text as switcher), prevnext, authordesc, maxheight slider,
  yiyan block, copyright, button toptext, front/after content, related posts
- migrate share_s to share page basic group and post_rewards_* to users
  features rewards group (runtime keys unchanged)
- remap get_post_page_settings() to reference keys, normalize slide cover
  option, hardcode non-reference runtime flags (reading progress, favorites,
  author card), drop dual-path legacy aliases
- wire slide option into aksrt_render_slider (effect/direction/spaceBetween/
  speed/interval/loop/autoplay/nav/pagination, scale vs fixed-height modes),
  clamp image scale 20-200 and video scale 0-200 with 16:9 fallback,
  wire p_indent container class + CSS, resync frontend-tags fallback and
  FacadeBulk fallback, remap PostMetaBox cover keys
- add post-page reference contract test; update stale cover-height and
  user-features contract tests

Validation: node --test 464/464 pass, audit-admin-contracts errors=0,
vite build ok, build-public-assets ok, php -l clean.
This commit is contained in:
2026-09-24 16:13:00 +08:00
parent a8060fa71d
commit 66f8bb933d
17 changed files with 797 additions and 267 deletions
+9 -4
View File
@@ -28,6 +28,14 @@ if (!function_exists('aksrt_resolve_single_post_display_settings')) :
'related_orderby' => 'views',
'related_title' => '',
'breadcrumbs_single_text' => true,
'breadcrumbs_home_text' => true,
'p_indent' => false,
'article_image_cover' => true,
'article_image_cover_scale' => 35,
'article_slide_cover' => true,
'article_slide_cover_option'=> [],
'article_video_cover' => true,
'article_video_cover_scale' => 0,
'like_enabled' => true,
'favorite_enabled' => true,
'share_enabled' => true,
@@ -46,7 +54,7 @@ if (!function_exists('aksrt_resolve_single_post_display_settings')) :
'maxheight_enabled' => false,
'maxheight' => 1000,
'copyright_enabled' => true,
'copyright_text' => '',
'copyright_text' => '文章版权归作者所有,未经允许请勿转载。',
'front_content' => '',
'after_content' => '',
'yiyan_header' => false,
@@ -62,9 +70,6 @@ if (!function_exists('aksrt_resolve_single_post_display_settings')) :
}
if (!array_key_exists('breadcrumbs', $settings) && array_key_exists('breadcrumbs_single_s', $settings)) {
$settings['breadcrumbs'] = !empty($settings['breadcrumbs_single_s']);
}
if (!array_key_exists('breadcrumbs_home', $settings) && array_key_exists('breadcrumbs_home_text', $settings)) {
$settings['breadcrumbs_home'] = (string) $settings['breadcrumbs_home_text'];
}
if (!array_key_exists('prevnext', $settings) && array_key_exists('prevnext_s', $settings)) {
$settings['prevnext'] = !empty($settings['prevnext_s']);
+35 -14
View File
@@ -21,8 +21,11 @@ if (!function_exists('aksrt_single_render_cover')) :
$type = (string) $ctx['cover_type'];
$badge = (string) $ctx['status_badge'];
$crumbs = (string) $ctx['breadcrumbs_html'];
$img_scale = max(10, min(100, (int) $ctx['img_scale']));
$video_scale = max(20, min(100, (int) $ctx['video_scale']));
// 参考主题 article_image_cover_option.scale:20-200(%),标题预留 50px。
$img_scale = max(20, min(200, (int) $ctx['img_scale']));
// 参考主题 article_video_cover_option.scale:0-200,0 = 不固定长宽比 → 16:9 回退。
$video_scale = max(0, min(200, (int) $ctx['video_scale']));
$video_padding = $video_scale > 0 ? (string) $video_scale : '56.25';
$slides = is_array($ctx['slide_images'] ?? null) ? $ctx['slide_images'] : [];
$poster = (string) ($ctx['video_poster'] ?? '');
$title_html = (string) ($ctx['title_html'] ?? esc_html(get_the_title()));
@@ -34,7 +37,7 @@ if (!function_exists('aksrt_single_render_cover')) :
?>
<div class="single-head-cover">
<div class="single-video">
<div class="graphic single-cover single-cover--video imgbox-container" style="padding-bottom:<?php echo esc_attr((string) $video_scale); ?>%;">
<div class="graphic single-cover single-cover--video imgbox-container" style="padding-bottom:<?php echo esc_attr($video_padding); ?>%;">
<div class="aksrt-video single-cover__player" data-aksrt-video data-src="<?php echo esc_url($ctx['cover_url']); ?>"<?php echo $poster !== '' ? ' data-poster="' . esc_url($poster) . '"' : ''; ?> style="position:absolute;inset:0;width:100%;height:100%;"></div>
</div>
<div class="single-video-footer dplayer-featured">
@@ -90,20 +93,38 @@ if (!function_exists('aksrt_single_render_cover')) :
. ($crumbs !== '' ? $crumbs : '')
. $badge
. '</div>';
// 与单图封面同一高度公式:calc(比例% + 50px)。
$slider_html = aksrt_render_slider([
// 幻灯片配置(参考主题 CFS_Module::slide 全字段,经 get_post_page_settings 归一化)。
$slide_option = is_array($ctx['settings']['article_slide_cover_option'] ?? null)
? $ctx['settings']['article_slide_cover_option']
: [];
$single_slide = count($slide_items) === 1;
$slider_args = [
'slides' => $slide_items,
'scale_height' => true,
'scale_ratio' => $img_scale / 100,
'scale_extra' => '50px',
'effect' => (string) ($slide_option['effect'] ?? 'slide'),
'direction' => (string) ($slide_option['direction'] ?? 'horizontal'),
'spaceBetween' => (int) ($slide_option['spacebetween'] ?? 15),
'speed' => (int) ($slide_option['speed'] ?? 0),
'loop' => !$single_slide && !empty($slide_option['loop']),
'autoplay' => !$single_slide && !empty($slide_option['autoplay']),
'interval' => max(1, (int) ($slide_option['interval'] ?? 4)) * 1000,
'show_nav' => !empty($slide_option['button']),
'show_pagination' => !empty($slide_option['pagination']),
'wrapper_class' => 'mb20 single-cover-slide imgbox-container',
'slider_class' => 'single-cover single-cover--slide',
'show_nav' => true,
'show_pagination' => true,
'loop' => count($slide_items) > 1,
'autoplay' => count($slide_items) > 1,
'overlay_html' => $overlay,
]);
];
if (!empty($slide_option['scale_height'])) {
// 固定高度模式:PC/移动端分别取 px 高度。
$slider_args['scale_height'] = false;
$slider_args['pc_height'] = ((int) ($slide_option['pc_height'] ?? 380)) . 'px';
$slider_args['m_height'] = ((int) ($slide_option['m_height'] ?? 180)) . 'px';
} else {
// 比例高度模式:scale% + 50px(标题预留,与单图封面同公式)。
$slider_args['scale_height'] = true;
$slider_args['scale_ratio'] = max(10, (int) ($slide_option['scale'] ?? 35)) / 100;
$slider_args['scale_extra'] = '50px';
}
$slider_html = aksrt_render_slider($slider_args);
?>
<div class="single-head-cover">
<?php echo $slider_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
@@ -633,7 +654,7 @@ if (!function_exists('aksrt_single_render_article')) :
<div class="post_front_content theme-box box-body"><?php echo wp_kses_post((string) $ctx['front_content']); ?></div>
<?php endif; ?>
<div class="theme-box wp-posts-content<?php echo $maxheight > 0 ? ' limit-height' : ''; ?>"
<div class="theme-box wp-posts-content<?php echo $maxheight > 0 ? ' limit-height' : ''; ?><?php echo !empty($settings['p_indent']) ? ' p-indent' : ''; ?>"
<?php echo $article_nav_on ? 'data-nav="posts"' : ''; ?>
<?php echo $maxheight > 0 ? ' style="max-height:' . esc_attr((string) $maxheight) . 'px;"' : ''; ?>
data-maxheight="<?php echo esc_attr((string) ($maxheight > 0 ? max(0, $maxheight - 80) : 0)); ?>">