fix(list): wire Zibll list/card display chain end-to-end

Resolve post list mode from global list_type + surface card overrides so
homepage/archives/AJAX honor admin list and card style settings.
This commit is contained in:
2026-07-12 20:56:38 +08:00
parent b2815614d1
commit d73a7af25e
17 changed files with 444 additions and 151 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ global $wp_query;
$render_config = function_exists('aksrt_archive_get_render_config')
? aksrt_archive_get_render_config(['context' => 'archive'])
: ['context' => 'archive', 'mode' => 'card', 'card_style' => 'standard'];
: ['context' => 'archive', 'mode' => 'list'];
$has_sidebar = function_exists('aksrt_archive_has_sidebar')
? aksrt_archive_has_sidebar()
: (function_exists('aksrt_is_show_sidebar') ? aksrt_is_show_sidebar() : false);
@@ -2,7 +2,7 @@
<div class="aksrt-page-container content-page">
<PageHeader
title="首页配置"
desc="按 Zibll 首页主线配置内容模型、Tab、主列表、卡片样式与基础交互。"
desc="按 Zibll 首页主线配置内容类型、Tab、主列表与基础交互。列表/卡片显示请在「文章列表」中设置。"
>
<template #actions>
<n-button type="primary" :loading="saving" @click="handleSave">保存设置</n-button>
@@ -13,7 +13,7 @@
<n-tab-pane name="stream" tab="主列表 & Tab">
<n-spin :show="loading" style="width:100%; min-height:200px;">
<n-card class="aksrt-section-card" style="margin-bottom:16px;">
<template #header><strong>首页模型</strong></template>
<template #header><strong>首页内容</strong></template>
<n-form :model="form" label-placement="left" label-width="160" class="aksrt-form">
<n-form-item label="首页内容模型">
<n-radio-group v-model:value="form.homepage_content_model">
@@ -152,32 +152,10 @@
<n-tab-pane name="cards" tab="卡片 & 交互">
<n-spin :show="loading" style="width:100%; min-height:200px;">
<n-card class="aksrt-section-card" style="margin-bottom:16px;">
<template #header><strong>卡片样式</strong></template>
<n-form :model="form" label-placement="left" label-width="160" class="aksrt-form">
<n-form-item label="卡片风格">
<n-radio-group v-model:value="form.homepage_card_style">
<n-space size="large">
<n-radio-button value="default">默认</n-radio-button>
<n-radio-button value="style2">风格 2</n-radio-button>
<n-radio-button value="style3">风格 3</n-radio-button>
</n-space>
</n-radio-group>
</n-form-item>
<n-form-item label="多图卡片">
<n-switch v-model:value="form.homepage_multi_thumb_enabled" />
</n-form-item>
<n-form-item v-if="form.homepage_multi_thumb_enabled" label="最少图片数">
<n-input-number v-model:value="form.homepage_multi_thumb_min_images" :min="2" :max="4" />
</n-form-item>
<n-form-item label="默认视图">
<n-radio-group v-model:value="form.homepage_default_view">
<n-space size="large">
<n-radio-button value="list">列表</n-radio-button>
<n-radio-button value="card">卡片</n-radio-button>
</n-space>
</n-radio-group>
</n-form-item>
</n-form>
<template #header><strong>列表显示</strong></template>
<n-alert type="info" :show-icon="false">
首页文章列表/卡片模式、样式变体与缩略图比例已统一到「文章&amp;列表 → 文章列表」设置(对齐 Zibll 全局 list_type / list_card_home)。此处不再单独维护 homepage_card_style / 默认视图。
</n-alert>
</n-card>
<n-card class="aksrt-section-card" style="margin-bottom:16px;">
@@ -1010,7 +1010,7 @@ export const pageDisplaySchemas = {
fields: [
{
key: 'homepage_card_style',
label: '卡片风格',
label: '卡片风格(已弃用)',
type: 'radio',
default: 'default',
options: [
@@ -1018,18 +1018,23 @@ export const pageDisplaySchemas = {
{ label: '风格 2', value: 'style2' },
{ label: '风格 3', value: 'style3' },
],
help: '已弃用:请改用「文章列表」中的列表/卡片样式设置。',
},
{ key: 'homepage_multi_thumb_enabled', label: '多图卡片', type: 'switch', default: true },
{ key: 'homepage_multi_thumb_min_images', label: '最少图片数', type: 'number', default: 3, min: 2, max: 4, dependsOn: { key: 'homepage_multi_thumb_enabled', value: true } },
{ key: 'homepage_multi_thumb_enabled', label: '多图卡片(已弃用)', type: 'switch', default: true, help: '请改用文章列表缩略图/多图设置。' },
{ key: 'homepage_multi_thumb_min_images', label: '最少图片数(已弃用)', type: 'number', default: 3, min: 2, max: 4 },
{
key: 'homepage_default_view',
label: '默认视图',
label: '默认视图(已弃用)',
type: 'radio',
default: 'list',
options: [
{ label: '列表', value: 'list' },
{ label: '卡片', value: 'card' },
],
help: 'SSR 以文章列表全局设置为准;此字段仅作兼容保留。',
},
{ label: '卡片', value: 'card' },
],
},
{ key: 'homepage_sidebar_mini_enabled', label: '迷你侧栏列表', type: 'switch', default: true },
{ key: 'homepage_sort_ajax_enabled', label: '排序栏 AJAX', type: 'switch', default: true },
@@ -166,18 +166,19 @@ export const listSchema = {
fields: [
{
key: 'post_card_style',
label: '列表卡片样式',
label: '默认列表模式',
type: 'select',
default: 'thumb',
options: [
{ label: '标准图文', value: 'thumb' },
{ label: '紧凑卡', value: 'compact' },
{ label: '大图卡', value: 'large_thumb' },
{ label: '多图卡', value: 'multi_thumb' },
{ label: '纯文字', value: 'text' },
{ label: '有图则图文', value: 'thumb_if_has' },
{ label: '列表图文模式', value: 'thumb' },
{ label: '列表文字模式', value: 'text' },
{ label: '列表自动图文', value: 'thumb_if_has' },
{ label: '卡片模式', value: 'card' },
{ label: '紧凑列表', value: 'compact' },
{ label: '大图列表', value: 'large_thumb' },
{ label: '多图列表', value: 'multi_thumb' },
],
help: '对齐 Zibll list_type:thumb/text/thumb_if_has 为列表,card 为卡片网格。首页可用下方「首页卡片模式」单独强制卡片。',
},
{ key: 'post_excerpt_length', label: '摘要长度', type: 'number', default: 120, min: 20, max: 500 },
{ key: 'post_list_per_page', label: '每页文章数', type: 'number', default: 12, min: 4, max: 48 },
@@ -223,7 +224,7 @@ export const listSchema = {
],
},
{ key: 'list_card_scale', label: '卡片缩略图比例 (%)', type: 'number', default: 70, min: 20, max: 200 },
{ key: 'list_card_home', label: '首页卡片模式', type: 'switch', default: false },
{ key: 'list_card_home', label: '首页卡片模式', type: 'switch', default: false, help: '当默认模式不为卡片时,单独将首页列表强制为卡片(Zibll list_card_home)', dependsOn: { key: 'post_card_style', operator: '!=', value: 'card' } },
{
key: 'list_card_cat',
label: '分类卡片模式',
+13 -10
View File
@@ -68,17 +68,20 @@ $custom_dimensions = is_array($cat_filter_config['dimensions'] ?? null) ? $cat_f
$sort_state = function_exists('aksrt_archive_get_sort_state') ? aksrt_archive_get_sort_state() : ['current' => 'latest', 'links' => []];
$current_sort = $sort_state['current'];
$sort_links = $sort_state['links'];
$render_config = function_exists('aksrt_archive_get_render_config')
? aksrt_archive_get_render_config([
'context' => 'category',
'mode' => $layout_mode,
'card_style' => $card_style,
])
: [
'context' => 'category',
'mode' => $layout_mode,
'card_style' => $card_style,
$render_overrides = [
'context' => 'category',
];
// Term meta layout_mode is authoritative only when explicitly set (non-empty preset).
$layout_preset = (string) ($archive_settings['layout_preset'] ?? '');
if ($layout_preset !== '' && in_array((string) $layout_mode, ['list', 'card', 'mini', 'grid-cms'], true)) {
$render_overrides['mode'] = (string) $layout_mode;
if (!empty($card_style)) {
$render_overrides['card_style'] = (string) $card_style;
}
}
$render_config = function_exists('aksrt_archive_get_render_config')
? aksrt_archive_get_render_config($render_overrides)
: array_merge(['context' => 'category', 'mode' => 'list'], $render_overrides);
$filter_terms = [];
$filter_all_url = get_category_link($term->term_id);
@@ -301,13 +301,20 @@ class AKSRT_Admin_Global_Controller extends AKSRT_Admin_Controller_Base {
$query = new WP_Query($args);
$mode = in_array($view_mode, ['card', 'list'], true) ? $view_mode : 'list';
$mode = in_array($view_mode, ['card', 'list'], true) ? $view_mode : '';
$html = '';
if (function_exists('aksrt_render_post_list')) {
$html = aksrt_render_post_list($query, [
'mode' => $mode,
'context' => 'home',
], false);
$overrides = ['context' => 'home'];
if ($mode !== '') {
$overrides['mode'] = $mode;
}
$render_config = function_exists('aksrt_resolve_post_list_render_config')
? aksrt_resolve_post_list_render_config([
'context' => 'home',
'overrides' => $overrides,
])
: array_merge(['mode' => ($mode !== '' ? $mode : 'list'), 'context' => 'home'], $overrides);
$html = aksrt_render_post_list($query, $render_config, false);
} elseif ($query->have_posts()) {
$html = '<div class="posts-row aksrt-homepage__posts" data-view="' . esc_attr($mode) . '">';
while ($query->have_posts()) {
@@ -159,16 +159,16 @@ class AKSRT_Admin_Schema_Post_List_List {
'fields' => [
[
'key' => 'post_card_style',
'label' => '列表卡片样式',
'label' => '默认列表模式',
'type' => 'select',
'default' => 'thumb',
'options' => [
['label' => '标准图文', 'value' => 'thumb'],
['label' => '列表图文模式', 'value' => 'thumb'],
['label' => '紧凑卡', 'value' => 'compact'],
['label' => '大图卡', 'value' => 'large_thumb'],
['label' => '多图卡', 'value' => 'multi_thumb'],
['label' => '纯文字', 'value' => 'text'],
['label' => '有图则图文', 'value' => 'thumb_if_has'],
['label' => '列表文字模式', 'value' => 'text'],
['label' => '列表自动图文', 'value' => 'thumb_if_has'],
['label' => '卡片模式', 'value' => 'card'],
],
],
+56 -1
View File
@@ -226,7 +226,10 @@ class AKSRT_Admin {
public static function sanitize_public_render_config(array $config): array {
$clean = [];
if (isset($config['mode'])) {
$clean['mode'] = sanitize_key((string) $config['mode']);
$mode = sanitize_key((string) $config['mode']);
if (in_array($mode, ['list', 'card', 'mini', 'grid-cms'], true)) {
$clean['mode'] = $mode;
}
}
if (isset($config['context'])) {
$clean['context'] = sanitize_key((string) $config['context']);
@@ -234,9 +237,49 @@ class AKSRT_Admin {
if (isset($config['query_context'])) {
$clean['query_context'] = sanitize_key((string) $config['query_context']);
}
if (isset($config['style'])) {
$style = sanitize_key((string) $config['style']);
if (in_array($style, ['', 'style2', 'style3'], true)) {
$clean['style'] = $style;
}
}
if (isset($config['card_style'])) {
$card_style = sanitize_key((string) $config['card_style']);
$allowed = ['thumb', 'text', 'thumb_if_has', 'card', 'compact', 'large_thumb', 'multi_thumb', 'standard'];
if (in_array($card_style, $allowed, true)) {
$clean['card_style'] = $card_style;
}
}
if (isset($config['list_show_type'])) {
$v = sanitize_key((string) $config['list_show_type']);
if (in_array($v, ['separate', 'no_margin'], true)) {
$clean['list_show_type'] = $v;
}
}
if (isset($config['list_img_position'])) {
$v = sanitize_key((string) $config['list_img_position']);
if (in_array($v, ['left', 'right'], true)) {
$clean['list_img_position'] = $v;
}
}
foreach (['thumb_if_has', 'show_thumb', 'show_author', 'show_date', 'show_views', 'show_comments', 'show_likes', 'show_excerpt', 'heading_bold', 'target_blank', 'badge_show', 'multi_thumb_enabled', 'skip_wrapper'] as $bool_key) {
if (array_key_exists($bool_key, $config)) {
$clean[$bool_key] = !empty($config[$bool_key]);
}
}
if (isset($config['multi_thumb_limit'])) {
$clean['multi_thumb_limit'] = max(1, min(6, (int) $config['multi_thumb_limit']));
}
if (isset($config['multi_thumb_min'])) {
$clean['multi_thumb_min'] = max(1, min(6, (int) $config['multi_thumb_min']));
}
if (isset($config['excerpt_words'])) {
$clean['excerpt_words'] = max(0, min(200, (int) $config['excerpt_words']));
}
return $clean;
}
public function ajax_load_more_posts(): void {
check_ajax_referer('aksrt_public_nonce', 'nonce');
$page = max(1, (int) ($_POST['page'] ?? 1));
@@ -244,6 +287,18 @@ class AKSRT_Admin {
$render_config = json_decode(wp_unslash((string) ($_POST['render_config'] ?? '{}')), true);
$query_vars = is_array($query_vars) ? self::sanitize_public_query_vars($query_vars) : [];
$render_config = is_array($render_config) ? self::sanitize_public_render_config($render_config) : [];
// Prefer server-side resolution so AJAX matches SSR styles even if client config is slim.
if (function_exists('aksrt_resolve_post_list_render_config')) {
$context = sanitize_key((string) ($render_config['context'] ?? 'archive'));
if ($context === '') {
$context = 'archive';
}
$resolved = aksrt_resolve_post_list_render_config([
'context' => $context,
'overrides' => $render_config,
]);
$render_config = array_merge($resolved, $render_config);
}
$query_vars['paged'] = $page;
$query = new WP_Query($query_vars);
+18 -13
View File
@@ -84,19 +84,24 @@ class AKSRT_Term_Meta {
$saved = [];
}
$layout_mode = isset($saved['layout_mode']) && $saved['layout_mode'] !== ''
? sanitize_key((string) $saved['layout_mode'])
: (string) ($global['list_mode'] ?? 'grid');
$layout_map = [
'grid' => ['mode' => 'card', 'card_style' => 'standard'],
'card' => ['mode' => 'card', 'card_style' => 'standard'],
'list' => ['mode' => 'list', 'card_style' => 'standard'],
'compact' => ['mode' => 'list', 'card_style' => 'compact'],
'mini' => ['mode' => 'mini', 'card_style' => 'standard'],
'grid-cms' => ['mode' => 'grid-cms', 'card_style' => 'standard'],
];
$resolved_layout = $layout_map[$layout_mode] ?? ['mode' => 'card', 'card_style' => 'standard'];
// Empty term layout_mode means follow global post-list settings (Zibll).
// Do not fall back to page-display list_mode=grid which forced card everywhere.
$layout_preset = isset($saved['layout_mode']) ? sanitize_key((string) $saved['layout_mode']) : '';
if ($layout_preset === '') {
$resolved_layout = ['mode' => '', 'card_style' => ''];
$layout_mode = '';
} else {
$layout_mode = $layout_preset;
$layout_map = [
'grid' => ['mode' => 'card', 'card_style' => 'thumb'],
'card' => ['mode' => 'card', 'card_style' => 'thumb'],
'list' => ['mode' => 'list', 'card_style' => 'thumb'],
'compact' => ['mode' => 'list', 'card_style' => 'compact'],
'mini' => ['mode' => 'mini', 'card_style' => 'thumb'],
'grid-cms' => ['mode' => 'grid-cms', 'card_style' => 'thumb'],
];
$resolved_layout = $layout_map[$layout_mode] ?? ['mode' => 'list', 'card_style' => 'thumb'];
}
$header_style = (string) ($global['header_style'] ?? 'simple');
if (!in_array($header_style, ['cover', 'simple', 'none'], true)) {
@@ -161,7 +161,7 @@ trait AKSRT_Settings_Display_Page_Groups {
return [
'list' => [
'post_card_style' => $list['card_style'],
'post_card_style' => $list['list_type'] ?? $list['card_style'] ?? 'thumb',
'post_list_author' => $list['show_author'],
'post_show_date' => $list['show_date'],
'post_show_views' => $list['show_views'],
@@ -188,10 +188,10 @@ trait AKSRT_Settings_Display_Page_Groups {
'list_list_style' => $list['list_style'],
'list_list_img_position' => $list['list_img_position'],
'list_list_scale' => $list['list_scale'],
'list_card_style' => $list['card_style'],
'list_card_style' => $list['card_variant'] ?? '',
'list_card_scale' => $list['card_scale'],
'list_card_home' => $list['card_home'],
'list_card_cat' => $list['card_cat'],
'list_card_cat' => $list['card_cat_ids'] ?? [],
'list_card_tag' => $list['card_tag'],
'list_card_topics' => $list['card_topics'],
'list_card_author' => $list['card_author'],
@@ -11,19 +11,26 @@ class AKSRT_Settings_Post_Display {
public static function get_post_list_style_settings(): array {
$settings = AKSRT_Settings::get_all();
$card_style = sanitize_key((string) ($settings['post_card_style'] ?? 'thumb'));
$allowed_styles = ['thumb', 'compact', 'large_thumb', 'multi_thumb', 'text', 'thumb_if_has', 'card', 'standard'];
if (!in_array($card_style, $allowed_styles, true)) {
$card_style = 'thumb';
// post_card_style storage key mirrors Zibll list_type.
$list_type = sanitize_key((string) ($settings['post_card_style'] ?? 'thumb'));
$allowed_list_types = ['thumb', 'compact', 'large_thumb', 'multi_thumb', 'text', 'thumb_if_has', 'card', 'standard'];
if (!in_array($list_type, $allowed_list_types, true)) {
$list_type = 'thumb';
}
// historical alias
if ($card_style === 'standard') {
$card_style = 'thumb';
// Historical aliases → Zibll list_type tokens.
if ($list_type === 'standard') {
$list_type = 'thumb';
}
// Non-Zibll extras stay list-mode variants (never force card grid).
if (in_array($list_type, ['compact', 'large_thumb', 'multi_thumb'], true)) {
// Keep token for CSS hooks; render as list.
}
// Zibll: only list_type=card is card mode; thumb/text/thumb_if_has are list.
$render_mode_map = [
'thumb' => 'card',
'thumb' => 'list',
'compact' => 'list',
'large_thumb' => 'list',
'multi_thumb' => 'list',
@@ -74,9 +81,34 @@ class AKSRT_Settings_Post_Display {
$ajax_nomore = sanitize_text_field((string) $settings['ajax_nomore_text']);
}
$list_style = sanitize_key((string) ($settings['list_list_style'] ?? ''));
if (!in_array($list_style, ['', 'style2'], true)) {
$list_style = '';
}
$card_variant = sanitize_key((string) ($settings['list_card_style'] ?? ''));
if (!in_array($card_variant, ['', 'style3'], true)) {
$card_variant = '';
}
$card_cat_ids = [];
if (is_array($settings['list_card_cat'] ?? null)) {
$card_cat_ids = array_values(array_filter(array_map('intval', $settings['list_card_cat'])));
}
return [
'card_style' => in_array(sanitize_key((string) ($settings['list_card_style'] ?? '')), ['', 'style3'], true) ? sanitize_key((string) ($settings['list_card_style'] ?? '')) : '',
'render_mode' => $render_mode_map[$card_style] ?? 'card',
// Zibll list_type (storage: post_card_style).
'list_type' => $list_type,
// Base mode from list_type only (surface card overrides applied by resolver).
'render_mode' => $render_mode_map[$list_type] ?? 'list',
// List item subtype token for text/thumb_if_has class hooks (not card variant).
'list_type_token' => $list_type,
// List mode visual variant (Zibll list_list_option.style).
'list_style' => $list_style,
// Card mode visual variant (Zibll list_card_option.style).
'card_variant' => $card_variant,
// Back-compat aliases used by older callers (prefer list_type / card_variant).
'card_style' => $list_type,
'show_author' => $show_author,
'show_date' => $show_date,
'show_views' => !isset($settings['post_show_views']) || !empty($settings['post_show_views']),
@@ -100,13 +132,12 @@ class AKSRT_Settings_Post_Display {
'list_orderby' => in_array(sanitize_key((string) ($settings['list_orderby'] ?? 'modified')), ['modified', 'date', 'default'], true) ? sanitize_key((string) ($settings['list_orderby'] ?? 'modified')) : 'modified',
'columns' => max(1, min(3, (int) ($settings['post_list_columns'] ?? 1))),
'per_page' => max(4, min(48, (int) ($settings['post_list_per_page'] ?? 12))),
'list_style' => in_array(sanitize_key((string) ($settings['list_list_style'] ?? '')), ['', 'style2'], true) ? sanitize_key((string) ($settings['list_list_style'] ?? '')) : '',
'list_img_position' => in_array(sanitize_key((string) ($settings['list_list_img_position'] ?? 'left')), ['left', 'right'], true) ? sanitize_key((string) ($settings['list_list_img_position'] ?? 'left')) : 'left',
'list_scale' => max(50, min(200, (int) ($settings['list_list_scale'] ?? 70))),
'card_scale' => max(20, min(200, (int) ($settings['list_card_scale'] ?? 70))),
'card_home' => !empty($settings['list_card_home']),
'card_cat' => !empty($settings['list_card_cat']),
'card_cat_ids' => is_array($settings['list_card_cat'] ?? null) ? array_map('intval', $settings['list_card_cat']) : [],
'card_cat' => !empty($card_cat_ids),
'card_cat_ids' => $card_cat_ids,
'card_tag' => !empty($settings['list_card_tag']),
'card_topics' => !empty($settings['list_card_topics']),
'card_author' => !empty($settings['list_card_author']),
+205 -27
View File
@@ -13,7 +13,7 @@ if (!function_exists('aksrt_archive_get_list_style_settings')) :
/**
* Shared list style defaults for archive surfaces.
*
* @return array{render_mode:string,card_style:string,card_cat_ids:array<int,int>}
* @return array<string,mixed>
*/
function aksrt_archive_get_list_style_settings(): array {
$settings = class_exists('AKSRT_Settings')
@@ -21,13 +21,203 @@ if (!function_exists('aksrt_archive_get_list_style_settings')) :
: [];
return [
'render_mode' => (string) ($settings['render_mode'] ?? 'card'),
'card_style' => (string) ($settings['card_style'] ?? 'standard'),
'card_cat_ids' => is_array($settings['card_cat_ids'] ?? null) ? array_map('intval', $settings['card_cat_ids']) : [],
'list_type' => (string) ($settings['list_type'] ?? 'thumb'),
'render_mode' => (string) ($settings['render_mode'] ?? 'list'),
'list_type_token' => (string) ($settings['list_type_token'] ?? ($settings['list_type'] ?? 'thumb')),
'list_style' => (string) ($settings['list_style'] ?? ''),
'card_variant' => (string) ($settings['card_variant'] ?? ''),
// Back-compat: older callers expected card_style as list_type token.
'card_style' => (string) ($settings['list_type'] ?? ($settings['card_style'] ?? 'thumb')),
'card_cat_ids' => is_array($settings['card_cat_ids'] ?? null) ? array_map('intval', $settings['card_cat_ids']) : [],
'card_home' => !empty($settings['card_home']),
'card_tag' => !empty($settings['card_tag']),
'card_topics' => !empty($settings['card_topics']),
'card_author' => !empty($settings['card_author']),
'list_show_type' => (string) ($settings['list_show_type'] ?? 'separate'),
'list_img_position'=> (string) ($settings['list_img_position'] ?? 'left'),
'show_author' => !isset($settings['show_author']) || !empty($settings['show_author']),
'show_date' => !isset($settings['show_date']) || !empty($settings['show_date']),
'show_views' => !isset($settings['show_views']) || !empty($settings['show_views']),
'show_comments' => !empty($settings['show_comments']),
'show_likes' => !empty($settings['show_likes']),
'target_blank' => !empty($settings['target_blank']),
'heading_bold' => !empty($settings['heading_bold']),
'badge_show' => !isset($settings['badge_show']) || !empty($settings['badge_show']),
'excerpt_length' => (int) ($settings['excerpt_length'] ?? 120),
];
}
endif;
if (!function_exists('aksrt_resolve_post_list_render_config')) :
/**
* Zibll-aligned list/card resolver for all surfaces.
*
* Decision order mirrors zib_mian_posts_while():
* 1) explicit override mode/type
* 2) global list_type (post_card_style): only "card" is card grid; thumb/text/thumb_if_has are list
* 3) surface card switches (home/tag/topics/author/cat IDs)
*
* @param array<string,mixed> $args {
* @type string $context home|category|tag|topics|author|search|archive
* @type int $term_id Optional term id for list_card_cat
* @type array<string,mixed> $overrides Optional renderer overrides (mode, style, …)
* }
* @return array<string,mixed>
*/
function aksrt_resolve_post_list_render_config(array $args = []): array {
$args = wp_parse_args($args, [
'context' => '',
'term_id' => 0,
'overrides' => [],
]);
$overrides = is_array($args['overrides']) ? $args['overrides'] : [];
if (!empty($args['context']) && empty($overrides['context'])) {
// keep context on root for merge below
}
$context = sanitize_key((string) ($args['context'] !== '' ? $args['context'] : ($overrides['context'] ?? '')));
if ($context === '') {
if (function_exists('is_front_page') && (is_front_page() || is_home())) {
$context = 'home';
} elseif (is_category()) {
$context = 'category';
} elseif (is_tag()) {
$context = 'tag';
} elseif (is_tax('topics')) {
$context = 'topics';
} elseif (is_author()) {
$context = 'author';
} elseif (is_search()) {
$context = 'search';
} else {
$context = 'archive';
}
}
$term_id = (int) ($args['term_id'] ?? 0);
if ($term_id <= 0) {
$term_id = (int) get_queried_object_id();
}
$list = aksrt_archive_get_list_style_settings();
$list_type = sanitize_key((string) ($list['list_type'] ?? 'thumb'));
if ($list_type === '' || $list_type === 'standard') {
$list_type = 'thumb';
}
// Explicit caller mode wins (term meta, AJAX view toggle, etc.).
$forced_mode = '';
if (isset($overrides['mode']) && is_string($overrides['mode']) && $overrides['mode'] !== '') {
$forced_mode = sanitize_key($overrides['mode']);
} elseif (isset($overrides['type']) && sanitize_key((string) $overrides['type']) === 'card') {
$forced_mode = 'card';
} elseif (!empty($overrides['is_card'])) {
$forced_mode = 'card';
}
$mode = $forced_mode !== ''
? $forced_mode
: (($list_type === 'card') ? 'card' : 'list');
// Surface card overrides (only when not already card from list_type / force).
if ($mode !== 'card' && $forced_mode === '') {
if ($context === 'home' && !empty($list['card_home'])) {
$mode = 'card';
} elseif ($context === 'tag' && !empty($list['card_tag'])) {
$mode = 'card';
} elseif ($context === 'topics' && !empty($list['card_topics'])) {
$mode = 'card';
} elseif ($context === 'author' && !empty($list['card_author'])) {
$mode = 'card';
} elseif ($term_id > 0 && !empty($list['card_cat_ids']) && in_array($term_id, array_map('intval', (array) $list['card_cat_ids']), true)) {
$mode = 'card';
}
}
if (!in_array($mode, ['list', 'card', 'mini', 'grid-cms'], true)) {
$mode = 'list';
}
// Visual variant: list → style2; card → style3 (Zibll fieldsets).
$style = '';
if ($mode === 'card') {
$style = sanitize_key((string) ($list['card_variant'] ?? ''));
if (!in_array($style, ['', 'style3'], true)) {
$style = '';
}
} else {
$style = sanitize_key((string) ($list['list_style'] ?? ''));
if (!in_array($style, ['', 'style2'], true)) {
$style = '';
}
}
if (isset($overrides['style']) && is_string($overrides['style'])) {
$style = sanitize_key($overrides['style']);
if (in_array($style, ['default', 'null'], true)) {
$style = '';
}
}
$excerpt_words = max(8, (int) round(((int) ($list['excerpt_length'] ?? 120)) / 4));
$config = [
'context' => $context,
'mode' => $mode,
// list_type token for text / thumb_if_has hooks (renderer card_style key).
'card_style' => $list_type,
'style' => $style === 'default' ? '' : $style,
'list_show_type' => (string) ($list['list_show_type'] ?? 'separate'),
'list_img_position' => (string) ($list['list_img_position'] ?? 'left'),
'thumb_if_has' => ($list_type === 'thumb_if_has'),
'show_thumb' => ($list_type !== 'text'),
'show_author' => !empty($list['show_author']),
'show_date' => !empty($list['show_date']),
'show_views' => !empty($list['show_views']),
'show_comments' => !empty($list['show_comments']),
'show_likes' => !empty($list['show_likes']),
'target_blank' => !empty($list['target_blank']),
'heading_bold' => !empty($list['heading_bold']),
'badge_show' => !empty($list['badge_show']),
'show_excerpt' => $mode !== 'card',
'excerpt_words' => $excerpt_words,
];
// Multi-thumb from global thumb settings + category allowlist.
if (class_exists('AKSRT_Settings')) {
$thumb_settings = AKSRT_Settings::get_post_thumb_settings();
if (!empty($thumb_settings['multi_enabled'])) {
$config['multi_thumb_enabled'] = true;
$config['multi_thumb_limit'] = (int) ($thumb_settings['multi_count'] ?? 4);
$config['multi_thumb_min'] = 3;
}
if (($context === 'category' || $context === 'topics') && !empty($thumb_settings['mult_thumb_cat_ids']) && $term_id > 0) {
if (in_array($term_id, array_map('intval', (array) $thumb_settings['mult_thumb_cat_ids']), true)) {
$config['multi_thumb_enabled'] = true;
$config['multi_thumb_limit'] = (int) ($thumb_settings['multi_count'] ?? 4);
$config['multi_thumb_min'] = 3;
}
}
}
// Merge remaining overrides last (except mode/style already handled carefully).
foreach ($overrides as $key => $value) {
if (in_array($key, ['mode', 'type', 'is_card', 'style', 'context'], true)) {
continue;
}
$config[$key] = $value;
}
// Re-apply forced mode after merge if present.
if ($forced_mode !== '' && in_array($forced_mode, ['list', 'card', 'mini', 'grid-cms'], true)) {
$config['mode'] = $forced_mode;
}
$config['context'] = $context;
$config['style'] = $style === 'default' ? '' : $style;
return $config;
}
endif;
if (!function_exists('aksrt_archive_get_render_config')) :
/**
* Build render config for archive-like pages.
@@ -36,32 +226,20 @@ if (!function_exists('aksrt_archive_get_render_config')) :
* @return array<string,mixed>
*/
function aksrt_archive_get_render_config(array $overrides = []): array {
$list = aksrt_archive_get_list_style_settings();
$config = array_merge([
'context' => 'archive',
'mode' => $list['render_mode'],
'card_style' => $list['card_style'],
], $overrides);
$context = sanitize_key((string) ($overrides['context'] ?? ''));
$term_id = isset($overrides['term_id']) ? (int) $overrides['term_id'] : 0;
if (is_category() && !empty($list['card_cat_ids'])) {
$current_cat_id = (int) get_queried_object_id();
if (in_array($current_cat_id, $list['card_cat_ids'], true)) {
$config['mode'] = 'card';
}
// Only treat explicit mode as override; empty string means follow global resolver.
$resolver_overrides = $overrides;
if (isset($resolver_overrides['mode']) && $resolver_overrides['mode'] === '') {
unset($resolver_overrides['mode']);
}
if (is_category() && class_exists('AKSRT_Settings')) {
$thumb_settings = AKSRT_Settings::get_post_thumb_settings();
if (!empty($thumb_settings['mult_thumb_cat_ids'])) {
$current_cat_id = (int) get_queried_object_id();
if (in_array($current_cat_id, array_map('intval', (array) $thumb_settings['mult_thumb_cat_ids']), true)) {
$config['multi_thumb_enabled'] = true;
$config['multi_thumb_limit'] = (int) ($thumb_settings['multi_count'] ?? 4);
}
}
}
return $config;
return aksrt_resolve_post_list_render_config([
'context' => $context,
'term_id' => $term_id,
'overrides' => $resolver_overrides,
]);
}
endif;
+31 -12
View File
@@ -384,11 +384,18 @@ if (!function_exists('aksrt_homepage_render_sortbar')) {
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php
$view_mode = 'list';
if (function_exists('aksrt_resolve_post_list_render_config')) {
$home_view_cfg = aksrt_resolve_post_list_render_config(['context' => 'home']);
$view_mode = (($home_view_cfg['mode'] ?? 'list') === 'card') ? 'card' : 'list';
}
?>
<div class="aksrt-homepage__view-toggle" data-aksrt-view-toggle>
<button type="button" class="aksrt-homepage__view-btn is-active" data-view-mode="list" aria-label="<?php esc_attr_e('列表视图', 'aksrt'); ?>">
<button type="button" class="aksrt-homepage__view-btn<?php echo $view_mode === 'list' ? ' is-active' : ''; ?>" data-view-mode="list" aria-label="<?php esc_attr_e('列表视图', 'aksrt'); ?>">
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M1 3h14v2H1V3zm0 4h14v2H1V7zm0 4h14v2H1v-2z"/></svg>
</button>
<button type="button" class="aksrt-homepage__view-btn" data-view-mode="card" aria-label="<?php esc_attr_e('卡片视图', 'aksrt'); ?>">
<button type="button" class="aksrt-homepage__view-btn<?php echo $view_mode === 'card' ? ' is-active' : ''; ?>" data-view-mode="card" aria-label="<?php esc_attr_e('卡片视图', 'aksrt'); ?>">
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M1 1h4v4H1V1zm5 0h4v4H6V1zm5 0h4v4h-4V1zM1 6h4v4H1V6zm5 0h4v4H6V6zm5 0h4v4h-4V6zM1 11h4v4H1v-4zm5 0h4v4H6v-4zm5 0h4v4h-4v-4z"/></svg>
</button>
</div>
@@ -589,10 +596,12 @@ if (!function_exists('aksrt_homepage_get_latest_panel_contract')) {
unset($query_vars['paged'], $query_vars['page']);
$render_config = [
'mode' => 'list',
'context' => 'home',
];
$render_config = function_exists('aksrt_resolve_post_list_render_config')
? aksrt_resolve_post_list_render_config(['context' => 'home'])
: [
'mode' => 'list',
'context' => 'home',
];
return [
'query_context' => 'homepage_latest',
@@ -753,10 +762,12 @@ if (!function_exists('aksrt_homepage_render_post_card')) {
return;
}
$config = [
'mode' => 'list',
'context' => 'home',
];
$config = function_exists('aksrt_resolve_post_list_render_config')
? aksrt_resolve_post_list_render_config(['context' => 'home'])
: [
'mode' => 'list',
'context' => 'home',
];
echo aksrt_render_post($config); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
@@ -768,15 +779,23 @@ if (!function_exists('aksrt_homepage_render_posts_grid')) {
*/
function aksrt_homepage_render_posts_grid(?WP_Query $query = null, bool $with_pagination = false): void {
$query = $query instanceof WP_Query ? $query : aksrt_homepage_get_latest_query();
$config = function_exists('aksrt_resolve_post_list_render_config')
? aksrt_resolve_post_list_render_config(['context' => 'home'])
: [
'mode' => 'list',
'context' => 'home',
];
$config['skip_wrapper'] = true;
$view = (($config['mode'] ?? 'list') === 'card') ? 'card' : 'list';
if (function_exists('aksrt_render_post_list')) {
// Panel already provides posts-row.ajaxpager; avoid nested wrapper.
aksrt_render_post_list($query, ['mode' => 'list', 'context' => 'home', 'skip_wrapper' => true], true);
aksrt_render_post_list($query, $config, true);
} else {
if (!$query->have_posts()) {
echo '<div class="no-results"><p>' . esc_html__('暂无文章', 'aksrt') . '</p></div>';
} else {
echo '<div class="posts-row aksrt-homepage__posts" data-view="list">';
echo '<div class="posts-row aksrt-homepage__posts" data-view="' . esc_attr($view) . '">';
while ($query->have_posts()) {
$query->the_post();
aksrt_homepage_render_post_card();
+15 -3
View File
@@ -50,6 +50,7 @@ if (!function_exists('aksrt_renderer_defaults')) {
'multi_thumb_limit' => 4,
'multi_thumb_min' => 2,
'list_show_type' => 'separate',
'list_img_position' => 'left',
'number_offset' => 0,
'show_number' => false,
'extra_class' => '',
@@ -87,9 +88,15 @@ if (!function_exists('aksrt_renderer_config')) {
$cfg['show_comments'] = false;
}
if ($cfg['mode'] === 'card' || $cfg['mode'] === 'grid-cms') {
$cfg['style'] = $cfg['style'] === 'default' ? 'style3' : $cfg['style'];
if (in_array((string) $cfg['style'], ['default', 'null'], true)) {
$cfg['style'] = '';
}
$cfg['list_img_position'] = in_array(sanitize_key((string) ($cfg['list_img_position'] ?? 'left')), ['left', 'right'], true)
? sanitize_key((string) ($cfg['list_img_position'] ?? 'left'))
: 'left';
$cfg['list_show_type'] = in_array(sanitize_key((string) ($cfg['list_show_type'] ?? 'separate')), ['separate', 'no_margin'], true)
? sanitize_key((string) ($cfg['list_show_type'] ?? 'separate'))
: 'separate';
return $cfg;
}
@@ -514,7 +521,11 @@ if (!function_exists('aksrt_renderer_thumb')) {
$target_attr = !empty($cfg['target_blank']) ? ' target="_blank"' : '';
if ($cfg['mode'] === 'list') {
return '<div class="post-graphic"><div class="item-thumbnail' . esc_attr($empty_class) . '"><a href="' . esc_url($href) . '" rel="bookmark"' . $target_attr . '>'
$graphic_class = 'post-graphic';
if (($cfg['list_img_position'] ?? 'left') === 'right') {
$graphic_class .= ' order1';
}
return '<div class="' . esc_attr($graphic_class) . '"><div class="item-thumbnail' . esc_attr($empty_class) . '"><a href="' . esc_url($href) . '" rel="bookmark"' . $target_attr . '>'
. $img_html . '</a>' . $sticky_html . $format_badge . '</div></div>';
}
@@ -714,6 +725,7 @@ if (!function_exists('aksrt_renderer_list')) {
}
if (($cfg['list_show_type'] ?? 'separate') === 'no_margin') {
$classes[] = 'no-margin';
$classes[] = 'no_margin';
}
$thumb = aksrt_renderer_thumb($data, $cfg);
+4 -5
View File
@@ -25,14 +25,13 @@ get_header();
<div class="content-layout<?php echo $has_sidebar ? '' : ' content-layout--no-sidebar'; ?>">
<div class="content-layout__primary">
<?php
$post_layout = class_exists('AKSRT_Settings')
? AKSRT_Settings::get_archive_layout()
: 'grid-cms';
$render_mode = in_array($post_layout, ['list', 'mini'], true) ? $post_layout : 'card';
$render_config = function_exists('aksrt_resolve_post_list_render_config')
? aksrt_resolve_post_list_render_config(['context' => 'archive'])
: ['context' => 'archive', 'mode' => 'list'];
?>
<?php if (have_posts()) : ?>
<?php aksrt_render_post_list(null, ['context' => 'archive', 'mode' => $render_mode, 'card_style' => 'standard']); ?>
<?php aksrt_render_post_list(null, $render_config); ?>
<?php aksrt_render_pagination(); ?>
<?php else : ?>
<div class="no-results">
+1 -4
View File
@@ -85,14 +85,11 @@ $search_count = isset($loop_query->found_posts) ? (int) $loop_query->found_posts
$render_config = function_exists('aksrt_archive_get_render_config')
? aksrt_archive_get_render_config([
'context' => 'search',
'mode' => (string) ($list_settings['render_mode'] ?? 'card'),
'card_style' => (string) ($list_settings['card_style'] ?? 'standard'),
'highlight_query' => $search_query,
])
: [
'context' => 'search',
'mode' => (string) ($list_settings['render_mode'] ?? 'card'),
'card_style' => (string) ($list_settings['card_style'] ?? 'standard'),
'mode' => 'list',
'highlight_query' => $search_query,
];
+13 -10
View File
@@ -45,17 +45,20 @@ $ajax_filter = !empty($filter_settings['ajax_enabled']) && !empty($filter_settin
$sort_state = function_exists('aksrt_archive_get_sort_state') ? aksrt_archive_get_sort_state() : ['current' => 'latest', 'links' => []];
$current_sort = $sort_state['current'];
$sort_links = $sort_state['links'];
$render_config = function_exists('aksrt_archive_get_render_config')
? aksrt_archive_get_render_config([
'context' => 'tag',
'mode' => $layout_mode,
'card_style' => $card_style,
])
: [
'context' => 'tag',
'mode' => $layout_mode,
'card_style' => $card_style,
$render_overrides = [
'context' => 'tag',
];
// Term meta layout_mode is authoritative only when explicitly set (non-empty preset).
$layout_preset = (string) ($archive_settings['layout_preset'] ?? '');
if ($layout_preset !== '' && in_array((string) $layout_mode, ['list', 'card', 'mini', 'grid-cms'], true)) {
$render_overrides['mode'] = (string) $layout_mode;
if (!empty($card_style)) {
$render_overrides['card_style'] = (string) $card_style;
}
}
$render_config = function_exists('aksrt_archive_get_render_config')
? aksrt_archive_get_render_config($render_overrides)
: array_merge(['context' => 'tag', 'mode' => 'list'], $render_overrides);
$cat_filter_terms = [];
$current_filter_cat = sanitize_text_field((string) get_query_var('aksrt_filter_cat', ''));