Merge pull request 'feat(nav): deep 1:1 zibll search-box + navbar-search + newposts unify' (#259) from worktree-nav-zibll-full-1to1 into main
Reviewed-on: CYL/wordpress-theme-aksrt#259
This commit is contained in:
@@ -36,7 +36,6 @@ export const pageDisplaySchemas = {
|
||||
header_fixed: true,
|
||||
header_search_enabled: true,
|
||||
header_user_menu: true,
|
||||
header_publish_btn: true,
|
||||
header_mobile_drawer: true,
|
||||
header_nav_style: 'default',
|
||||
header_max_width: 1200,
|
||||
@@ -52,7 +51,7 @@ export const pageDisplaySchemas = {
|
||||
header_newposts_enabled: true,
|
||||
header_newposts_text: '<i class="fa fa-pencil"></i> 发布',
|
||||
header_newposts_radius: true,
|
||||
header_newposts_class: '',
|
||||
header_newposts_class: 'jb-blue',
|
||||
header_theme_custom: false,
|
||||
header_theme_bg_custom: '',
|
||||
header_theme_bg: '',
|
||||
@@ -124,10 +123,17 @@ export const pageDisplaySchemas = {
|
||||
title: '发布按钮',
|
||||
icon: 'fas fa-pen',
|
||||
fields: [
|
||||
{ key: 'header_newposts_enabled', label: '启用发布按钮', type: 'switch', default: true, help: '导航栏显示前台发布入口' },
|
||||
{ key: 'header_newposts_enabled', label: '启用发布按钮', type: 'switch', default: true, help: '顶部导航显示发布入口(对齐 zibll nav_newposts)' },
|
||||
{ key: 'header_newposts_text', label: '按钮文案', type: 'input', default: '<i class="fa fa-pencil"></i> 发布', 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_class', label: '按钮颜色', type: 'select', default: 'jb-blue', options: [
|
||||
{ label: '蓝色', value: 'jb-blue' },
|
||||
{ label: '红色', value: 'jb-red' },
|
||||
{ label: '绿色', value: 'jb-green' },
|
||||
{ label: '黄色', value: 'jb-yellow' },
|
||||
{ label: '紫色', value: 'jb-purple' },
|
||||
{ label: '粉色', value: 'jb-pink' },
|
||||
], dependsOn: { key: 'header_newposts_enabled', value: true } },
|
||||
{ key: 'header_newposts_types', label: '发布类型', type: 'select', multiple: true, default: ['post'], options: [
|
||||
{ label: '文章', value: 'post' },
|
||||
{ label: '帖子', value: 'topic' },
|
||||
@@ -161,7 +167,6 @@ export const pageDisplaySchemas = {
|
||||
fields: [
|
||||
{ key: 'header_search_enabled', label: '搜索入口', type: 'switch', default: true },
|
||||
{ key: 'header_user_menu', label: '用户菜单', type: 'switch', default: true },
|
||||
{ key: 'header_publish_btn', label: '发布按钮', type: 'switch', default: true, help: '管理员可见的前台发布入口' },
|
||||
{ key: 'header_mobile_drawer', label: '移动端抽屉导航', type: 'switch', default: true },
|
||||
],
|
||||
},
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
@import url("nav/zib-mobile-navbar.css");
|
||||
@import url("nav/zib-senior-submenu.css");
|
||||
@import url("nav/zib-utilities.css");
|
||||
@import url("nav/zib-search-box.css");
|
||||
@import url("nav/header-menu-buttons.css");
|
||||
@import url("nav/header-userbox.css");
|
||||
@import url("nav/dark-mode-submenu.css");
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
/* zibll search-box / menu_search panel parity */
|
||||
|
||||
/* Layout-2 focus dropdown */
|
||||
.navbar-collapse .form-group.relative.dropdown {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.navbar-collapse .search-input ~ .dropdown-menu,
|
||||
.navbar-collapse .form-group .dropdown-menu.hover-show-con {
|
||||
display: none;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 100%;
|
||||
z-index: 1002;
|
||||
min-width: 320px;
|
||||
width: max(320px, 100%);
|
||||
max-width: 460px;
|
||||
margin-top: 10px;
|
||||
padding: 10px;
|
||||
background: var(--main-bg-color, #fff);
|
||||
border-radius: var(--main-radius, 8px);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.navbar-form.hover-show:hover .dropdown-menu.hover-show-con,
|
||||
.navbar-form.hover-show:focus-within .dropdown-menu.hover-show-con,
|
||||
.navbar-collapse .form-group:focus-within .dropdown-menu.hover-show-con,
|
||||
.navbar-collapse .dropdown-menu.hover-show-con.is-open {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Search box body */
|
||||
.search-input .search-keywords {
|
||||
padding: 6px 10px 2px;
|
||||
}
|
||||
.search-input .search-keywords > p {
|
||||
margin: 0 0 6px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.search-input .search-keywords .but,
|
||||
.search-input .search-keywords a.but {
|
||||
display: inline-block;
|
||||
margin: 0 6px 6px 0;
|
||||
padding: 2px 10px;
|
||||
font-size: 0.85em;
|
||||
border-radius: 20px;
|
||||
background: var(--main-shadow, rgba(0, 0, 0, 0.05));
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
.search-input .search-keywords .but:hover {
|
||||
color: var(--focus-color, #2997f7);
|
||||
}
|
||||
|
||||
.search-input .history-search .trash-history-search {
|
||||
text-decoration: none;
|
||||
opacity: 0.7;
|
||||
}
|
||||
.search-input .history-search .trash-history-search:hover {
|
||||
opacity: 1;
|
||||
color: var(--focus-color, #2997f7);
|
||||
}
|
||||
|
||||
/* Hot posts swiper row */
|
||||
.search-input .relates-thumb {
|
||||
overflow: hidden;
|
||||
}
|
||||
.search-input .relates-thumb .swiper-container,
|
||||
.search-input .relates-thumb .swiper-scroll {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
.search-input .relates-thumb .swiper-wrapper {
|
||||
display: flex;
|
||||
overflow-x: auto;
|
||||
scroll-snap-type: x mandatory;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
gap: 0;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
.search-input .relates-thumb .swiper-wrapper::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
.search-input .relates-thumb .swiper-slide {
|
||||
flex: 0 0 auto;
|
||||
scroll-snap-align: start;
|
||||
}
|
||||
.search-input .relates-thumb .swiper-button-prev,
|
||||
.search-input .relates-thumb .swiper-button-next {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Full navbar-search slide (layout 1/3) */
|
||||
.navbar-search {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
}
|
||||
.navbar-search .container {
|
||||
max-width: var(--nav-max-width, 1200px);
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
padding: 10px 15px 20px;
|
||||
}
|
||||
.navbar-search .navbar-search-close,
|
||||
.navbar-search > .container > .close {
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
top: 12px;
|
||||
z-index: 2;
|
||||
background: none;
|
||||
border: 0;
|
||||
font-size: 1.25rem;
|
||||
color: inherit;
|
||||
cursor: pointer;
|
||||
opacity: 0.7;
|
||||
}
|
||||
.navbar-search .navbar-search-close:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Line form (full search box) */
|
||||
.search-input .line-form {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
|
||||
position: relative;
|
||||
}
|
||||
.search-input .search-input-text {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
min-width: 0;
|
||||
}
|
||||
.search-input .line-form-input {
|
||||
width: 100%;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
padding: 12px 40px 12px 4px;
|
||||
font-size: 1.05em;
|
||||
outline: none;
|
||||
color: inherit;
|
||||
}
|
||||
.search-input .scale-placeholder {
|
||||
position: absolute;
|
||||
left: 4px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
pointer-events: none;
|
||||
opacity: 0.45;
|
||||
transition: 0.2s;
|
||||
}
|
||||
.search-input .scale-placeholder.is-focus,
|
||||
.search-input .line-form-input:focus + .line-form-line + .scale-placeholder,
|
||||
.search-input .line-form-input:not([value=""]) ~ .scale-placeholder {
|
||||
opacity: 0;
|
||||
}
|
||||
.search-input .option-dropdown {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-right: 8px;
|
||||
}
|
||||
.search-input .search-type-but-average .but {
|
||||
margin: 0 4px;
|
||||
}
|
||||
.search-input .search-type-but-average .but.active {
|
||||
color: #fff;
|
||||
background: var(--focus-color, #2997f7);
|
||||
}
|
||||
|
||||
/* Live suggest (extension) */
|
||||
.navbar-inline-search-suggest__item,
|
||||
.aksrt-menu-search-suggest a {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
padding: 6px 4px;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
.navbar-inline-search-suggest__item:hover {
|
||||
color: var(--focus-color, #2997f7);
|
||||
}
|
||||
|
||||
body.theme-dark .navbar-collapse .form-group .dropdown-menu.hover-show-con,
|
||||
html.dark .navbar-collapse .form-group .dropdown-menu.hover-show-con,
|
||||
body.dark-theme .navbar-collapse .form-group .dropdown-menu.hover-show-con {
|
||||
background: var(--main-bg-color, #1e1e1e);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
@@ -291,19 +291,20 @@
|
||||
|
||||
document.querySelectorAll(".main-search-btn, .nav-search-toggle, [data-aksrt-open-search]").forEach(function (btn) {
|
||||
btn.addEventListener("click", function (e) {
|
||||
// Top bar uses zibll .navbar-search slide — skip tabbar overlay.
|
||||
var tgt = btn.getAttribute("data-target") || "";
|
||||
if (tgt.indexOf("navbar-search") !== -1 || tgt.indexOf("main-search") !== -1) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
setOpen(true);
|
||||
});
|
||||
});
|
||||
|
||||
// Zibll-compatible data-toggle-class for .navbar-search
|
||||
document.addEventListener("click", function (e) {
|
||||
var toggle = e.target.closest('[data-toggle-class][data-target=".navbar-search"], [data-toggle-class][data-target=".main-search"]');
|
||||
if (!toggle) return;
|
||||
e.preventDefault();
|
||||
var isOpen = mobileOverlay && !mobileOverlay.hasAttribute("hidden");
|
||||
setOpen(!isOpen);
|
||||
});
|
||||
// Top-nav .navbar-search is toggled by aksrt-runtime (data-toggle-class="show").
|
||||
// Do NOT redirect those clicks into the footer tabbar overlay.
|
||||
// Only open tabbar overlay for explicit main-search-btn without .navbar-search target
|
||||
// (handled above via .main-search-btn listeners).
|
||||
|
||||
if (historyClear) {
|
||||
historyClear.addEventListener("click", function () {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/**
|
||||
* Layout-2 navbar search — zibll remote-box + live suggestions.
|
||||
* Loads aksrt_menu_search panel (history/hot/posts), then suggests on input.
|
||||
* Layout-2 navbar search — zibll remote-box + search-input panel.
|
||||
* Loads menu_search panel (.dropdown-menu.hover-show-con > .search-input),
|
||||
* fills guest history from localStorage, live suggestions optional.
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
@@ -40,6 +41,24 @@
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
function keywordChips(list) {
|
||||
return (list || [])
|
||||
.map(function (kw) {
|
||||
return (
|
||||
'<a class="but jb-sm" data-search-keyword="' +
|
||||
encodeURIComponent(kw) +
|
||||
'" href="' +
|
||||
(window.location.origin || "") +
|
||||
"/?s=" +
|
||||
encodeURIComponent(kw) +
|
||||
'">' +
|
||||
kw +
|
||||
"</a> "
|
||||
);
|
||||
})
|
||||
.join("");
|
||||
}
|
||||
|
||||
function loadRemote(box) {
|
||||
if (!box || box.getAttribute("data-loaded") === "1") return;
|
||||
var url = box.getAttribute("remote-box") || box.getAttribute("data-url");
|
||||
@@ -58,57 +77,51 @@
|
||||
box.innerHTML = "";
|
||||
return;
|
||||
}
|
||||
var parent = box.parentNode;
|
||||
box.outerHTML = html;
|
||||
var form = document.querySelector('form[data-aksrt-search-form="inline"]');
|
||||
var form = parent ? parent.closest("form") : document.querySelector('form[data-aksrt-search-form="inline"]');
|
||||
if (form) enhancePanel(form);
|
||||
initSwiperScroll(form || document);
|
||||
})
|
||||
.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");
|
||||
if (!group || !input) return;
|
||||
function initSwiperScroll(root) {
|
||||
if (!root || typeof window.Swiper === "undefined") return;
|
||||
root.querySelectorAll(".relates-thumb .swiper-container:not(.swiper-initialized)").forEach(function (el) {
|
||||
try {
|
||||
new window.Swiper(el, {
|
||||
slidesPerView: "auto",
|
||||
freeMode: true,
|
||||
navigation: {
|
||||
nextEl: el.querySelector(".swiper-button-next"),
|
||||
prevEl: el.querySelector(".swiper-button-prev"),
|
||||
},
|
||||
});
|
||||
} catch (e) {}
|
||||
});
|
||||
}
|
||||
|
||||
// Merge guest local history into panel list.
|
||||
var histList = form.querySelector(".aksrt-menu-search-history__list");
|
||||
function enhancePanel(form) {
|
||||
if (!form || form._aksrtMenuSearchEnhanced) return;
|
||||
form._aksrtMenuSearchEnhanced = 1;
|
||||
|
||||
var input = form.querySelector(".search-input, input[name='s']");
|
||||
var histList = form.querySelector(".history-search-list, .history-search > div:last-child");
|
||||
|
||||
// Guest local history → panel.
|
||||
if (histList && !(window.aksrtData && aksrtData.isLoggedIn)) {
|
||||
var local = readLocalHistory();
|
||||
if (local.length) {
|
||||
histList.innerHTML = local
|
||||
.map(function (kw) {
|
||||
return (
|
||||
'<a class="but jb-sm" href="' +
|
||||
(window.location.origin || "") +
|
||||
"/?s=" +
|
||||
encodeURIComponent(kw) +
|
||||
'">' +
|
||||
kw +
|
||||
"</a> "
|
||||
);
|
||||
})
|
||||
.join("");
|
||||
histList.innerHTML = keywordChips(local);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
form.querySelectorAll("[data-aksrt-menu-search-type]").forEach(function (chip) {
|
||||
chip.addEventListener("click", function (e) {
|
||||
e.preventDefault();
|
||||
var v = chip.getAttribute("data-aksrt-menu-search-type") || "post";
|
||||
var tin = form.querySelector('input[name="aksrt_search_type"]');
|
||||
if (tin) tin.value = v;
|
||||
form.querySelectorAll("[data-aksrt-menu-search-type]").forEach(function (c) {
|
||||
c.classList.toggle("active", c === chip);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
var clearBtn = form.querySelector("[data-aksrt-clear-menu-history]");
|
||||
if (clearBtn && !clearBtn._bound) {
|
||||
// Clear history (zibll .trash-history-search).
|
||||
form.querySelectorAll(".trash-history-search, [data-aksrt-clear-menu-history]").forEach(function (clearBtn) {
|
||||
if (clearBtn._bound) return;
|
||||
clearBtn._bound = 1;
|
||||
clearBtn.addEventListener("click", function (e) {
|
||||
e.preventDefault();
|
||||
@@ -118,14 +131,30 @@ var clearBtn = form.querySelector("[data-aksrt-clear-menu-history]");
|
||||
'<span class="muted-3-color em09" data-empty="1">暂无历史</span>';
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Type chips inside panel (if any).
|
||||
form.querySelectorAll("[data-for='type'], [data-aksrt-menu-search-type]").forEach(function (chip) {
|
||||
chip.addEventListener("click", function (e) {
|
||||
e.preventDefault();
|
||||
var v =
|
||||
chip.getAttribute("data-value") ||
|
||||
chip.getAttribute("data-aksrt-menu-search-type") ||
|
||||
"post";
|
||||
var tin = form.querySelector('input[name="aksrt_search_type"], input[name="type"]');
|
||||
if (tin) tin.value = v;
|
||||
form.querySelectorAll("[data-for='type'], [data-aksrt-menu-search-type]").forEach(function (c) {
|
||||
c.classList.toggle("active", c === chip);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
var suggestMount = form.querySelector("[data-aksrt-menu-suggest]");
|
||||
var timer = null;
|
||||
var searchConfig = (window.aksrtData && aksrtData.search) || {};
|
||||
|
||||
function typeValue() {
|
||||
var t = form.querySelector('input[name="aksrt_search_type"]');
|
||||
var t = form.querySelector('input[name="aksrt_search_type"], input[name="type"]');
|
||||
return (t && t.value) || searchConfig.defaultType || "post";
|
||||
}
|
||||
|
||||
@@ -153,14 +182,14 @@ var clearBtn = form.querySelector("[data-aksrt-clear-menu-history]");
|
||||
var html =
|
||||
'<div class="muted-2-color em09 mb6">' +
|
||||
(searchConfig.suggestTitle || "搜索建议") +
|
||||
"</div><div class=\"navbar-inline-search-suggest\">";
|
||||
'</div><div class="navbar-inline-search-suggest">';
|
||||
items.forEach(function (it) {
|
||||
html +=
|
||||
'<a class="navbar-inline-search-suggest__item" href="' +
|
||||
(it.url || "#") +
|
||||
'"><span class="title">' +
|
||||
(it.title || "") +
|
||||
'</span>' +
|
||||
"</span>" +
|
||||
(it.meta
|
||||
? '<span class="meta muted-2-color em09">' + it.meta + "</span>"
|
||||
: "") +
|
||||
@@ -181,7 +210,7 @@ var clearBtn = form.querySelector("[data-aksrt-clear-menu-history]");
|
||||
);
|
||||
}
|
||||
|
||||
if (!input._aksrtMenuSearchBound) {
|
||||
if (input && !input._aksrtMenuSearchBound) {
|
||||
input._aksrtMenuSearchBound = 1;
|
||||
input.addEventListener("input", function () {
|
||||
var q = (input.value || "").trim();
|
||||
@@ -191,9 +220,9 @@ var clearBtn = form.querySelector("[data-aksrt-clear-menu-history]");
|
||||
}, 180);
|
||||
});
|
||||
input.addEventListener("focus", function () {
|
||||
var remote = form.querySelector("[data-aksrt-menu-search-remote]");
|
||||
var remote = form.querySelector("[remote-box]");
|
||||
if (remote) loadRemote(remote);
|
||||
var p = form.querySelector(".navbar-inline-search-panel");
|
||||
var p = form.querySelector(".dropdown-menu.hover-show-con");
|
||||
if (p) {
|
||||
p.classList.add("is-open");
|
||||
p.style.display = "block";
|
||||
@@ -214,9 +243,9 @@ var clearBtn = form.querySelector("[data-aksrt-clear-menu-history]");
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
document.querySelectorAll("[data-aksrt-menu-search-remote]").forEach(function (box) {
|
||||
// Prefetch on idle / first hover of form.
|
||||
/** Generic remote-box / lazyload-action=ias (zibll-compatible). */
|
||||
function bindRemoteBoxes(root) {
|
||||
(root || document).querySelectorAll("[remote-box]").forEach(function (box) {
|
||||
var form = box.closest("form");
|
||||
if (form) {
|
||||
form.addEventListener(
|
||||
@@ -226,8 +255,14 @@ var clearBtn = form.querySelector("[data-aksrt-clear-menu-history]");
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
form.addEventListener(
|
||||
"focusin",
|
||||
function () {
|
||||
loadRemote(box);
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
}
|
||||
// Also load when lazyload-action ias would fire — simple viewport/idle.
|
||||
if ("requestIdleCallback" in window) {
|
||||
requestIdleCallback(function () {
|
||||
loadRemote(box);
|
||||
@@ -238,9 +273,53 @@ var clearBtn = form.querySelector("[data-aksrt-clear-menu-history]");
|
||||
}, 600);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function bindNavbarSearchSlide() {
|
||||
// Ensure .navbar-search show toggle clears aria-hidden / focuses input.
|
||||
document.addEventListener("click", function (e) {
|
||||
var toggle = e.target.closest
|
||||
? e.target.closest('[data-toggle-class="show"][data-target=".navbar-search"]')
|
||||
: null;
|
||||
if (!toggle) return;
|
||||
// Let runtime toggle class; after tick sync aria + focus.
|
||||
setTimeout(function () {
|
||||
var panel = document.querySelector(".navbar-search");
|
||||
if (!panel) return;
|
||||
var open = panel.classList.contains("show");
|
||||
panel.setAttribute("aria-hidden", open ? "false" : "true");
|
||||
if (open) {
|
||||
var input = panel.querySelector('input[name="s"]');
|
||||
if (input) input.focus();
|
||||
initSwiperScroll(panel);
|
||||
}
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
bindRemoteBoxes(document);
|
||||
bindNavbarSearchSlide();
|
||||
var form = document.querySelector('form[data-aksrt-search-form="inline"]');
|
||||
if (form) enhancePanel(form);
|
||||
// Full navbar-search box history for guests.
|
||||
document.querySelectorAll(".navbar-search .history-search-list").forEach(function (histList) {
|
||||
if (window.aksrtData && aksrtData.isLoggedIn) return;
|
||||
var local = readLocalHistory();
|
||||
if (local.length) histList.innerHTML = keywordChips(local);
|
||||
});
|
||||
document.querySelectorAll(".navbar-search .trash-history-search").forEach(function (btn) {
|
||||
if (btn._bound) return;
|
||||
btn._bound = 1;
|
||||
btn.addEventListener("click", function (e) {
|
||||
e.preventDefault();
|
||||
writeLocalHistory([]);
|
||||
document.querySelectorAll(".navbar-search .history-search-list").forEach(function (list) {
|
||||
list.innerHTML = '<span class="muted-3-color em09" data-empty="1">暂无历史</span>';
|
||||
});
|
||||
});
|
||||
});
|
||||
initSwiperScroll(document);
|
||||
}
|
||||
|
||||
if (window.AksrtFrontend && typeof window.AksrtFrontend.register === "function") {
|
||||
|
||||
@@ -45,6 +45,8 @@ require_once AKSRT_DIR . '/inc/helpers/aksrt-credits.php';
|
||||
require_once AKSRT_DIR . '/inc/helpers/aksrt-null.php';
|
||||
require_once AKSRT_DIR . '/inc/helpers/aksrt-ajax-list.php';
|
||||
require_once AKSRT_DIR . '/inc/helpers/aksrt-links.php';
|
||||
require_once AKSRT_DIR . '/inc/helpers/search/aksrt-search-posts.php';
|
||||
require_once AKSRT_DIR . '/inc/helpers/search/aksrt-search-box.php';
|
||||
require_once AKSRT_DIR . '/inc/helpers/aksrt-header-userbox.php';
|
||||
require_once AKSRT_DIR . '/inc/helpers/aksrt-header-menu-buttons.php';
|
||||
require_once AKSRT_DIR . '/inc/helpers/header/aksrt-header-render.php';
|
||||
|
||||
@@ -14,12 +14,9 @@ if (!function_exists('aksrt_get_header_newposts_config')) :
|
||||
function aksrt_get_header_newposts_config(): array {
|
||||
$cfg = class_exists('\AKSRT\Settings\Settings')
|
||||
? \AKSRT\Settings\Settings::get_header_newposts_config()
|
||||
: ['enabled' => true, 'text' => __('发布', 'aksrt'), 'radius' => 20, 'class' => '', 'types' => []];
|
||||
$nav = class_exists('\AKSRT\Settings\Settings')
|
||||
? \AKSRT\Settings\Settings::get_header_nav_settings()
|
||||
: ['publish_btn' => true];
|
||||
// Single source: newposts enabled AND header publish switch.
|
||||
$cfg['enabled'] = !empty($cfg['enabled']) && !empty($nav['publish_btn']);
|
||||
: ['enabled' => true, 'text' => __('发布', 'aksrt'), 'radius' => 20, 'class' => 'jb-blue', 'types' => []];
|
||||
// Single source: header_newposts_enabled (zibll nav_newposts).
|
||||
// FacadeBulk maps publish_btn to the same setting.
|
||||
|
||||
$types = is_array($cfg['types'] ?? null) ? $cfg['types'] : [];
|
||||
if (!$types) {
|
||||
@@ -36,6 +33,9 @@ if (!function_exists('aksrt_get_header_newposts_config')) :
|
||||
}
|
||||
}
|
||||
$cfg['types'] = $types;
|
||||
if (empty($cfg['class'])) {
|
||||
$cfg['class'] = 'jb-blue';
|
||||
}
|
||||
return $cfg;
|
||||
}
|
||||
endif;
|
||||
@@ -60,7 +60,6 @@ if (!function_exists('aksrt_get_new_add_actions')) :
|
||||
'type' => 'post',
|
||||
'url' => $url,
|
||||
'label' => __('写文章', 'aksrt'),
|
||||
// FA5 free solid names (avoid FA4 aliases like file-text-o).
|
||||
'icon' => 'fas fa-file-alt',
|
||||
];
|
||||
} elseif ($type === 'topic') {
|
||||
@@ -104,28 +103,24 @@ if (!function_exists('aksrt_normalize_header_cta_label')) :
|
||||
return '<i class="' . esc_attr($fallback_icon) . '" aria-hidden="true"></i> ' . esc_html__('发布', 'aksrt');
|
||||
}
|
||||
|
||||
// Common FA4 → FA5 renames used in admin defaults.
|
||||
$replacements = [
|
||||
'fa-file-text-o' => 'fa-file-alt',
|
||||
'fa-file-text' => 'fa-file-alt',
|
||||
'fa-pencil-square-o' => 'fa-edit',
|
||||
'fa-pencil' => 'fa-pen',
|
||||
'fa-comments-o' => 'fa-comments',
|
||||
'fa-clock-o' => 'fa-clock',
|
||||
'fa-calendar-check-o'=> 'fa-calendar-check',
|
||||
'fa-diamond' => 'fa-gem',
|
||||
'fa-file-text-o' => 'fa-file-alt',
|
||||
'fa-file-text' => 'fa-file-alt',
|
||||
'fa-pencil-square-o' => 'fa-edit',
|
||||
'fa-pencil' => 'fa-pen',
|
||||
'fa-comments-o' => 'fa-comments',
|
||||
'fa-clock-o' => 'fa-clock',
|
||||
'fa-calendar-check-o' => 'fa-calendar-check',
|
||||
'fa-diamond' => 'fa-gem',
|
||||
];
|
||||
$label = strtr($label, $replacements);
|
||||
|
||||
// Ensure icon uses fas (FA5 solid) when only bare "fa " is present.
|
||||
$label = preg_replace('/\bclass=(["\'])fa\s+/', 'class=$1fas ', $label) ?? $label;
|
||||
$label = preg_replace('/<i\s+class=(["\'])(?!fas\b|far\b|fab\b)/', '<i class=$1fas ', $label) ?? $label;
|
||||
|
||||
// If label is plain text without icon markup, prefix default icon.
|
||||
if (stripos($label, '<i') === false) {
|
||||
$label = '<i class="' . esc_attr($fallback_icon) . '" aria-hidden="true"></i> <span class="navbar-cta-text">' . esc_html(wp_strip_all_tags($label)) . '</span>';
|
||||
} else {
|
||||
// Wrap remaining text nodes for flex alignment without raw text siblings.
|
||||
$label = preg_replace(
|
||||
'/(<\/i>)\s*([^<].*)$/u',
|
||||
'$1 <span class="navbar-cta-text">$2</span>',
|
||||
@@ -152,8 +147,8 @@ if (!function_exists('aksrt_render_new_add_btns')) :
|
||||
$label = __('发布', 'aksrt');
|
||||
}
|
||||
$label_html = aksrt_normalize_header_cta_label((string) $label, 'fas fa-pen');
|
||||
// Keep CTA paint classes (e.g. btn-primary) off multi-type wrapper so the
|
||||
// dropdown plate is not filled pink/primary; apply them on the toggle only.
|
||||
|
||||
// Split paint classes vs wrapper tokens.
|
||||
$class_tokens = preg_split('/\s+/', trim($class), -1, PREG_SPLIT_NO_EMPTY) ?: [];
|
||||
$cta_tokens = [];
|
||||
$wrap_tokens = ['newadd-btns'];
|
||||
@@ -161,35 +156,37 @@ if (!function_exists('aksrt_render_new_add_btns')) :
|
||||
if ($token === 'newadd-btns') {
|
||||
continue;
|
||||
}
|
||||
if ($token === 'btn-primary' || $token === 'but' || $token === 'navbar-cta') {
|
||||
if ($token === 'btn-primary' || $token === 'but' || $token === 'navbar-cta' || str_starts_with($token, 'jb-')) {
|
||||
$cta_tokens[] = $token;
|
||||
continue;
|
||||
}
|
||||
$wrap_tokens[] = $token;
|
||||
}
|
||||
if (!in_array('btn-primary', $cta_tokens, true)) {
|
||||
$cta_tokens[] = 'btn-primary';
|
||||
if (!$cta_tokens) {
|
||||
$cta_tokens[] = 'jb-blue';
|
||||
}
|
||||
if (!in_array('but', $cta_tokens, true)) {
|
||||
$cta_tokens[] = 'but';
|
||||
}
|
||||
$cta_class = trim(implode(' ', array_unique($cta_tokens)));
|
||||
|
||||
if (count($actions) === 1) {
|
||||
$a = $actions[0];
|
||||
// Prefer configured label; icon already embedded after normalize.
|
||||
return '<a rel="nofollow" class="' . esc_attr(trim(implode(' ', $wrap_tokens) . ' ' . $cta_class . ' but navbar-cta')) . '" href="' . esc_url($a['url']) . '">'
|
||||
return '<a rel="nofollow" class="' . esc_attr(trim(implode(' ', $wrap_tokens) . ' ' . $cta_class . ' navbar-cta')) . '" href="' . esc_url($a['url']) . '">'
|
||||
. $label_html
|
||||
. '</a>';
|
||||
}
|
||||
|
||||
// data-aksrt-newadd: JS portals the menu to body so chip width cannot track menu.
|
||||
$html = '<span class="' . esc_attr(trim(implode(' ', $wrap_tokens) . ' hover-show')) . '" data-aksrt-newadd="1">';
|
||||
$html .= '<button type="button" class="' . esc_attr(trim('but newadd-btns__toggle navbar-cta ' . $cta_class)) . '" aria-haspopup="menu" aria-expanded="false">'
|
||||
. $label_html
|
||||
. ' <i class="fas fa-caret-down" aria-hidden="true"></i></button>';
|
||||
$html .= '<div class="hover-show-con drop-newadd" role="menu" hidden>';
|
||||
// zibll: span.newadd-btns.hover-show > label + .hover-show-con.dropdown-menu.drop-newadd
|
||||
// data-aksrt-newadd: JS may portal menu to body so chip width cannot track menu.
|
||||
$html = '<span class="' . esc_attr(trim(implode(' ', $wrap_tokens) . ' hover-show ' . $cta_class)) . '" data-aksrt-newadd="1">';
|
||||
$html .= '<span class="newadd-btns__toggle navbar-cta">' . $label_html
|
||||
. ' <i class="fas fa-caret-down" aria-hidden="true"></i></span>';
|
||||
$html .= '<div class="hover-show-con dropdown-menu drop-newadd" role="menu">';
|
||||
foreach ($actions as $a) {
|
||||
$html .= '<a rel="nofollow" class="newadd-btns__item" role="menuitem" href="' . esc_url($a['url']) . '">';
|
||||
$html .= '<a rel="nofollow" class="btn-newadd newadd-btns__item" role="menuitem" href="' . esc_url($a['url']) . '">';
|
||||
$html .= '<i class="' . esc_attr($a['icon']) . '" aria-hidden="true"></i> '
|
||||
. '<span>' . esc_html($a['label']) . '</span>';
|
||||
. '<text>' . esc_html($a['label']) . '</text>';
|
||||
$html .= '</a>';
|
||||
}
|
||||
$html .= '</div></span>';
|
||||
@@ -202,22 +199,26 @@ if (!function_exists('aksrt_render_header_menu_buttons')) :
|
||||
* Publish + optional VIP open button for header CTA.
|
||||
*/
|
||||
function aksrt_render_header_menu_buttons(): string {
|
||||
$cfg = aksrt_get_header_newposts_config();
|
||||
$cfg = aksrt_get_header_newposts_config();
|
||||
$html = '';
|
||||
if (!empty($cfg['enabled'])) {
|
||||
$class = 'btn-primary navbar-newposts';
|
||||
if (!empty($cfg['class'])) {
|
||||
$class .= ' ' . $cfg['class'];
|
||||
// zibll default: but nowave jb-blue (+ radius).
|
||||
$class = 'but nowave navbar-newposts';
|
||||
$skin = trim((string) ($cfg['class'] ?? ''));
|
||||
if ($skin === '') {
|
||||
$skin = 'jb-blue';
|
||||
}
|
||||
$class .= ' ' . $skin;
|
||||
$radius = (int) ($cfg['radius'] ?? 20);
|
||||
$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);
|
||||
$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);
|
||||
if ($btn !== '') {
|
||||
$html .= '<div class="navbar-form navbar-right navbar-but"' . $radius_attr . '>' . $btn . '</div>';
|
||||
}
|
||||
@@ -227,7 +228,7 @@ if (!function_exists('aksrt_render_header_menu_buttons')) :
|
||||
$user_id = get_current_user_id();
|
||||
$show_vip = false;
|
||||
if (class_exists('\AKSRT\Settings\Settings')) {
|
||||
$vs = \AKSRT\Settings\Settings::get_payment_vip_settings();
|
||||
$vs = \AKSRT\Settings\Settings::get_payment_vip_settings();
|
||||
$show_vip = !empty($vs['enabled']) && !empty(\AKSRT\Settings\Settings::get_header_nav_settings()['nav_pay_vip']);
|
||||
}
|
||||
if ($show_vip) {
|
||||
@@ -236,7 +237,7 @@ if (!function_exists('aksrt_render_header_menu_buttons')) :
|
||||
$is_vip = (int) aksrt_get_user_vip_level($user_id) > 0;
|
||||
}
|
||||
if (!$is_vip) {
|
||||
$cls = $user_id > 0 ? 'pay-vip' : 'signin-loader';
|
||||
$cls = $user_id > 0 ? 'pay-vip' : 'signin-loader';
|
||||
$hover = '';
|
||||
if (class_exists('\AKSRT\Content\VipService')) {
|
||||
$svc = \AKSRT\Content\VipService::get_instance();
|
||||
@@ -247,7 +248,7 @@ if (!function_exists('aksrt_render_header_menu_buttons')) :
|
||||
}
|
||||
}
|
||||
}
|
||||
$html .= '<div class="navbar-form navbar-right navbar-vip">';
|
||||
$html .= '<div class="navbar-form navbar-right navbar-vip">';
|
||||
// zibll: span.hover-show wraps button + .hover-show-con.sub-vip-card
|
||||
$html .= '<span class="hover-show inline-block navbar-vip-hover">';
|
||||
$html .= '<a class="but jb-red radius payvip-icon navbar-cta ' . esc_attr($cls) . '" href="javascript:;"'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* Layout-2 menu search remote panel (zibll menu_search parity subset).
|
||||
* Layout-2 menu search remote panel (zibll menu_search / zib_get_search_box).
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
@@ -20,21 +20,10 @@ if (!function_exists('aksrt_ajax_menu_search')) :
|
||||
}
|
||||
}
|
||||
|
||||
$html = aksrt_get_menu_search_panel_html();
|
||||
if ($html === '') {
|
||||
if (!function_exists('aksrt_get_search_box')) {
|
||||
wp_die('0');
|
||||
}
|
||||
|
||||
echo '<div class="dropdown-menu hover-show-con navbar-inline-search-panel is-open">' . $html . '</div>'; // 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;
|
||||
@@ -50,100 +39,38 @@ if (!function_exists('aksrt_get_menu_search_panel_html')) :
|
||||
: !empty(\AKSRT\Settings\Settings::get_value('search_posts', true));
|
||||
}
|
||||
|
||||
$out = '';
|
||||
$search = aksrt_get_search_box([
|
||||
'show_form' => false,
|
||||
'show_keywords' => $show_keywords,
|
||||
'show_history' => $show_history,
|
||||
'show_posts' => $show_posts,
|
||||
]);
|
||||
|
||||
// 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 .= '<div class="aksrt-menu-search-history" data-aksrt-menu-history="1">';
|
||||
$out .= '<div class="flex jsb ac mb6"><span class="muted-2-color em09">' . esc_html__('搜索历史', 'aksrt') . '</span>';
|
||||
$out .= '<a href="javascript:;" class="muted-2-color em09" data-aksrt-clear-menu-history="1">' . esc_html__('清空', 'aksrt') . '</a></div>';
|
||||
$out .= '<div class="aksrt-menu-search-history__list">';
|
||||
if ($hist) {
|
||||
foreach ($hist as $kw) {
|
||||
$out .= '<a class="but jb-sm" href="' . esc_url(home_url('/?s=' . rawurlencode($kw))) . '">' . esc_html($kw) . '</a> ';
|
||||
}
|
||||
} else {
|
||||
$out .= '<span class="muted-3-color em09" data-empty="1">' . esc_html__('暂无历史', 'aksrt') . '</span>';
|
||||
}
|
||||
$out .= '</div></div>';
|
||||
if ($search === '' || $search === null) {
|
||||
wp_die('0');
|
||||
}
|
||||
|
||||
// Search type chips (when multi-type search enabled).
|
||||
$types = [];
|
||||
if (function_exists('aksrt_get_search_type_options')) {
|
||||
$types = aksrt_get_search_type_options();
|
||||
}
|
||||
if (is_array($types) && count($types) > 1) {
|
||||
$out .= '<div class="aksrt-menu-search-types flex jc mb10">';
|
||||
foreach ($types as $k => $label) {
|
||||
$out .= '<a href="javascript:;" class="but" data-aksrt-menu-search-type="' . esc_attr((string) $k) . '">' . esc_html((string) $label) . '</a>';
|
||||
}
|
||||
$out .= '</div>';
|
||||
}
|
||||
// zibll contract: outer dropdown + inner .search-input.
|
||||
echo '<div class="dropdown-menu hover-show-con">' . $search . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
wp_die();
|
||||
}
|
||||
endif;
|
||||
|
||||
// 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 .= '<div class="aksrt-menu-search-hots mt10">';
|
||||
$out .= '<div class="muted-2-color em09 mb6">' . esc_html($title) . '</div>';
|
||||
$out .= '<div class="navbar-inline-search-hots">';
|
||||
foreach ($hots as $kw) {
|
||||
$kw = trim((string) $kw);
|
||||
if ($kw === '') {
|
||||
continue;
|
||||
}
|
||||
$out .= '<a class="but jb-sm" href="' . esc_url(home_url('/?s=' . rawurlencode($kw))) . '">' . esc_html($kw) . '</a> ';
|
||||
}
|
||||
$out .= '</div></div>';
|
||||
}
|
||||
// Panel builder retained as thin alias for any external callers.
|
||||
if (!function_exists('aksrt_get_menu_search_panel_html')) :
|
||||
/**
|
||||
* @return string Inner HTML (without dropdown wrapper).
|
||||
*/
|
||||
function aksrt_get_menu_search_panel_html(): string {
|
||||
if (!function_exists('aksrt_get_search_box')) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// 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 .= '<div class="aksrt-menu-search-posts mt10">';
|
||||
$out .= '<div class="muted-2-color em09 mb6">' . esc_html__('推荐内容', 'aksrt') . '</div>';
|
||||
$out .= '<div class="aksrt-menu-search-posts__list">';
|
||||
foreach ($posts as $p) {
|
||||
$out .= '<a class="aksrt-menu-search-posts__item" href="' . esc_url(get_permalink($p)) . '">';
|
||||
$out .= '<span class="title text-ellipsis">' . esc_html(get_the_title($p)) . '</span>';
|
||||
$out .= '<span class="meta muted-3-color em09">' . esc_html(get_the_date('', $p)) . '</span>';
|
||||
$out .= '</a>';
|
||||
}
|
||||
$out .= '</div></div>';
|
||||
}
|
||||
}
|
||||
|
||||
// Live suggestions mount point.
|
||||
$out .= '<div class="aksrt-menu-search-suggest mt10" data-aksrt-menu-suggest="1" hidden></div>';
|
||||
|
||||
return $out;
|
||||
return (string) aksrt_get_search_box([
|
||||
'show_form' => false,
|
||||
'show_keywords' => true,
|
||||
'show_history' => true,
|
||||
'show_posts' => true,
|
||||
]);
|
||||
}
|
||||
endif;
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ if (!function_exists('aksrt_nav_mobile_content')) :
|
||||
$top_btns .= '</a>';
|
||||
}
|
||||
if ($m_layout !== 'center' && !empty($ctx['search_enabled'])) {
|
||||
$top_btns .= '<a href="javascript:;" class="toggle-radius main-search-btn" data-toggle-class data-target=".navbar-search" aria-label="'
|
||||
$top_btns .= '<a href="javascript:;" class="toggle-radius main-search-btn" data-toggle-class="show" data-target=".navbar-search" aria-label="'
|
||||
. esc_attr__('打开搜索', 'aksrt') . '"><i class="fas fa-search" aria-hidden="true"></i></a>';
|
||||
}
|
||||
if (function_exists('aksrt_get_translate_language_btn')) {
|
||||
|
||||
@@ -77,7 +77,7 @@ if (!function_exists('aksrt_navbar_header')) :
|
||||
$button .= '<i class="em12 css-icon i-menu"><i></i></i></button>';
|
||||
|
||||
if (($ctx['mobile_layout'] ?? 'center') === 'center' && !empty($ctx['search_enabled'])) {
|
||||
$button .= '<button type="button" class="navbar-toggle main-search-btn nav-search-btn" data-toggle-class data-target=".navbar-search" aria-label="'
|
||||
$button .= '<button type="button" class="navbar-toggle main-search-btn nav-search-btn" data-toggle-class="show" data-target=".navbar-search" aria-label="'
|
||||
. esc_attr__('打开搜索', 'aksrt') . '">';
|
||||
$button .= '<i class="fas fa-search" aria-hidden="true"></i></button>';
|
||||
}
|
||||
@@ -100,33 +100,27 @@ if (!function_exists('aksrt_get_menu_search')) :
|
||||
return;
|
||||
}
|
||||
$placeholder = (string) ($ctx['search_placeholder'] ?? __('搜索内容', 'aksrt'));
|
||||
$state = is_array($ctx['search_state'] ?? null) ? $ctx['search_state'] : [];
|
||||
$type = (string) ($state['type'] ?? 'post');
|
||||
$cat_enabled = !empty($state['category_enabled']);
|
||||
$cat_id = (int) ($state['category_id'] ?? 0);
|
||||
|
||||
// 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')
|
||||
);
|
||||
|
||||
// zibll: form + input + remote-box (action=menu_search).
|
||||
echo '<form method="get" class="navbar-form navbar-left hover-show" action="' . esc_url(home_url('/')) . '" role="search" data-aksrt-search-form="inline">';
|
||||
echo '<div class="form-group relative dropdown">';
|
||||
echo '<input type="hidden" name="aksrt_search_type" value="' . esc_attr($type) . '">';
|
||||
if ($cat_enabled) {
|
||||
echo '<input type="hidden" name="aksrt_category" value="' . esc_attr((string) $cat_id) . '">';
|
||||
}
|
||||
echo '<input type="text" class="form-control search-input focus-show" name="s" value="'
|
||||
. esc_attr(get_search_query()) . '" placeholder="' . esc_attr($placeholder) . '" autocomplete="off">';
|
||||
echo '<div class="abs-right muted-3-color"><button type="submit" class="null" aria-label="'
|
||||
. esc_attr__('搜索', 'aksrt') . '"><i class="fas fa-search" aria-hidden="true"></i></button></div>';
|
||||
// Remote panel mount (zibll remote-box / lazyload-action=ias).
|
||||
echo '<div class="aksrt-remote-box lazyload" remote-box="' . esc_url($remote_url) . '" lazyload-action="ias" data-aksrt-menu-search-remote="1">';
|
||||
echo '<i class="loading-spot"><i></i></i>';
|
||||
echo '</div>';
|
||||
if (function_exists('aksrt_get_remote_box')) {
|
||||
echo aksrt_get_remote_box([ // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
'class' => '',
|
||||
'loader' => ' ',
|
||||
'query' => [
|
||||
'action' => 'menu_search',
|
||||
],
|
||||
]);
|
||||
} else {
|
||||
$remote_url = add_query_arg(['action' => 'menu_search'], admin_url('admin-ajax.php'));
|
||||
echo '<div class="lazyload" remote-box="' . esc_url($remote_url) . '" lazyload-action="ias">';
|
||||
echo '<i class="loading-spot"><i></i></i></div>';
|
||||
}
|
||||
echo '</div></form>';
|
||||
}
|
||||
endif;
|
||||
@@ -224,6 +218,17 @@ if (!function_exists('aksrt_header_user_box_html')) :
|
||||
$href .= '<a rel="nofollow" target="_blank" href="' . esc_url((string) $ctx['theme_settings_url']) . '">';
|
||||
$href .= '<div class="badg mb6 toggle-radius c-yellow"><i class="fas fa-sliders-h" aria-hidden="true"></i></div>';
|
||||
$href .= '<div class="c-yellow">' . esc_html__('主题设置', 'aksrt') . '</div></a>';
|
||||
// zibll: 模块布局 → widgets.
|
||||
$href .= '<a rel="nofollow" target="_blank" href="' . esc_url(admin_url('widgets.php')) . '">';
|
||||
$href .= '<div class="badg mb6 toggle-radius c-yellow"><i class="fas fa-chart-pie" aria-hidden="true"></i></div>';
|
||||
$href .= '<div class="c-yellow">' . esc_html__('模块布局', 'aksrt') . '</div></a>';
|
||||
// zibll: 商城中心.
|
||||
$shop_url = post_type_exists('aksrt_product')
|
||||
? admin_url('edit.php?post_type=aksrt_product')
|
||||
: admin_url('admin.php?page=aksrt_pay');
|
||||
$href .= '<a rel="nofollow" target="_blank" href="' . esc_url($shop_url) . '">';
|
||||
$href .= '<div class="badg mb6 toggle-radius c-yellow"><i class="fas fa-shopping-bag" aria-hidden="true"></i></div>';
|
||||
$href .= '<div class="c-yellow">' . esc_html__('商城中心', 'aksrt') . '</div></a>';
|
||||
$href .= '<a rel="nofollow" target="_blank" href="' . esc_url(admin_url()) . '">';
|
||||
$href .= '<div class="badg mb6 toggle-radius c-yellow"><i class="fas fa-cog" aria-hidden="true"></i></div>';
|
||||
$href .= '<div class="c-yellow">' . esc_html__('后台管理', 'aksrt') . '</div></a>';
|
||||
@@ -346,7 +351,7 @@ if (!function_exists('aksrt_menu_button')) :
|
||||
|
||||
$search_but = '';
|
||||
if ('2' !== $layout && !empty($ctx['search_enabled'])) {
|
||||
$search_but = '<li class="relative"><a href="javascript:;" class="btn nav-search-btn main-search-btn" data-toggle-class data-target=".navbar-search" aria-label="'
|
||||
$search_but = '<li class="relative"><a href="javascript:;" class="btn nav-search-btn main-search-btn" data-toggle-class="show" data-target=".navbar-search" aria-label="'
|
||||
. esc_attr__('打开搜索', 'aksrt') . '"><i class="fas fa-search" aria-hidden="true"></i></a></li>';
|
||||
}
|
||||
|
||||
|
||||
@@ -183,8 +183,16 @@ if (!function_exists('aksrt_header')) :
|
||||
aksrt_nav_mobile_shell($ctx);
|
||||
}
|
||||
|
||||
if (function_exists('aksrt_render_signout_modal')) {
|
||||
aksrt_render_signout_modal();
|
||||
}
|
||||
// Layout 1/3 search slide (zibll .navbar-search). Layout-2 uses inline menu_search.
|
||||
if (!empty($ctx['search_enabled'])) {
|
||||
$navbar_search = locate_template('templates/parts/navbar-search.php');
|
||||
if ($navbar_search) {
|
||||
include $navbar_search;
|
||||
}
|
||||
}
|
||||
|
||||
if (function_exists('aksrt_render_signout_modal')) {
|
||||
aksrt_render_signout_modal();
|
||||
}
|
||||
}
|
||||
endif;
|
||||
|
||||
@@ -0,0 +1,319 @@
|
||||
<?php
|
||||
/**
|
||||
* Search box markup (zibll zib_get_search_box parity).
|
||||
*
|
||||
* Used by layout-2 menu_search AJAX panel and layout 1/3 .navbar-search.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
if (!function_exists('aksrt_get_search_history_keywords')) :
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
function aksrt_get_search_history_keywords(): array {
|
||||
$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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return array_values(array_unique(array_filter(array_map('trim', $hist))));
|
||||
}
|
||||
endif;
|
||||
|
||||
if (!function_exists('aksrt_get_search_keywords_but')) :
|
||||
/**
|
||||
* Render keyword chip links.
|
||||
*
|
||||
* @param list<string> $keywords
|
||||
* @param string $type popular|history
|
||||
*/
|
||||
function aksrt_get_search_keywords_but(array $keywords, string $type = 'popular', int $limit = 0): string {
|
||||
if ($limit > 0) {
|
||||
$keywords = array_slice($keywords, 0, $limit);
|
||||
}
|
||||
$out = '';
|
||||
foreach ($keywords as $kw) {
|
||||
$kw = trim((string) $kw);
|
||||
if ($kw === '') {
|
||||
continue;
|
||||
}
|
||||
$out .= '<a class="but jb-sm" data-search-keyword="' . esc_attr($kw) . '" href="'
|
||||
. esc_url(home_url('/?s=' . rawurlencode($kw))) . '">'
|
||||
. esc_html($kw) . '</a> ';
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
endif;
|
||||
|
||||
if (!function_exists('aksrt_get_search_box')) :
|
||||
/**
|
||||
* zibll-compatible search box.
|
||||
*
|
||||
* @param array<string,mixed> $args
|
||||
* @param bool $echo
|
||||
* @return string|void
|
||||
*/
|
||||
function aksrt_get_search_box(array $args = [], bool $echo = false) {
|
||||
$defaults = [
|
||||
's' => '',
|
||||
'class' => '',
|
||||
'show_form' => true,
|
||||
'show_keywords' => true,
|
||||
'popular_limit' => 0,
|
||||
'show_history' => true,
|
||||
'keywords_title' => '',
|
||||
'placeholder' => '',
|
||||
'show_input_cat' => true,
|
||||
'show_posts' => false,
|
||||
'show_type' => false,
|
||||
'in_cat' => '',
|
||||
'in_type' => 'post',
|
||||
'in_user' => '',
|
||||
'more_cats' => [],
|
||||
];
|
||||
$args = wp_parse_args($args, $defaults);
|
||||
|
||||
if ($args['keywords_title'] === '' && class_exists('\AKSRT\Settings\Settings')
|
||||
&& method_exists('\AKSRT\Settings\Settings', 'search_popular_title')) {
|
||||
$args['keywords_title'] = (string) \AKSRT\Settings\Settings::search_popular_title();
|
||||
}
|
||||
if ($args['keywords_title'] === '') {
|
||||
$args['keywords_title'] = __('热门搜索', 'aksrt');
|
||||
}
|
||||
if ($args['placeholder'] === '' && function_exists('aksrt_get_search_placeholder')) {
|
||||
$args['placeholder'] = aksrt_get_search_placeholder();
|
||||
}
|
||||
if ($args['placeholder'] === '') {
|
||||
$args['placeholder'] = __('开启精彩搜索', 'aksrt');
|
||||
}
|
||||
$args['placeholder'] = esc_attr((string) $args['placeholder']);
|
||||
|
||||
// Settings gates when caller left defaults on.
|
||||
if (class_exists('\AKSRT\Settings\Settings')) {
|
||||
if (!array_key_exists('show_keywords_forced', $args)
|
||||
&& method_exists('\AKSRT\Settings\Settings', 'hot_search_enabled')
|
||||
&& !\AKSRT\Settings\Settings::hot_search_enabled()) {
|
||||
// Keep explicit false from caller; only gate when show_keywords true by default path.
|
||||
}
|
||||
}
|
||||
|
||||
$form_html = '';
|
||||
if (!empty($args['show_form'])) {
|
||||
$state = function_exists('aksrt_get_search_form_state')
|
||||
? aksrt_get_search_form_state()
|
||||
: [
|
||||
'type' => 'post',
|
||||
'types' => ['post' => __('文章', 'aksrt')],
|
||||
'category_id' => 0,
|
||||
'category_enabled' => false,
|
||||
'categories' => [],
|
||||
];
|
||||
|
||||
$type_html = '';
|
||||
$types = is_array($state['types'] ?? null) ? $state['types'] : [];
|
||||
$in_type = (string) ($args['in_type'] ?: ($state['type'] ?? 'post'));
|
||||
if (!empty($args['show_type']) && count($types) > 1) {
|
||||
$type_items = '';
|
||||
foreach ($types as $k => $v) {
|
||||
$cls = $in_type === (string) $k ? ' active' : '';
|
||||
$type_items .= '<a class="but' . esc_attr($cls) . '" data-for="type" data-value="'
|
||||
. esc_attr((string) $k) . '" href="javascript:;">' . esc_html((string) $v) . '</a>';
|
||||
}
|
||||
$type_html = '<div class="flex jc mb10 search-type-but-average">';
|
||||
$type_html .= '<div class="but-average radius">' . $type_items . '</div></div>';
|
||||
}
|
||||
|
||||
$cat_html = '';
|
||||
if (!empty($args['show_input_cat']) && !empty($state['category_enabled'])
|
||||
&& !empty($state['categories']) && is_array($state['categories'])) {
|
||||
$in_cat_id = (int) ($args['in_cat'] ?: ($state['category_id'] ?? 0));
|
||||
$in_cat_name = '';
|
||||
$all_cat = '<li data-for="trem" data-value="null"><a href="javascript:;" class="text-ellipsis">'
|
||||
. esc_html__('全部', 'aksrt') . '</a></li>';
|
||||
foreach ($state['categories'] as $cat) {
|
||||
if (!is_array($cat)) {
|
||||
continue;
|
||||
}
|
||||
$cid = (int) ($cat['id'] ?? 0);
|
||||
$cname = (string) ($cat['name'] ?? '');
|
||||
if ($cid <= 0 || $cname === '') {
|
||||
continue;
|
||||
}
|
||||
if ($cid === $in_cat_id) {
|
||||
$in_cat_name = $cname;
|
||||
}
|
||||
$all_cat .= '<li data-for="trem" data-value="' . esc_attr((string) $cid) . '"><a href="javascript:;" class="text-ellipsis">'
|
||||
. esc_html(mb_strlen($cname) > 8 ? mb_substr($cname, 0, 8) . '…' : $cname)
|
||||
. '</a></li>';
|
||||
}
|
||||
$all_cat = '<ul class="dropdown-menu cat-drop">' . $all_cat . '</ul>';
|
||||
$label = $in_cat_name !== ''
|
||||
? (mb_strlen($in_cat_name) > 6 ? mb_substr($in_cat_name, 0, 6) . '…' : $in_cat_name)
|
||||
: __('请选择', 'aksrt');
|
||||
$input_cat = '<a href="javascript:;" class="padding-h10" data-toggle="dropdown"><span name="trem">'
|
||||
. esc_html($label) . '</span><i class="fa ml6 fa-sort opacity5" aria-hidden="true"></i></a>';
|
||||
$input_cat .= $all_cat;
|
||||
$cat_html = '<div class="option-dropdown splitters-this-r search-drop"><div class="dropdown">'
|
||||
. $input_cat . '</div></div>';
|
||||
}
|
||||
|
||||
$s = esc_attr(wp_strip_all_tags((string) $args['s']));
|
||||
if ($s === '' && is_search()) {
|
||||
$s = esc_attr(get_search_query());
|
||||
}
|
||||
$input_html = '<div class="search-input-text">';
|
||||
$input_html .= '<input type="text" name="s" class="line-form-input" tabindex="1" value="' . $s . '">';
|
||||
$input_html .= '<i class="line-form-line"></i>';
|
||||
$input_html .= '<div class="scale-placeholder' . ($s !== '' ? ' is-focus' : '') . '" default="'
|
||||
. $args['placeholder'] . '">' . $args['placeholder'] . '</div>';
|
||||
$input_html .= '<div class="abs-right muted-color"><button type="submit" tabindex="2" class="null" aria-label="'
|
||||
. esc_attr__('搜索', 'aksrt') . '"><i class="fas fa-search" aria-hidden="true"></i></button></div>';
|
||||
$input_html .= '</div>';
|
||||
|
||||
$input_html .= '<input type="hidden" name="aksrt_search_type" value="' . esc_attr($in_type) . '">';
|
||||
if ($cat_html !== '' || (string) $args['in_cat'] !== '') {
|
||||
$input_html .= '<input type="hidden" name="aksrt_category" value="'
|
||||
. esc_attr((string) ($args['in_cat'] !== '' ? $args['in_cat'] : ($state['category_id'] ?? 0))) . '">';
|
||||
}
|
||||
if ((string) $args['in_user'] !== '') {
|
||||
$input_html .= '<input type="hidden" name="user" value="' . esc_attr((string) $args['in_user']) . '">';
|
||||
}
|
||||
|
||||
if ($cat_html === '') {
|
||||
$cat_html = $type_html;
|
||||
$type_html = '';
|
||||
}
|
||||
|
||||
$form_html = '<form method="get" class="padding-10 search-form" action="'
|
||||
. esc_url(home_url('/')) . '" role="search" data-aksrt-search-form="box">'
|
||||
. $type_html
|
||||
. '<div class="line-form">' . $cat_html . $input_html . '</div>'
|
||||
. '</form>';
|
||||
}
|
||||
|
||||
// Popular keywords.
|
||||
$keywords_html = '';
|
||||
if (!empty($args['show_keywords'])) {
|
||||
$show = true;
|
||||
if (class_exists('\AKSRT\Settings\Settings') && method_exists('\AKSRT\Settings\Settings', 'hot_search_enabled')) {
|
||||
$show = (bool) \AKSRT\Settings\Settings::hot_search_enabled();
|
||||
}
|
||||
if ($show) {
|
||||
$keywords = function_exists('aksrt_get_search_hot_keywords') ? aksrt_get_search_hot_keywords() : [];
|
||||
$limit = (int) $args['popular_limit'];
|
||||
$keyword_link = aksrt_get_search_keywords_but(is_array($keywords) ? $keywords : [], 'popular', $limit);
|
||||
if ($keyword_link !== '') {
|
||||
$keywords_html = '<div class="search-keywords">'
|
||||
. '<p class="muted-color"><span>' . esc_html((string) $args['keywords_title']) . '</span></p>'
|
||||
. '<div>' . $keyword_link . '</div>'
|
||||
. '</div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// History.
|
||||
$history_html = '';
|
||||
if (!empty($args['show_history'])) {
|
||||
$show_h = true;
|
||||
if (function_exists('aksrt_search_history_enabled')) {
|
||||
$show_h = aksrt_search_history_enabled();
|
||||
} elseif (class_exists('\AKSRT\Settings\Settings') && method_exists('\AKSRT\Settings\Settings', 'search_history_enabled')) {
|
||||
$show_h = (bool) \AKSRT\Settings\Settings::search_history_enabled();
|
||||
}
|
||||
if ($show_h) {
|
||||
$hist = aksrt_get_search_history_keywords();
|
||||
// Empty shell still rendered so client localStorage can fill it.
|
||||
$keyword_link = aksrt_get_search_keywords_but($hist, 'history');
|
||||
$history_html = '<div class="search-keywords history-search" data-aksrt-menu-history="1">';
|
||||
$history_html .= '<p class="muted-color"><span>' . esc_html__('历史搜索', 'aksrt') . '</span>';
|
||||
$history_html .= '<a class="pull-right trash-history-search muted-3-color" href="javascript:;" data-aksrt-clear-menu-history="1" aria-label="'
|
||||
. esc_attr__('清空历史', 'aksrt') . '"><i class="fas fa-trash-alt em12" aria-hidden="true"></i></a></p>';
|
||||
$history_html .= '<div class="history-search-list">';
|
||||
if ($keyword_link !== '') {
|
||||
$history_html .= $keyword_link;
|
||||
} else {
|
||||
$history_html .= '<span class="muted-3-color em09" data-empty="1">' . esc_html__('暂无历史', 'aksrt') . '</span>';
|
||||
}
|
||||
$history_html .= '</div></div>';
|
||||
}
|
||||
}
|
||||
|
||||
// Hot posts (thumb swiper).
|
||||
$posts_html = '';
|
||||
if (!empty($args['show_posts'])) {
|
||||
$show_p = true;
|
||||
if (class_exists('\AKSRT\Settings\Settings') && method_exists('\AKSRT\Settings\Settings', 'search_posts_enabled')) {
|
||||
$show_p = (bool) \AKSRT\Settings\Settings::search_posts_enabled();
|
||||
}
|
||||
if ($show_p && function_exists('aksrt_get_search_posts')) {
|
||||
$slides = aksrt_get_search_posts(6, 'views', true);
|
||||
if ($slides !== '') {
|
||||
$posts_html = '<div class="padding-10 relates relates-thumb">';
|
||||
$posts_html .= '<p class="muted-color">' . esc_html__('热门文章', 'aksrt') . '</p>';
|
||||
$posts_html .= '<div class="swiper-container swiper-scroll">';
|
||||
$posts_html .= '<div class="swiper-wrapper">' . $slides . '</div>';
|
||||
$posts_html .= '<div class="swiper-button-prev"></div><div class="swiper-button-next"></div>';
|
||||
$posts_html .= '</div></div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Live suggestions mount (AKSRT extension; does not break zibll classes).
|
||||
$suggest = '<div class="aksrt-menu-search-suggest mt10" data-aksrt-menu-suggest="1" hidden></div>';
|
||||
|
||||
$class = $args['class'] ? ' ' . sanitize_html_class((string) $args['class']) : '';
|
||||
$html = '<div class="search-input' . esc_attr($class) . '">'
|
||||
. $form_html . $keywords_html . $history_html . $posts_html . $suggest
|
||||
. '</div>';
|
||||
|
||||
if ($echo) {
|
||||
echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
return;
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
endif;
|
||||
|
||||
if (!function_exists('aksrt_get_remote_box')) :
|
||||
/**
|
||||
* Lazy remote HTML mount (zibll zib_get_remote_box).
|
||||
*
|
||||
* @param array<string,mixed> $args
|
||||
*/
|
||||
function aksrt_get_remote_box(array $args = []): string {
|
||||
$defaults = [
|
||||
'type' => 'ias',
|
||||
'class' => '',
|
||||
'loader' => '<i class="loading-spot"><i></i></i>',
|
||||
'url' => admin_url('admin-ajax.php'),
|
||||
'query' => false,
|
||||
];
|
||||
$args = wp_parse_args($args, $defaults);
|
||||
$url = (string) $args['url'];
|
||||
if (!empty($args['query']) && is_array($args['query'])) {
|
||||
$url = add_query_arg($args['query'], $url);
|
||||
}
|
||||
$attr = ' remote-box="' . esc_url($url) . '"';
|
||||
$class = (string) $args['class'];
|
||||
if (($args['type'] ?? '') === 'ias') {
|
||||
$attr .= ' lazyload-action="ias"';
|
||||
$class .= ' lazyload';
|
||||
}
|
||||
if (($args['type'] ?? '') === 'load') {
|
||||
$attr .= ' load-click';
|
||||
}
|
||||
$class_attr = $class !== '' ? ' class="' . esc_attr(trim($class)) . '"' : '';
|
||||
return '<div' . $class_attr . $attr . '>' . $args['loader'] . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
endif;
|
||||
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
/**
|
||||
* Search panel hot posts (zibll zib_get_search_posts parity).
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
if (!function_exists('aksrt_get_search_posts')) :
|
||||
/**
|
||||
* Build hot-post slides for the search dropdown.
|
||||
*
|
||||
* @param int $count Number of posts.
|
||||
* @param string $orderby views|date|modified|…
|
||||
* @param bool $show_img Use graphic cards (true) or text list (false).
|
||||
*/
|
||||
function aksrt_get_search_posts(int $count = 6, string $orderby = 'views', bool $show_img = true): string {
|
||||
$count = max(1, min(20, $count));
|
||||
|
||||
$args = [
|
||||
'posts_per_page' => $count,
|
||||
'ignore_sticky_posts' => true,
|
||||
'post_status' => 'publish',
|
||||
'post_type' => 'post',
|
||||
'no_found_rows' => true,
|
||||
'update_post_meta_cache' => true,
|
||||
'update_post_term_cache' => false,
|
||||
];
|
||||
|
||||
if ($orderby === 'views') {
|
||||
$args['orderby'] = 'meta_value_num';
|
||||
$args['meta_key'] = 'aksrt_post_views';
|
||||
$args['order'] = 'DESC';
|
||||
} else {
|
||||
$allowed = ['date', 'modified', 'comment_count', 'rand', 'title'];
|
||||
$args['orderby'] = in_array($orderby, $allowed, true) ? $orderby : 'date';
|
||||
$args['order'] = 'DESC';
|
||||
}
|
||||
|
||||
$query = new WP_Query($args);
|
||||
// Fallback when no posts have views meta yet.
|
||||
if (!$query->have_posts() && $orderby === 'views') {
|
||||
wp_reset_postdata();
|
||||
$args['orderby'] = 'date';
|
||||
unset($args['meta_key']);
|
||||
$query = new WP_Query($args);
|
||||
}
|
||||
|
||||
$lists = '';
|
||||
while ($query->have_posts()) {
|
||||
$query->the_post();
|
||||
$post_id = (int) get_the_ID();
|
||||
$title = get_the_title($post_id);
|
||||
if ($title === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($show_img && function_exists('aksrt_graphic_card')) {
|
||||
$thumb = get_the_post_thumbnail_url($post_id, 'medium');
|
||||
if (!$thumb) {
|
||||
$thumb = get_template_directory_uri() . '/assets/img/placeholder.svg';
|
||||
}
|
||||
$views = function_exists('aksrt_get_post_views') ? (int) aksrt_get_post_views($post_id) : 0;
|
||||
$views_txt = function_exists('aksrt_format_number')
|
||||
? aksrt_format_number($views)
|
||||
: (string) $views;
|
||||
$time_ago = human_time_diff(get_the_time('U', $post_id), current_time('timestamp'));
|
||||
$info = '<item>' . esc_html(sprintf(/* translators: %s: relative time */ __('%s前', 'aksrt'), $time_ago))
|
||||
. '</item><item class="pull-right"><i class="fas fa-eye" aria-hidden="true"></i> '
|
||||
. esc_html((string) $views_txt) . '</item>';
|
||||
|
||||
$lists .= '<div class="swiper-slide em09 mr10" style="width:160px;">';
|
||||
$lists .= aksrt_graphic_card([
|
||||
'type' => 'style-3',
|
||||
'class' => '',
|
||||
'img' => $thumb,
|
||||
'alt' => $title,
|
||||
'link' => [
|
||||
'url' => get_permalink($post_id),
|
||||
'target' => '',
|
||||
],
|
||||
'text1' => $title,
|
||||
'text2' => mb_strlen($title) > 29 ? mb_substr($title, 0, 29) . '…' : $title,
|
||||
'text3' => $info,
|
||||
'lazy' => true,
|
||||
'height_scale' => 70,
|
||||
], false);
|
||||
$lists .= '</div>';
|
||||
} else {
|
||||
$lists .= '<li><a class="icon-circle text-ellipsis" href="'
|
||||
. esc_url(get_permalink($post_id)) . '">'
|
||||
. esc_html($title) . '</a></li>';
|
||||
}
|
||||
}
|
||||
wp_reset_postdata();
|
||||
|
||||
return $lists;
|
||||
}
|
||||
endif;
|
||||
@@ -42,7 +42,6 @@ class SchemaPageDisplay {
|
||||
['key' => 'components', 'title' => '导航组件', 'fields' => [
|
||||
['key' => 'header_search_enabled', 'label' => '搜索入口', 'type' => 'switch', 'default' => true],
|
||||
['key' => 'header_user_menu', 'label' => '用户菜单', 'type' => 'switch', 'default' => true],
|
||||
['key' => 'header_publish_btn', 'label' => '发布按钮', 'type' => 'switch', 'default' => true],
|
||||
['key' => 'header_mobile_drawer', 'label' => '移动端抽屉导航', 'type' => 'switch', 'default' => true],
|
||||
['key' => 'header_nav_pay_vip', 'label' => '导航栏开通会员按钮', 'type' => 'switch', 'default' => true],
|
||||
['key' => 'header_nav_user_pay_vip', 'label' => '用户框开通会员按钮', 'type' => 'switch', 'default' => true],
|
||||
@@ -51,7 +50,14 @@ class SchemaPageDisplay {
|
||||
['key' => 'header_newposts_enabled', 'label' => '启用发布按钮', 'type' => 'switch', 'default' => true],
|
||||
['key' => 'header_newposts_text', 'label' => '按钮文案', 'type' => 'input', 'default' => '<i class="fa fa-pencil"></i> 发布'],
|
||||
['key' => 'header_newposts_radius', 'label' => '按钮圆角(胶囊)', 'type' => 'switch', 'default' => true],
|
||||
['key' => 'header_newposts_class', 'label' => '样式类', 'type' => 'input', 'default' => ''],
|
||||
['key' => 'header_newposts_class', 'label' => '按钮颜色', 'type' => 'select', 'default' => 'jb-blue', 'options' => [
|
||||
['label' => '蓝色', 'value' => 'jb-blue'],
|
||||
['label' => '红色', 'value' => 'jb-red'],
|
||||
['label' => '绿色', 'value' => 'jb-green'],
|
||||
['label' => '黄色', 'value' => 'jb-yellow'],
|
||||
['label' => '紫色', 'value' => 'jb-purple'],
|
||||
['label' => '粉色', 'value' => 'jb-pink'],
|
||||
]],
|
||||
['key' => 'header_newposts_types', 'label' => '发布类型', 'type' => 'select', 'default' => ['post'], 'options' => [
|
||||
['label' => '文章', 'value' => 'post'],
|
||||
['label' => '帖子', 'value' => 'topic'],
|
||||
|
||||
@@ -40,7 +40,8 @@ trait FacadeBulk {
|
||||
'fixed' => !isset($settings['header_fixed']) || !empty($settings['header_fixed']),
|
||||
'search_enabled' => !isset($settings['header_search_enabled']) || !empty($settings['header_search_enabled']),
|
||||
'user_menu' => !isset($settings['header_user_menu']) || !empty($settings['header_user_menu']),
|
||||
'publish_btn' => !isset($settings['header_publish_btn']) || !empty($settings['header_publish_btn']),
|
||||
// Unified with header_newposts_enabled (zibll nav_newposts).
|
||||
'publish_btn' => !isset($settings['header_newposts_enabled']) || !empty($settings['header_newposts_enabled']),
|
||||
'mobile_drawer' => !isset($settings['header_mobile_drawer']) || !empty($settings['header_mobile_drawer']),
|
||||
'nav_style' => $nav_style,
|
||||
'max_width' => $max_width,
|
||||
@@ -85,7 +86,7 @@ trait FacadeBulk {
|
||||
'text' => trim((string) ($s['header_newposts_text'] ?? '<i class="fa fa-pencil"></i> 发布')),
|
||||
'radius' => $radius_px,
|
||||
'radius_pill' => $radius_pill,
|
||||
'class' => sanitize_html_class((string) ($s['header_newposts_class'] ?? '')),
|
||||
'class' => sanitize_html_class((string) (($s['header_newposts_class'] ?? '') !== '' ? $s['header_newposts_class'] : 'jb-blue')),
|
||||
'types' => $types,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
/**
|
||||
* Layout 1/3 top search slide layer (zibll .navbar-search + search-box).
|
||||
*
|
||||
* Footer tabbar keeps templates/parts/search-panel.php (#tabbar-search-overlay).
|
||||
* Top-nav icons use data-toggle-class="show" data-target=".navbar-search".
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
if (class_exists('\AKSRT\Settings\Settings')) {
|
||||
$header_nav = \AKSRT\Settings\Settings::get_header_nav_settings();
|
||||
if (empty($header_nav['search_enabled'])) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_get_search_box')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$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));
|
||||
}
|
||||
?>
|
||||
<div class="navbar-search main-search" data-aksrt-shell="navbar-search" aria-hidden="true">
|
||||
<div class="container">
|
||||
<button type="button" class="close navbar-search-close" data-toggle-class="show" data-target=".navbar-search" aria-label="<?php esc_attr_e('关闭搜索', 'aksrt'); ?>">
|
||||
<i class="fas fa-times" aria-hidden="true"></i>
|
||||
</button>
|
||||
<?php
|
||||
// Full form + keywords + history + hot posts (zibll show_form=true path).
|
||||
echo aksrt_get_search_box([ // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
'show_form' => true,
|
||||
'show_keywords' => $show_keywords,
|
||||
'show_history' => $show_history,
|
||||
'show_posts' => $show_posts,
|
||||
'show_type' => true,
|
||||
'show_input_cat'=> true,
|
||||
's' => is_search() ? get_search_query() : '',
|
||||
]);
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,6 +1,9 @@
|
||||
<?php
|
||||
/**
|
||||
* Global search panel (desktop + mobile).
|
||||
* Footer tabbar / shell search overlay (NOT the top-nav zibll slide).
|
||||
*
|
||||
* Top navigation uses templates/parts/navbar-search.php (.navbar-search) for
|
||||
* layouts 1/3 and remote menu_search for layout 2.
|
||||
*
|
||||
* DOM contracts for assets/js/core/search.js and footer-tabbar search tab:
|
||||
* - #tabbar-search-overlay (also #nav-search-panel for shell config)
|
||||
|
||||
@@ -1,43 +1,42 @@
|
||||
# Top nav zibll 1:1 acceptance checklist
|
||||
|
||||
Branch: `worktree-nav-zibll-1to1`
|
||||
Branch: `worktree-nav-zibll-full-1to1`
|
||||
|
||||
## Desktop
|
||||
- [ ] Layout 1: logo | menu | publish/VIP | theme(+lang) | user | search icon
|
||||
- [ ] Layout 2: logo | menu | inline search(+hot/suggest) | CTAs | user (no search icon)
|
||||
## Desktop shell
|
||||
- [ ] Layout 1: logo | menu | publish/VIP | theme(+lang) | user | search icon → `.navbar-search` slide
|
||||
- [ ] Layout 2: logo | menu | inline search(+remote panel) | CTAs | user (no search icon)
|
||||
- [ ] Layout 3: logo | CTAs/user | menu right cluster
|
||||
- [ ] Fixed `body.nav-fixed` 88px reserve; hero show-slide pull-up
|
||||
- [ ] Fixed `body.nav-fixed` reserve; hero `show-slide` pull-up
|
||||
- [ ] Scroll-down hide / scroll-up show
|
||||
- [ ] Submenu hover + chevron; overflow folding "更多"
|
||||
- [ ] Publish single vs multi; VIP hover cards gated by switches
|
||||
- [ ] User box density + user-card publish type URL
|
||||
- [ ] Publish single vs multi; default `jb-blue` + radius pill; VIP hover cards
|
||||
- [ ] User box: check-in / wallet / badges + admin row (主题设置/模块布局/商城中心/后台)
|
||||
- [ ] Header theme colors when custom enabled
|
||||
- [ ] Language dropdown when i18n enabled + position header/both
|
||||
- [ ] Language dropdown when i18n enabled
|
||||
|
||||
## menu_search / search box (zibll DOM)
|
||||
- [ ] Layout-2 remote-box `action=menu_search` loads `.dropdown-menu.hover-show-con > .search-input`
|
||||
- [ ] Panel contains `.search-keywords` / `.history-search` / `.relates.relates-thumb` (when enabled)
|
||||
- [ ] Guest history from localStorage; trash clears
|
||||
- [ ] Layout 1/3 `.navbar-search` uses full `aksrt_get_search_box(show_form=true)`
|
||||
- [ ] Footer tabbar `#tabbar-search-overlay` still independent
|
||||
|
||||
## Mobile
|
||||
- [ ] center/left header; drawer left/right/top
|
||||
- [ ] `body.mobile-navbar-show` open/close + fixed-body + swipe
|
||||
- [ ] `body.mobile-navbar-show` + fixed-body + swipe
|
||||
- [ ] mobile menus depth 2 + user box + widgets
|
||||
- [ ] posts-nav-box TOC on single posts
|
||||
|
||||
## Admin
|
||||
- [ ] SPA image_select previews for layouts
|
||||
- [ ] newposts types multi + VIP switches persist
|
||||
- [ ] Appearance → Menus: icon/badge/senior visual editor saves meta
|
||||
- [ ] SPA image_select layouts
|
||||
- [ ] Single publish switch `header_newposts_enabled` (+ skin select jb-*)
|
||||
- [ ] Appearance → Menus senior editor
|
||||
- [ ] `cd assets/admin && npm run build` after schema changes
|
||||
- [ ] `php tools/audit-admin-contracts.php` green
|
||||
|
||||
## Page/section navs
|
||||
- [ ] section-navs builds `.posts-nav-lists` on `[data-nav]` pages
|
||||
- [ ] page-navs enqueued on posts-navs template
|
||||
## Deploy
|
||||
- Admin `build/` may be gitignored — build on deploy host.
|
||||
- Push branch to remote **`target`**, open PR via Gitea URL.
|
||||
|
||||
## 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
|
||||
## Contract report
|
||||
- `tools/nav-zibll-contract-report.txt` should list search DOM PASS after smoke.
|
||||
|
||||
@@ -1 +1,6 @@
|
||||
PASS full-push deep nav contracts
|
||||
PASS deep nav contracts (search-box DOM + remote menu_search + navbar-search slide + unified newposts)
|
||||
- aksrt_get_search_box / aksrt_get_search_posts present
|
||||
- menu_search AJAX wraps .dropdown-menu.hover-show-con > .search-input
|
||||
- layout1/3 templates/parts/navbar-search.php
|
||||
- header_newposts_enabled single switch; publish_btn mirrors
|
||||
- user box admin row: 主题设置/模块布局/商城中心/后台
|
||||
|
||||
Reference in New Issue
Block a user