diff --git a/assets/admin/src/schema/sections/page-display/index.js b/assets/admin/src/schema/sections/page-display/index.js index a999be28..1b40dcab 100644 --- a/assets/admin/src/schema/sections/page-display/index.js +++ b/assets/admin/src/schema/sections/page-display/index.js @@ -51,7 +51,7 @@ export const pageDisplaySchemas = { mobile_navbar_align: 'left', header_newposts_enabled: true, header_newposts_text: ' 发布', - header_newposts_radius: 20, + header_newposts_radius: true, header_newposts_class: '', header_theme_custom: false, header_theme_bg_custom: '', @@ -126,7 +126,7 @@ export const pageDisplaySchemas = { fields: [ { key: 'header_newposts_enabled', label: '启用发布按钮', type: 'switch', default: true, help: '导航栏显示前台发布入口' }, { key: 'header_newposts_text', label: '按钮文案', type: 'input', default: ' 发布', dependsOn: { key: 'header_newposts_enabled', value: true } }, - { key: 'header_newposts_radius', label: '圆角 (px)', type: 'number', default: 20, min: 0, max: 30, dependsOn: { key: 'header_newposts_enabled', value: true } }, + { key: 'header_newposts_radius', label: '按钮圆角(胶囊)', type: 'switch', default: true, dependsOn: { key: 'header_newposts_enabled', value: true }, help: '开启后两端大圆角,对齐 zibll nav_newposts_radius' }, { key: 'header_newposts_class', label: '自定义 CSS 类', type: 'input', default: '', dependsOn: { key: 'header_newposts_enabled', value: true } }, { key: 'header_newposts_types', label: '发布类型', type: 'select', multiple: true, default: ['post'], options: [ { label: '文章', value: 'post' }, diff --git a/assets/css/frontend/nav/zib-utilities.css b/assets/css/frontend/nav/zib-utilities.css index ba3d1e3c..cda1622a 100644 --- a/assets/css/frontend/nav/zib-utilities.css +++ b/assets/css/frontend/nav/zib-utilities.css @@ -162,3 +162,61 @@ body.mobile-navbar-show { overflow: hidden; } .aksrt-sme-field { display: block; margin: 4px 0; } .aksrt-sme-field span { display: block; font-size: 12px; color: #646970; } .aksrt-sme-card, .aksrt-sme-col { border: 1px solid #dcdcde; padding: 8px; margin: 8px 0; border-radius: 4px; } + +/* Layout-2 remote menu search panel (zibll menu_search) */ +.aksrt-remote-box[data-aksrt-menu-search-remote] { + min-height: 8px; +} +.navbar-inline-search-panel { + min-width: 300px; + max-width: 380px; + max-height: 70vh; + overflow: auto; +} +.aksrt-menu-search-posts__item { + display: flex; + flex-direction: column; + gap: 2px; + padding: 6px 2px; + color: inherit; + text-decoration: none; + border-bottom: 1px solid rgba(0,0,0,.04); +} +.aksrt-menu-search-posts__item:last-child { border-bottom: 0; } +.aksrt-menu-search-posts__item:hover { color: var(--focus-color); } +.aksrt-menu-search-history__list .but, +.navbar-inline-search-hots .but { margin: 0 4px 4px 0; } +.loading-spot { + display: inline-block; + width: 1em; + height: 1em; + margin: 8px; + border: 2px solid rgba(0,0,0,.15); + border-top-color: var(--focus-color, #f04494); + border-radius: 50%; + animation: aksrt-spin .7s linear infinite; +} +@keyframes aksrt-spin { to { transform: rotate(360deg); } } +.navbar-but .radius, +.navbar-but .but.radius, +.navbar-cta.radius { + border-radius: 999px !important; +} + +/* Active menu underline (zibll-like) */ +.navbar-top .nav > li.current-menu-item > a, +.navbar-top .nav > li.current-menu-ancestor > a { + color: var(--focus-color); +} +.navbar-top .nav > li.current-menu-item > a::before, +.navbar-top .nav > li.current-menu-ancestor > a::before { + content: ""; + position: absolute; + left: 10px; + right: 10px; + top: 0; + height: 3px; + border-radius: 0 0 3px 3px; + background: var(--focus-color); +} +.navbar-top .nav > li > a { position: relative; } diff --git a/assets/js/admin-nav-menu-senior.js b/assets/js/admin-nav-menu-senior.js index a6dadc76..eb6dbcb6 100644 --- a/assets/js/admin-nav-menu-senior.js +++ b/assets/js/admin-nav-menu-senior.js @@ -39,11 +39,15 @@ }; } - function field(name, label, value, type) { + function field(name, label, value, type, withMedia) { type = type || 'text'; + var mediaBtn = withMedia + ? ' 选择图片' + : ''; return ( '' + label + + mediaBtn + ''; html += '卡片 #' + (i + 1) + ''; html += ' 删除'; - html += field('img', '图片 URL', item.img || ''); + html += field('img', '图片 URL', item.img || '', 'text', true); html += field('title', '标题', item.title || ''); html += field('badge', '徽章', item.badge || ''); html += field('badge_class', '徽章 class', item.badge_class || ''); @@ -236,6 +240,24 @@ }); } + + $(document).on('click', '.aksrt-sme-pick-img', function (e) { + e.preventDefault(); + var $btn = $(this); + var name = $btn.data('for'); + var $input = $btn.closest('.aksrt-sme-field').find('input[data-name="' + name + '"]'); + if (typeof wp === 'undefined' || !wp.media) { + window.alert('媒体库不可用'); + return; + } + var frame = wp.media({ title: '选择图片', button: { text: '使用此图' }, multiple: false, library: { type: 'image' } }); + frame.on('select', function () { + var att = frame.state().get('selection').first().toJSON(); + if (att && att.url) $input.val(att.url).trigger('change'); + }); + frame.open(); + }); + $(boot); $(document).on('menu-item-added', function () { setTimeout(boot, 50); diff --git a/assets/js/header-inline-search.js b/assets/js/header-inline-search.js index 75b79f09..569f295a 100644 --- a/assets/js/header-inline-search.js +++ b/assets/js/header-inline-search.js @@ -1,112 +1,166 @@ /** - * Enhance layout-2 inline search with AJAX suggestions (aksrt_search_suggestions). - * Extends existing panel search without dual systems. + * Layout-2 navbar search — zibll remote-box + live suggestions. + * Loads aksrt_menu_search panel (history/hot/posts), then suggests on input. */ (function () { "use strict"; - function initInlineSearchSuggest() { - var form = document.querySelector('form[data-aksrt-search-form="inline"]'); - if (!form || !window.aksrtData || !aksrtData.ajaxUrl) return; + var HISTORY_KEY = "aksrt-mobile-search-history"; + function ajaxUrl() { + return (window.aksrtData && aksrtData.ajaxUrl) || ""; + } + function nonce() { + return (window.aksrtData && aksrtData.nonce) || ""; + } + + function readLocalHistory() { + try { + var raw = localStorage.getItem(HISTORY_KEY); + var list = raw ? JSON.parse(raw) : []; + if (!Array.isArray(list)) return []; + return list + .map(function (it) { + if (typeof it === "string") return it; + return it && it.keyword ? String(it.keyword) : ""; + }) + .filter(Boolean) + .slice(0, 10); + } catch (e) { + return []; + } + } + + function writeLocalHistory(keywords) { + try { + var items = (keywords || []).slice(0, 10).map(function (k) { + return { keyword: k, type: "post" }; + }); + localStorage.setItem(HISTORY_KEY, JSON.stringify(items)); + } catch (e) {} + } + + function loadRemote(box) { + if (!box || box.getAttribute("data-loaded") === "1") return; + var url = box.getAttribute("remote-box") || box.getAttribute("data-url"); + if (!url) return; + box.setAttribute("data-loaded", "1"); + var sep = url.indexOf("?") >= 0 ? "&" : "?"; + if (nonce()) { + url = url + sep + "nonce=" + encodeURIComponent(nonce()); + } + fetch(url, { credentials: "same-origin" }) + .then(function (r) { + return r.text(); + }) + .then(function (html) { + if (!html || html === "0") { + box.innerHTML = ""; + return; + } + box.outerHTML = html; + var form = document.querySelector('form[data-aksrt-search-form="inline"]'); + if (form) enhancePanel(form); + }) + .catch(function () { + box.removeAttribute("data-loaded"); + }); + } + + function enhancePanel(form) { + var group = form.querySelector(".form-group"); + var panel = form.querySelector(".navbar-inline-search-panel"); var input = form.querySelector(".search-input"); - var group = form.querySelector(".form-group.relative, .form-group"); - if (!input || !group) return; + if (!group || !input) return; - var panel = group.querySelector(".navbar-inline-search-panel"); - if (!panel) { - panel = document.createElement("div"); - panel.className = "dropdown-menu hover-show-con navbar-inline-search-panel"; - group.appendChild(panel); + // Merge guest local history into panel list. + var histList = form.querySelector(".aksrt-menu-search-history__list"); + if (histList && !(window.aksrtData && aksrtData.isLoggedIn)) { + var local = readLocalHistory(); + if (local.length) { + histList.innerHTML = local + .map(function (kw) { + return ( + '' + + kw + + " " + ); + }) + .join(""); + } } + var clearBtn = form.querySelector("[data-aksrt-clear-menu-history]"); + if (clearBtn && !clearBtn._bound) { + clearBtn._bound = 1; + clearBtn.addEventListener("click", function (e) { + e.preventDefault(); + writeLocalHistory([]); + if (histList) { + histList.innerHTML = + '暂无历史'; + } + }); + } + + var suggestMount = form.querySelector("[data-aksrt-menu-suggest]"); var timer = null; var searchConfig = (window.aksrtData && aksrtData.search) || {}; - var suggestionsEnabled = searchConfig.suggestionsEnabled !== false; function typeValue() { var t = form.querySelector('input[name="aksrt_search_type"]'); return (t && t.value) || searchConfig.defaultType || "post"; } - function renderItems(items) { - var html = ""; - if (items && items.length) { - html += '' + (searchConfig.suggestTitle || "搜索建议") + ""; - html += ''; - items.forEach(function (it) { - html += - '' + - (it.title || "") + - '' + - (it.meta ? '' + it.meta + "" : "") + - ""; - }); - html += ""; - } - // Keep hot keywords block if present as static sibling content was replaced — - // re-append hots from data attribute if we stored them. - var hots = form.getAttribute("data-hots"); - if (hots) { - try { - var arr = JSON.parse(hots); - if (arr && arr.length) { - html += '热门搜索'; - arr.forEach(function (kw) { - html += - '' + - kw + - " "; - }); - html += ""; - } - } catch (e) {} - } - panel.innerHTML = html || panel.innerHTML; - panel.classList.add("is-open"); - panel.style.display = "block"; - panel.style.visibility = "visible"; - } - - // Persist hot keywords for re-render after suggestions - var hotLinks = panel.querySelectorAll(".navbar-inline-search-hots a"); - if (hotLinks.length) { - var kws = []; - hotLinks.forEach(function (a) { - kws.push((a.textContent || "").trim()); - }); - form.setAttribute("data-hots", JSON.stringify(kws)); - } - - function request(q) { - if (!suggestionsEnabled || q.length < 2) { - // restore hots-only - if (form.getAttribute("data-hots")) { - renderItems([]); + function requestSuggest(q) { + if (!suggestMount || !ajaxUrl() || q.length < 2) { + if (suggestMount) { + suggestMount.hidden = true; + suggestMount.innerHTML = ""; } return; } var xhr = new XMLHttpRequest(); - xhr.open("POST", aksrtData.ajaxUrl, true); + xhr.open("POST", ajaxUrl(), true); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); xhr.onload = function () { if (xhr.status < 200 || xhr.status >= 300) return; try { var json = JSON.parse(xhr.responseText); - if (json.success && json.data && json.data.items) { - renderItems(json.data.items); + var items = (json.success && json.data && json.data.items) || []; + if (!items.length) { + suggestMount.hidden = true; + suggestMount.innerHTML = ""; + return; } + var html = + '' + + (searchConfig.suggestTitle || "搜索建议") + + ""; + items.forEach(function (it) { + html += + '' + + (it.title || "") + + '' + + (it.meta + ? '' + it.meta + "" + : "") + + ""; + }); + html += ""; + suggestMount.innerHTML = html; + suggestMount.hidden = false; } catch (e) {} }; xhr.send( "action=aksrt_search_suggestions&nonce=" + - encodeURIComponent(aksrtData.nonce) + + encodeURIComponent(nonce()) + "&q=" + encodeURIComponent(q) + "&type=" + @@ -114,27 +168,75 @@ ); } - input.addEventListener("input", function () { - var q = (input.value || "").trim(); - if (timer) clearTimeout(timer); - timer = setTimeout(function () { - request(q); - }, 180); + if (!input._aksrtMenuSearchBound) { + input._aksrtMenuSearchBound = 1; + input.addEventListener("input", function () { + var q = (input.value || "").trim(); + if (timer) clearTimeout(timer); + timer = setTimeout(function () { + requestSuggest(q); + }, 180); + }); + input.addEventListener("focus", function () { + var remote = form.querySelector("[data-aksrt-menu-search-remote]"); + if (remote) loadRemote(remote); + var p = form.querySelector(".navbar-inline-search-panel"); + if (p) { + p.classList.add("is-open"); + p.style.display = "block"; + p.style.visibility = "visible"; + } + }); + form.addEventListener("submit", function () { + var q = (input.value || "").trim(); + if (!q) return; + if (!(window.aksrtData && aksrtData.isLoggedIn)) { + var list = readLocalHistory().filter(function (k) { + return k !== q; + }); + list.unshift(q); + writeLocalHistory(list); + } + }); + } + } + + function init() { + document.querySelectorAll("[data-aksrt-menu-search-remote]").forEach(function (box) { + // Prefetch on idle / first hover of form. + var form = box.closest("form"); + if (form) { + form.addEventListener( + "mouseenter", + function () { + loadRemote(box); + }, + { once: true } + ); + } + // Also load when lazyload-action ias would fire — simple viewport/idle. + if ("requestIdleCallback" in window) { + requestIdleCallback(function () { + loadRemote(box); + }); + } else { + setTimeout(function () { + loadRemote(box); + }, 600); + } }); - input.addEventListener("focus", function () { - panel.style.display = "block"; - panel.style.visibility = "visible"; - }); + var form = document.querySelector('form[data-aksrt-search-form="inline"]'); + if (form) enhancePanel(form); } if (window.AksrtFrontend && typeof window.AksrtFrontend.register === "function") { window.AksrtFrontend.register("aksrt-inline-search-suggest", function () { - initInlineSearchSuggest(); + init(); }); } else if (document.readyState === "loading") { - document.addEventListener("DOMContentLoaded", initInlineSearchSuggest); + document.addEventListener("DOMContentLoaded", init); } else { - initInlineSearchSuggest(); + init(); } })(); diff --git a/inc/bootstrap.php b/inc/bootstrap.php index e1f09f57..3d202b4a 100644 --- a/inc/bootstrap.php +++ b/inc/bootstrap.php @@ -50,6 +50,7 @@ require_once AKSRT_DIR . '/inc/helpers/aksrt-header-menu-buttons.php'; require_once AKSRT_DIR . '/inc/helpers/header/aksrt-header-render.php'; require_once AKSRT_DIR . '/inc/helpers/header/aksrt-header-navbar.php'; require_once AKSRT_DIR . '/inc/helpers/header/aksrt-header-mobile.php'; +require_once AKSRT_DIR . '/inc/helpers/header/aksrt-header-menu-search.php'; require_once AKSRT_DIR . '/inc/helpers/aksrt-runtime-win.php'; require_once AKSRT_DIR . '/inc/helpers/aksrt-identity.php'; require_once AKSRT_DIR . '/inc/helpers/aksrt-graphic-card.php'; diff --git a/inc/helpers/aksrt-header-menu-buttons.php b/inc/helpers/aksrt-header-menu-buttons.php index 3ad6e0e0..2fe36262 100644 --- a/inc/helpers/aksrt-header-menu-buttons.php +++ b/inc/helpers/aksrt-header-menu-buttons.php @@ -9,7 +9,7 @@ defined('ABSPATH') || exit; if (!function_exists('aksrt_get_header_newposts_config')) : /** - * @return array{enabled:bool,text:string,radius:int,class:string,types:string[]} + * @return array{enabled:bool,text:string,radius:int,radius_pill:bool,class:string,types:string[]} */ function aksrt_get_header_newposts_config(): array { $cfg = class_exists('\AKSRT\Settings\Settings') @@ -210,7 +210,11 @@ if (!function_exists('aksrt_render_header_menu_buttons')) : $class .= ' ' . $cfg['class']; } $radius = (int) ($cfg['radius'] ?? 20); - // Radius applied via CSS class variable to avoid style attribute overriding flex. + $pill = !empty($cfg['radius_pill']) || $radius >= 16; + if ($pill && !str_contains($class, 'radius')) { + $class .= ' radius'; + } + // Radius applied via CSS variable (zibll pill ≈ 20px when switch on). $radius_attr = $radius > 0 ? ' data-radius="' . esc_attr((string) $radius) . '" style="--navbar-cta-radius:' . $radius . 'px"' : ''; $label = (string) ($cfg['text'] ?? __('发布', 'aksrt')); $btn = aksrt_render_new_add_btns($cfg['types'] ?? ['post'], $class, $label); diff --git a/inc/helpers/header/aksrt-header-menu-search.php b/inc/helpers/header/aksrt-header-menu-search.php new file mode 100644 index 00000000..9621e06a --- /dev/null +++ b/inc/helpers/header/aksrt-header-menu-search.php @@ -0,0 +1,141 @@ +' . $html . ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + wp_die(); + } +endif; + +if (!function_exists('aksrt_get_menu_search_panel_html')) : + /** + * Build inner search panel HTML (no outer dropdown wrapper). + */ + function aksrt_get_menu_search_panel_html(): string { + $show_keywords = true; + $show_history = true; + $show_posts = true; + if (class_exists('\AKSRT\Settings\Settings')) { + $show_keywords = method_exists('\AKSRT\Settings\Settings', 'hot_search_enabled') + ? (bool) \AKSRT\Settings\Settings::hot_search_enabled() + : true; + $show_history = method_exists('\AKSRT\Settings\Settings', 'search_history_enabled') + ? (bool) \AKSRT\Settings\Settings::search_history_enabled() + : true; + $show_posts = method_exists('\AKSRT\Settings\Settings', 'search_posts_enabled') + ? (bool) \AKSRT\Settings\Settings::search_posts_enabled() + : !empty(\AKSRT\Settings\Settings::get_value('search_posts', true)); + } + + $out = ''; + + // History (client may also fill via localStorage; server returns logged-in history). + if ($show_history) { + $hist = []; + if (is_user_logged_in()) { + $saved = get_user_meta(get_current_user_id(), 'aksrt_search_history', true); + if (is_array($saved)) { + foreach (array_slice($saved, 0, 10) as $item) { + if (is_array($item) && !empty($item['keyword'])) { + $hist[] = (string) $item['keyword']; + } elseif (is_string($item) && $item !== '') { + $hist[] = $item; + } + } + } + } + $out .= ''; + $out .= '' . esc_html__('搜索历史', 'aksrt') . ''; + $out .= '' . esc_html__('清空', 'aksrt') . ''; + $out .= ''; + if ($hist) { + foreach ($hist as $kw) { + $out .= '' . esc_html($kw) . ' '; + } + } else { + $out .= '' . esc_html__('暂无历史', 'aksrt') . ''; + } + $out .= ''; + } + + // Hot keywords. + if ($show_keywords) { + $hots = function_exists('aksrt_get_search_hot_keywords') ? aksrt_get_search_hot_keywords() : []; + if ($hots) { + $title = class_exists('\AKSRT\Settings\Settings') && method_exists('\AKSRT\Settings\Settings', 'search_popular_title') + ? \AKSRT\Settings\Settings::search_popular_title() + : __('热门搜索', 'aksrt'); + $out .= ''; + $out .= '' . esc_html($title) . ''; + $out .= ''; + foreach ($hots as $kw) { + $kw = trim((string) $kw); + if ($kw === '') { + continue; + } + $out .= '' . esc_html($kw) . ' '; + } + $out .= ''; + } + } + + // Latest / popular posts (optional). + if ($show_posts) { + $posts = get_posts([ + 'post_type' => 'post', + 'post_status' => 'publish', + 'posts_per_page' => 6, + 'ignore_sticky_posts' => true, + 'no_found_rows' => true, + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + ]); + if ($posts) { + $out .= ''; + $out .= '' . esc_html__('推荐内容', 'aksrt') . ''; + $out .= ''; + foreach ($posts as $p) { + $out .= ''; + $out .= '' . esc_html(get_the_title($p)) . ''; + $out .= '' . esc_html(get_the_date('', $p)) . ''; + $out .= ''; + } + $out .= ''; + } + } + + // Live suggestions mount point. + $out .= ''; + + return $out; + } +endif; + +add_action('wp_ajax_aksrt_menu_search', 'aksrt_ajax_menu_search'); +add_action('wp_ajax_nopriv_aksrt_menu_search', 'aksrt_ajax_menu_search'); +// Alias for zibll-compatible remote-box query action name used in markup. +add_action('wp_ajax_menu_search', 'aksrt_ajax_menu_search'); +add_action('wp_ajax_nopriv_menu_search', 'aksrt_ajax_menu_search'); diff --git a/inc/helpers/header/aksrt-header-navbar.php b/inc/helpers/header/aksrt-header-navbar.php index 68188451..a8844ed0 100644 --- a/inc/helpers/header/aksrt-header-navbar.php +++ b/inc/helpers/header/aksrt-header-navbar.php @@ -104,7 +104,14 @@ if (!function_exists('aksrt_get_menu_search')) : $type = (string) ($state['type'] ?? 'post'); $cat_enabled = !empty($state['category_enabled']); $cat_id = (int) ($state['category_id'] ?? 0); - $hots = is_array($ctx['search_hot_keywords'] ?? null) ? $ctx['search_hot_keywords'] : []; + + // zibll remote-box: panel HTML loaded via ajax action menu_search. + $remote_url = add_query_arg( + [ + 'action' => 'aksrt_menu_search', + ], + admin_url('admin-ajax.php') + ); echo ''; echo ''; @@ -116,19 +123,10 @@ if (!function_exists('aksrt_get_menu_search')) : . esc_attr(get_search_query()) . '" placeholder="' . esc_attr($placeholder) . '" autocomplete="off">'; echo ''; - if ($hots) { - echo ''; - echo '' . esc_html__('热门搜索', 'aksrt') . ''; - echo ''; - foreach ($hots as $kw) { - $kw = trim((string) $kw); - if ($kw === '') { - continue; - } - echo '' . esc_html($kw) . ' '; - } - echo ''; - } + // Remote panel mount (zibll remote-box / lazyload-action=ias). + echo ''; + echo ''; + echo ''; echo ''; } endif; diff --git a/src/AKSRT/Admin/NavMenuOptions.php b/src/AKSRT/Admin/NavMenuOptions.php index 283181de..8ea603d4 100644 --- a/src/AKSRT/Admin/NavMenuOptions.php +++ b/src/AKSRT/Admin/NavMenuOptions.php @@ -25,6 +25,7 @@ class NavMenuOptions { if (!file_exists($path)) { return; } + wp_enqueue_media(); wp_enqueue_script( 'aksrt-admin-nav-menu-senior', get_template_directory_uri() . '/assets/js/admin-nav-menu-senior.js', diff --git a/src/AKSRT/Admin/Schema/SchemaPageDisplay.php b/src/AKSRT/Admin/Schema/SchemaPageDisplay.php index 128c727b..f7ad833f 100644 --- a/src/AKSRT/Admin/Schema/SchemaPageDisplay.php +++ b/src/AKSRT/Admin/Schema/SchemaPageDisplay.php @@ -50,7 +50,7 @@ class SchemaPageDisplay { ['key' => 'newposts', 'title' => '发布按钮', 'fields' => [ ['key' => 'header_newposts_enabled', 'label' => '启用发布按钮', 'type' => 'switch', 'default' => true], ['key' => 'header_newposts_text', 'label' => '按钮文案', 'type' => 'input', 'default' => ' 发布'], - ['key' => 'header_newposts_radius', 'label' => '圆角', 'type' => 'number', 'default' => 20, 'min' => 0, 'max' => 30], + ['key' => 'header_newposts_radius', 'label' => '按钮圆角(胶囊)', 'type' => 'switch', 'default' => true], ['key' => 'header_newposts_class', 'label' => '样式类', 'type' => 'input', 'default' => ''], ['key' => 'header_newposts_types', 'label' => '发布类型', 'type' => 'select', 'default' => ['post'], 'options' => [ ['label' => '文章', 'value' => 'post'], diff --git a/src/AKSRT/Core/ScriptsPart2.php b/src/AKSRT/Core/ScriptsPart2.php index 89980dda..bd6a72c8 100644 --- a/src/AKSRT/Core/ScriptsPart2.php +++ b/src/AKSRT/Core/ScriptsPart2.php @@ -221,6 +221,37 @@ trait ScriptsPart2 { ]; } } + + } elseif ($type === 'topic' && post_type_exists('aksrt_topic')) { + $posts = get_posts([ + 'post_type' => 'aksrt_topic', + 'post_status' => 'publish', + 's' => $q, + 'posts_per_page' => 6, + 'no_found_rows' => true, + ]); + foreach ($posts as $p) { + $items[] = [ + 'title' => $p->post_title, + 'url' => get_permalink($p), + 'meta' => get_the_date('', $p), + ]; + } + } elseif ($type === 'product' && post_type_exists('aksrt_product')) { + $posts = get_posts([ + 'post_type' => 'aksrt_product', + 'post_status' => 'publish', + 's' => $q, + 'posts_per_page' => 6, + 'no_found_rows' => true, + ]); + foreach ($posts as $p) { + $items[] = [ + 'title' => $p->post_title, + 'url' => get_permalink($p), + 'meta' => get_the_date('', $p), + ]; + } } elseif ($type === 'tag') { $terms = get_terms([ 'taxonomy' => 'post_tag', diff --git a/src/AKSRT/Settings/FacadeBulk.php b/src/AKSRT/Settings/FacadeBulk.php index 1f128931..5ea51682 100644 --- a/src/AKSRT/Settings/FacadeBulk.php +++ b/src/AKSRT/Settings/FacadeBulk.php @@ -69,13 +69,24 @@ trait FacadeBulk { $types = array_values(array_filter(array_map('sanitize_key', $s['header_newposts_types']))); } + // zibll nav_newposts_radius is bool pill; map true→20px, false→0. Legacy int still accepted once. + $raw_radius = $s['header_newposts_radius'] ?? true; + if (is_bool($raw_radius) || $raw_radius === '0' || $raw_radius === '1' || $raw_radius === 0 || $raw_radius === 1) { + $radius_px = !empty($raw_radius) ? 20 : 0; + $radius_pill = !empty($raw_radius); + } else { + $radius_px = max(0, min(30, (int) $raw_radius)); + $radius_pill = $radius_px >= 16; + } + return [ // Default on like zibll nav_newposts when key unset. - 'enabled' => !isset($s['header_newposts_enabled']) || !empty($s['header_newposts_enabled']), - 'text' => trim((string) ($s['header_newposts_text'] ?? ' 发布')), - 'radius' => max(0, min(30, (int) ($s['header_newposts_radius'] ?? 20))), - 'class' => sanitize_html_class((string) ($s['header_newposts_class'] ?? '')), - 'types' => $types, + 'enabled' => !isset($s['header_newposts_enabled']) || !empty($s['header_newposts_enabled']), + 'text' => trim((string) ($s['header_newposts_text'] ?? ' 发布')), + 'radius' => $radius_px, + 'radius_pill' => $radius_pill, + 'class' => sanitize_html_class((string) ($s['header_newposts_class'] ?? '')), + 'types' => $types, ]; } diff --git a/tools/nav-zibll-acceptance.md b/tools/nav-zibll-acceptance.md index 48c5cdcd..aca617cb 100644 --- a/tools/nav-zibll-acceptance.md +++ b/tools/nav-zibll-acceptance.md @@ -33,3 +33,11 @@ Branch: `worktree-nav-zibll-1to1` ## Deploy notes - Admin `build/` is gitignored — run build on deploy host. - PR: open from branch `worktree-nav-zibll-1to1` against main on Gitea. + + +## Deep align (post 2a11a88) +- [ ] Layout-2 focus loads remote panel (history + hot + posts) +- [ ] Typing shows live suggestions (post/topic/product) +- [ ] Publish radius switch = pill ends +- [ ] Menus senior editor: add card + media library pick image +- [ ] Contract report: tools/nav-zibll-contract-report.txt PASS diff --git a/tools/nav-zibll-contract-report.txt b/tools/nav-zibll-contract-report.txt index 60a53575..41542458 100644 --- a/tools/nav-zibll-contract-report.txt +++ b/tools/nav-zibll-contract-report.txt @@ -1 +1 @@ -PASS all nav zibll source contracts +PASS deep-align menu_search + radius_pill + senior media