diff --git a/assets/css/frontend/homepage-fixed/ajax-tab-error-state.css b/assets/css/frontend/homepage-fixed/ajax-tab-error-state.css index f867ad90..71c3502d 100644 --- a/assets/css/frontend/homepage-fixed/ajax-tab-error-state.css +++ b/assets/css/frontend/homepage-fixed/ajax-tab-error-state.css @@ -116,6 +116,20 @@ ================================================================ */ @media (max-width: 640px) { + .aksrt-homepage__stream-header { + flex-direction: column; + align-items: flex-start; + gap: 10px; + } + + .aksrt-homepage__stream-title { + font-size: 20px; + } + + .aksrt-homepage__stream-subtitle { + font-size: 13px; + } + .aksrt-homepage__tabs, .aksrt-homepage__titlebox { margin-bottom: 8px; diff --git a/assets/css/frontend/homepage-fixed/base-1.css b/assets/css/frontend/homepage-fixed/base-1.css index 3ca9aa28..63c24c3e 100644 --- a/assets/css/frontend/homepage-fixed/base-1.css +++ b/assets/css/frontend/homepage-fixed/base-1.css @@ -130,6 +130,23 @@ margin-bottom: 20px; } +.aksrt-homepage__content-zone--operated, +.aksrt-homepage__content-zone--mid, +.aksrt-homepage__content-zone--supplement { + margin-bottom: 20px; +} + +.aksrt-homepage__content-zone--operated.home-modules, +.aksrt-homepage__content-zone--mid.home-modules, +.aksrt-homepage__content-zone--supplement.home-modules { + gap: 24px; + padding-bottom: 0; +} + +.aksrt-homepage__content-zone--supplement { + padding-top: 4px; +} + .aksrt-homepage__content-zone--featured.home-modules { gap: 24px; padding-bottom: 0; @@ -176,6 +193,43 @@ 4. STREAM CONTAINER ================================================================ */ +.aksrt-homepage__stream-header { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 16px; + margin-bottom: 14px; + padding: 0; +} + +.aksrt-homepage__stream-intro { + min-width: 0; +} + +.aksrt-homepage__stream-kicker { + margin-bottom: 6px; + color: var(--color-primary, var(--color-primary)); + font-size: 12px; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.aksrt-homepage__stream-title { + margin: 0; + color: var(--color-ink); + font-size: 24px; + font-weight: 700; + line-height: 1.25; +} + +.aksrt-homepage__stream-subtitle { + margin: 8px 0 0; + color: var(--color-ink-3, #777); + font-size: 14px; + line-height: 1.6; +} + .aksrt-homepage__stream, .aksrt-homepage__stream.widget-card { overflow: visible; diff --git a/assets/css/frontend/homepage-fixed/base-2.css b/assets/css/frontend/homepage-fixed/base-2.css index 3f33502b..1bb7211a 100644 --- a/assets/css/frontend/homepage-fixed/base-2.css +++ b/assets/css/frontend/homepage-fixed/base-2.css @@ -66,14 +66,14 @@ transition: opacity 0.3s ease; } -.aksrt-homepage__panel.is-active, -.aksrt-homepage__panel:not([hidden]) { - opacity: 1; +.aksrt-homepage__panel-contract { + display: none; +} + +.aksrt-homepage__posts.post-grid--home { + gap: 0; } -/* ================================================================ - 9. POST LIST — LIST MODE - ================================================================ */ .aksrt-homepage__posts { display: block; diff --git a/front-page.php b/front-page.php index f07386cc..9972ca39 100644 --- a/front-page.php +++ b/front-page.php @@ -1,6 +1,9 @@ = $limit) { break; } - // Skip excluded categories if (isset($excluded_cat_ids[$tab['term_id']])) { continue; } @@ -181,10 +179,6 @@ if (!function_exists('aksrt_homepage_get_tab_terms')) { if (!function_exists('aksrt_homepage_get_tab_posts_per_page')) { /** * Per-tab homepage post count. - * - * Reads from AKSRT_Settings::homepage_tab_posts_per_page() first; - * falls back to the legacy module config bridge for old installs - * that haven't saved the new setting yet. */ function aksrt_homepage_get_tab_posts_per_page(): int { if (class_exists('AKSRT_Settings')) { @@ -194,7 +188,6 @@ if (!function_exists('aksrt_homepage_get_tab_posts_per_page')) { } } - // Legacy fallback for sites that haven't migrated yet $legacy = aksrt_homepage_get_legacy_tabs_config(); $count = (int) apply_filters('aksrt_homepage_tab_posts_per_page', $legacy['posts_per_page']); @@ -307,10 +300,6 @@ if (!function_exists('aksrt_homepage_get_sort_items')) { if (!function_exists('aksrt_homepage_apply_sort_args')) { /** * Apply sort args to a query configuration. - * Supports all 8 homepage sort modes. - * - * @param array $args - * @return array */ function aksrt_homepage_apply_sort_args(array $args): array { $sort_mode = aksrt_homepage_get_sort_mode(); @@ -362,10 +351,6 @@ if (!function_exists('aksrt_homepage_apply_sort_args')) { if (!function_exists('aksrt_homepage_apply_named_sort_args')) { /** * Apply a specific named sort to query args (used by per-tab orderby). - * - * @param array $args - * @param string $sort_mode - * @return array */ function aksrt_homepage_apply_named_sort_args(array $args, string $sort_mode): array { $allowed = class_exists('AKSRT_Settings') @@ -376,7 +361,6 @@ if (!function_exists('aksrt_homepage_apply_named_sort_args')) { $sort_mode = 'date'; } - // Temporarily override the global sort mode $previous = get_query_var('aksrt_homepage_sort_override'); set_query_var('aksrt_homepage_sort_override', $sort_mode); $result = aksrt_homepage_apply_sort_args($args); @@ -389,8 +373,6 @@ if (!function_exists('aksrt_homepage_apply_named_sort_args')) { if (!function_exists('aksrt_homepage_render_sortbar')) { /** * Render the main-stream sort bar. - * Only renders when home_list_sort_enabled is true. - * Supports inline links or dropdown mode. */ function aksrt_homepage_render_sortbar(): void { if (class_exists('AKSRT_Settings') && !AKSRT_Settings::home_list_sort_enabled()) { @@ -459,7 +441,6 @@ if (!function_exists('aksrt_homepage_render_sortbar')) { if (!function_exists('aksrt_homepage_get_latest_query')) { /** * Homepage main-stream query. - * Applies sort, exclusion filters, and content model. */ function aksrt_homepage_get_latest_query(): WP_Query { static $query = null; @@ -478,7 +459,6 @@ if (!function_exists('aksrt_homepage_get_latest_query')) { 'order' => 'DESC', ]; - // Exclude specific posts (both main stream and tabs) $exclude_ids = class_exists('AKSRT_Settings') ? AKSRT_Settings::home_exclude_post_ids() : []; @@ -486,7 +466,6 @@ if (!function_exists('aksrt_homepage_get_latest_query')) { $query_args['post__not_in'] = $exclude_ids; } - // Exclude specific categories (main stream only) $exclude_cat_ids = class_exists('AKSRT_Settings') ? AKSRT_Settings::home_exclude_category_ids() : []; @@ -503,11 +482,6 @@ if (!function_exists('aksrt_homepage_get_latest_query')) { if (!function_exists('aksrt_homepage_get_tab_query')) { /** * Build a category-tab query. - * Uses the tab's own orderby instead of the main stream sort. - * Applies post exclusion but NOT category exclusion (tabs bind to specific categories). - * - * @param int $term_id Category term ID. - * @param string $orderby Per-tab orderby override. */ function aksrt_homepage_get_tab_query(int $term_id, string $orderby = 'date'): WP_Query { static $queries = []; @@ -530,7 +504,6 @@ if (!function_exists('aksrt_homepage_get_tab_query')) { 'no_found_rows' => true, ]; - // Exclude specific posts (shared with main stream) $exclude_ids = class_exists('AKSRT_Settings') ? AKSRT_Settings::home_exclude_post_ids() : []; @@ -538,7 +511,6 @@ if (!function_exists('aksrt_homepage_get_tab_query')) { $query_args['post__not_in'] = $exclude_ids; } - // Apply per-tab orderby (NOT the main stream sort) $queries[$cache_key] = new WP_Query( aksrt_homepage_apply_named_sort_args($query_args, $orderby) ); @@ -630,6 +602,35 @@ if (!function_exists('aksrt_homepage_render_sidebar')) { } } +if (!function_exists('aksrt_homepage_get_latest_panel_contract')) { + /** + * Public-safe latest stream contract shared by homepage pagination/AJAX. + * + * @return array{query_context:string,query_vars:string,render_config:string,render_config_array:array} + */ + function aksrt_homepage_get_latest_panel_contract(): array { + $query = aksrt_homepage_get_latest_query(); + $query_vars = $query instanceof WP_Query ? $query->query_vars : []; + if (!is_array($query_vars)) { + $query_vars = []; + } + + unset($query_vars['paged'], $query_vars['page']); + + $render_config = [ + 'mode' => 'list', + 'context' => 'home', + ]; + + return [ + 'query_context' => 'homepage_latest', + 'query_vars' => (string) wp_json_encode($query_vars), + 'render_config' => (string) wp_json_encode($render_config), + 'render_config_array' => $render_config, + ]; + } +} + if (!function_exists('aksrt_homepage_render_pagination')) { /** * Render pagination for the fixed homepage latest stream. @@ -669,7 +670,6 @@ if (!function_exists('aksrt_homepage_render_pagination')) { } $links = paginate_links($base_args); - if (!$links || !is_array($links)) { return; } @@ -684,12 +684,18 @@ if (!function_exists('aksrt_homepage_render_pagination')) {
+ data-query-context="" + data-query-vars="" + data-render-config="" + data-page="" + data-tab="latest"> @@ -706,9 +712,6 @@ if (!function_exists('aksrt_get_post_gallery_images')) { /** * Collect gallery images for homepage mult-thumb cards. * - * Uses a transient keyed by the post modified timestamp so repeated list - * renders do not keep re-parsing post content. - * * @return string[] */ function aksrt_get_post_gallery_images(int $post_id, int $limit = 4): array { @@ -745,7 +748,7 @@ if (!function_exists('aksrt_get_post_gallery_images')) { $content = (string) get_post_field('post_content', $post_id, 'raw'); if ($content !== '') { - if (preg_match_all('/]+src=["\x27"]([^"\x27"]+)["\x27"]/i', $content, $html_matches) && !empty($html_matches[1])) { + if (preg_match_all('/]+src=["\x27]([^"\x27]+)["\x27]/i', $content, $html_matches) && !empty($html_matches[1])) { foreach ($html_matches[1] as $raw_url) { $images[] = esc_url_raw((string) $raw_url); } @@ -772,8 +775,6 @@ if (!function_exists('aksrt_get_post_gallery_images')) { if (!function_exists('aksrt_homepage_render_post_card')) { /** * Render a homepage post card inline. - * - * Thin wrapper over the unified shared renderer (aksrt_render_post). */ function aksrt_homepage_render_post_card(): void { if (!function_exists('aksrt_render_post')) { @@ -791,9 +792,7 @@ if (!function_exists('aksrt_homepage_render_post_card')) { if (!function_exists('aksrt_homepage_render_posts_grid')) { /** - * Render a card-grid post block for the fixed homepage. - * - * Delegates to the unified shared renderer via aksrt_render_post_list. + * Render a list block for the fixed homepage. */ 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(); @@ -801,7 +800,6 @@ if (!function_exists('aksrt_homepage_render_posts_grid')) { if (function_exists('aksrt_render_post_list')) { aksrt_render_post_list($query, ['mode' => 'list', 'context' => 'home'], true); } else { - // Fallback: simple loop if shared renderer is unavailable if (!$query->have_posts()) { echo '

' . esc_html__('暂无文章', 'aksrt') . '

'; } else { @@ -852,9 +850,6 @@ if (!function_exists('aksrt_homepage_get_featured_modules')) { * Resolve non-core homepage modules that should render alongside the fixed * hero/banner/main-stream skeleton. * - * Hero, banner, and tabs are now owned by dedicated settings surfaces, so - * the legacy modules list only contributes featured content modules here. - * * @return array */ function aksrt_homepage_get_featured_modules(): array { @@ -871,6 +866,7 @@ if (!function_exists('aksrt_homepage_get_featured_modules')) { 'tag_cloud', 'friend_links', 'html', + 'highlight_cards', ]; $modules = []; @@ -897,9 +893,6 @@ if (!function_exists('aksrt_homepage_get_featured_modules')) { if (!function_exists('aksrt_homepage_render_featured_modules')) { /** * Render featured homepage modules in configured order. - * - * @param array $modules - * @param string $wrapper_class */ function aksrt_homepage_render_featured_modules(array $modules, string $wrapper_class = 'home-modules'): void { if (empty($modules)) { @@ -923,18 +916,57 @@ if (!function_exists('aksrt_homepage_render_featured_modules')) { } } +if (!function_exists('aksrt_homepage_split_featured_modules')) { + /** + * Split legacy featured modules into homepage skeleton slots. + * + * @param array $modules + * @return array{top:array,mid:array,bottom:array} + */ + function aksrt_homepage_split_featured_modules(array $modules): array { + $buckets = [ + 'top' => [], + 'mid' => [], + 'bottom' => [], + ]; + + $top_types = ['highlight_cards', 'hotspot', 'html']; + $bottom_types = ['ranking', 'tag_cloud', 'friend_links']; + + foreach ($modules as $module) { + $type = sanitize_key((string) ($module['type'] ?? '')); + if ($type === '') { + continue; + } + + if (in_array($type, $top_types, true)) { + $buckets['top'][] = $module; + continue; + } + + if (in_array($type, $bottom_types, true)) { + $buckets['bottom'][] = $module; + continue; + } + + $buckets['mid'][] = $module; + } + + return $buckets; + } +} + if (!function_exists('aksrt_homepage_render_layout')) { /** * Render the fixed homepage layout directly. - * - * Keeping the markup here avoids silent empty homepages when a template - * part file is missing or not synced on the target server. */ function aksrt_homepage_render_layout(): void { $current_page = aksrt_homepage_get_current_page(); $show_tabs = $current_page === 1; $tab_configs = $show_tabs ? aksrt_homepage_get_tab_configs() : []; $featured_modules = $show_tabs ? aksrt_homepage_get_featured_modules() : []; + $featured_slots = $show_tabs ? aksrt_homepage_split_featured_modules($featured_modules) : ['top' => [], 'mid' => [], 'bottom' => []]; + $latest_contract = aksrt_homepage_get_latest_panel_contract(); $has_sidebar = aksrt_homepage_has_sidebar(); $hero_on = $show_tabs && aksrt_homepage_module_hero_enabled(); $banner_on = $show_tabs && aksrt_homepage_module_banner_enabled(); @@ -971,16 +1003,25 @@ if (!function_exists('aksrt_homepage_render_layout')) { aksrt_homepage_render_system_module('banner', 'aksrt-homepage__content-zone aksrt-homepage__content-zone--banner aksrt-homepage__system-modules home-modules'); } - if (!empty($featured_modules)) { + if (!empty($featured_slots['top'])) { aksrt_homepage_render_featured_modules( - $featured_modules, - 'aksrt-homepage__content-zone aksrt-homepage__content-zone--featured home-modules' + $featured_slots['top'], + 'aksrt-homepage__content-zone aksrt-homepage__content-zone--operated aksrt-homepage__content-zone--top-modules home-modules' ); } ?>
+
+
+
+

+

+
+ +
+
    @@ -1010,27 +1051,22 @@ if (!function_exists('aksrt_homepage_render_layout')) {
-
- + 1) : ?>
- 1) : ?> - - - - + + +
-
@@ -1038,6 +1074,14 @@ if (!function_exists('aksrt_homepage_render_layout')) {
+
@@ -1049,19 +1093,32 @@ if (!function_exists('aksrt_homepage_render_layout')) { data-home-tab-panel="term-" data-tab-orderby="" hidden - > -
+ >
- + @@ -1083,8 +1140,6 @@ if (!function_exists('aksrt_homepage_render_layout')) { if (!function_exists('aksrt_render_fixed_homepage')) { /** * Render the new fixed homepage layout. - * - * @return bool True when the current request was handled. */ function aksrt_render_fixed_homepage(): bool { if (!aksrt_is_fixed_homepage_request()) { diff --git a/inc/helpers/aksrt-posts-renderer.php b/inc/helpers/aksrt-posts-renderer.php index 60488323..9bd2caa3 100644 --- a/inc/helpers/aksrt-posts-renderer.php +++ b/inc/helpers/aksrt-posts-renderer.php @@ -913,6 +913,8 @@ if (!function_exists('aksrt_render_post_list')) { if ($cfg['context'] === 'home') { $wrapper_classes[] = 'aksrt-homepage__posts'; + $wrapper_classes[] = 'post-grid'; + $wrapper_classes[] = 'post-grid--home'; } elseif ($cfg['mode'] !== 'mini') { $wrapper_classes[] = 'post-grid'; $wrapper_classes[] = 'post-grid--' . $cfg['mode']; diff --git a/index.php b/index.php index a5807d75..4f53fbc7 100644 --- a/index.php +++ b/index.php @@ -1,10 +1,9 @@