feat(nav): complete remaining zibll parity (search, i18n, senior menus, CSS)
- Remove obsolete dual-path nav CSS; add utilities + language dropdown styles - Wire header/mobile translate switcher from i18n config - Layout-2 inline search hot keywords panel; nav_folding on resize - NavMenuOptions JSON editors for graphic_card / multi_column_links - Section-navs zibll posts-nav-lists; page-navs enqueue; mobile article TOC box - SPA/PHP user-card publish type; rebuild admin assets
This commit is contained in:
@@ -37,6 +37,7 @@ export const pageDisplaySchemas = {
|
||||
header_nav_pay_vip: true,
|
||||
header_nav_user_pay_vip: true,
|
||||
header_newposts_types: ['post'],
|
||||
header_user_newposts_btn: 'post',
|
||||
header_user_newposts_text: '发布内容',
|
||||
mobile_header_layout: 'center',
|
||||
mobile_navbar_align: 'left',
|
||||
@@ -124,6 +125,11 @@ export const pageDisplaySchemas = {
|
||||
{ label: '帖子', value: 'topic' },
|
||||
{ label: '商品', value: 'product' },
|
||||
], dependsOn: { key: 'header_newposts_enabled', value: true }, help: '未开启的模块不会显示' },
|
||||
{ key: 'header_user_newposts_btn', label: '用户卡发布类型', type: 'select', default: 'post', options: [
|
||||
{ label: '文章', value: 'post' },
|
||||
{ label: '帖子', value: 'topic' },
|
||||
{ label: '商品', value: 'product' },
|
||||
] },
|
||||
{ key: 'header_user_newposts_text', label: '用户卡发布文案', type: 'input', default: '发布内容' },
|
||||
{ key: 'header_nav_pay_vip', label: '导航栏开通会员按钮', type: 'switch', default: true, help: '顶部导航显示开通会员' },
|
||||
{ key: 'header_nav_user_pay_vip', label: '用户框开通会员按钮', type: 'switch', default: true },
|
||||
|
||||
@@ -2,10 +2,7 @@
|
||||
@import url("nav/zib-navbar-core.css");
|
||||
@import url("nav/zib-mobile-navbar.css");
|
||||
@import url("nav/zib-senior-submenu.css");
|
||||
@import url("nav/dark-mode-submenu.css");
|
||||
@import url("nav/dark-mode-mega-menu.css");
|
||||
@import url("nav/zib-utilities.css");
|
||||
@import url("nav/header-menu-buttons.css");
|
||||
@import url("nav/header-userbox.css");
|
||||
@import url("nav/menu-item-icon.css");
|
||||
@import url("nav/menu-item-badge.css");
|
||||
@import url("nav/hover-effects.css");
|
||||
@import url("nav/dark-mode-submenu.css");
|
||||
|
||||
@@ -1,577 +0,0 @@
|
||||
/* Zibll body.nav-fixed: hard 88px reserve (main.css), not bare --nav-height.
|
||||
* Nav bar itself is ~60px; extra space matches zibll chrome/shadow gap.
|
||||
* --nav-fixed-reserve is shared with the hero pull-up so they cancel exactly
|
||||
* (zibll: body padding-top 88px + .slide-header { margin-top: -90px }). */
|
||||
body.nav-fixed {
|
||||
--nav-fixed-reserve: 88px;
|
||||
padding-top: var(--nav-fixed-reserve);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
body.nav-fixed {
|
||||
--nav-fixed-reserve: 72px;
|
||||
padding-top: var(--nav-fixed-reserve);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
body.nav-fixed {
|
||||
--nav-fixed-reserve: 60px;
|
||||
padding-top: var(--nav-fixed-reserve);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fixed nav without hero overlay: take header out of flow.
|
||||
body.nav-fixed already reserves space via padding-top. */
|
||||
body.nav-fixed .header:not(.show-slide) {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
/* Nav lives inside the fixed header — don't keep sticky (double offset). */
|
||||
body.nav-fixed .header:not(.show-slide) .site-nav,
|
||||
body.nav-fixed .header:not(.show-slide) .navbar.navbar-top {
|
||||
position: relative;
|
||||
top: auto;
|
||||
}
|
||||
|
||||
/*
|
||||
* Non-home pages have no hero under the fixed header. Keep the first content
|
||||
* (breadcrumb / article) clearly below the bar even if a fluid widget zone is
|
||||
* empty or a child uses negative margin.
|
||||
*/
|
||||
body.nav-fixed:not(:has(.header.show-slide)) .fluid-widget-wrap:first-of-type:empty + main.container,
|
||||
body.nav-fixed:not(:has(.header.show-slide)) main.container:first-of-type {
|
||||
scroll-margin-top: calc(var(--nav-fixed-reserve, 88px) + 8px);
|
||||
}
|
||||
|
||||
/* Hero sits under transparent fixed/absolute header.
|
||||
* MUST cancel the full --nav-fixed-reserve (88/72/60), not just --nav-height (60).
|
||||
* Using only -60px against 88px padding left a ~28px blank strip above the hero. */
|
||||
body.nav-fixed .header-slider-container,
|
||||
body.nav-fixed .header-components-container,
|
||||
body.nav-fixed .header-components.slide-header {
|
||||
margin-top: calc(var(--nav-fixed-reserve, 88px) * -1) !important;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* AKSRT Navigation — Zibll-aligned
|
||||
*
|
||||
* - 高度 60px (--nav-height)
|
||||
* - 毛玻璃 blur-bg(saturate(5) blur(20px))
|
||||
* - 透明叠 slider → 滚动后恢复实底
|
||||
* - 滚动隐藏(scroll-down-hide 等价)
|
||||
* ============================================================ */
|
||||
|
||||
.site-nav {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1000;
|
||||
min-height: var(--nav-height, 60px);
|
||||
background-color: var(--blur-bg);
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.45);
|
||||
backdrop-filter: saturate(5) blur(20px);
|
||||
-webkit-backdrop-filter: saturate(5) blur(20px);
|
||||
transition: background-color 0.25s ease,
|
||||
border-color 0.25s ease,
|
||||
color 0.25s ease,
|
||||
box-shadow 0.25s ease,
|
||||
transform 0.3s ease; /* 滚动隐藏过渡 */
|
||||
}
|
||||
|
||||
/* 滚动隐藏头部 — 对齐 zibll .scroll-down.nav-fixed .header.scroll-down-hide */
|
||||
.site-nav.is-hidden {
|
||||
transform: translateY(-105%);
|
||||
}
|
||||
|
||||
.site-nav--static {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.site-nav--transparent {
|
||||
background: transparent; /* 对齐 zibll .header.show-slide: 透明覆盖在 slider 上 */
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
|
||||
.site-nav--transparent:not(.is-scrolled) {
|
||||
--header-color: #fff; /* 对齐 zibll --header-color:#fff */
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.site-nav--transparent:not(.is-scrolled) a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.site-nav--transparent.is-scrolled {
|
||||
background: var(--blur-bg); /* 滚动后恢复毛玻璃背景 */
|
||||
border-bottom-color: var(--color-line-soft);
|
||||
}
|
||||
|
||||
.site-nav--blur {
|
||||
background: var(--blur-bg);
|
||||
backdrop-filter: saturate(5) blur(20px);
|
||||
-webkit-backdrop-filter: saturate(5) blur(20px);
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
|
||||
html.dark .site-nav--transparent:not(.is-scrolled),
|
||||
html.dark .site-nav--blur:not(.is-scrolled),
|
||||
body.dark-theme .site-nav--transparent:not(.is-scrolled),
|
||||
body.dark-theme .site-nav--blur:not(.is-scrolled) {
|
||||
background: transparent;
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
|
||||
html.dark .site-nav--transparent.is-scrolled,
|
||||
html.dark .site-nav--blur.is-scrolled,
|
||||
body.dark-theme .site-nav--transparent.is-scrolled,
|
||||
body.dark-theme .site-nav--blur.is-scrolled {
|
||||
background: var(--blur-bg);
|
||||
border-bottom-color: var(--color-line-soft);
|
||||
}
|
||||
|
||||
/* 滚动后追加阴影 — 对齐 zibll .body-scroll .header */
|
||||
.site-nav.is-scrolled {
|
||||
box-shadow: 0 4px 10px var(--main-shadow, var(--shadow-sm));
|
||||
}
|
||||
|
||||
/* WordPress Admin Bar 已全局禁用,无需偏移规则 */
|
||||
|
||||
/* ============================================================
|
||||
* Inner / Row layout
|
||||
* ============================================================ */
|
||||
.site-nav__inner {
|
||||
max-width: var(--nav-max-width, var(--container));
|
||||
margin: 0 auto;
|
||||
padding: 0 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.site-nav__row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
gap: 12px;
|
||||
width: 100%;
|
||||
min-height: var(--nav-height, 60px);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Brand
|
||||
* ============================================================ */
|
||||
.site-brand {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
min-width: 0;
|
||||
max-width: min(48vw, 360px);
|
||||
padding: 7px 10px;
|
||||
color: var(--color-ink);
|
||||
font-size: 17px;
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.01em;
|
||||
flex-shrink: 0;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.site-brand:hover {
|
||||
color: var(--color-ink);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.site-brand--has-logo {
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.site-brand__logo {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 800;
|
||||
font-size: 13px;
|
||||
color: var(--color-on-primary, #fff);
|
||||
background: linear-gradient(135deg, var(--color-primary), var(--color-primary-active, var(--color-primary-dark)));
|
||||
letter-spacing: 0.02em;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.site-brand__media {
|
||||
display: block;
|
||||
flex: 0 1 auto;
|
||||
max-width: 100%;
|
||||
padding: 0 30px;
|
||||
line-height: 0;
|
||||
box-sizing: border-box;
|
||||
background: transparent !important;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
filter: none !important;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.site-brand__img {
|
||||
display: block;
|
||||
height: 36px;
|
||||
width: auto;
|
||||
max-width: 100%;
|
||||
object-fit: contain;
|
||||
object-position: left center;
|
||||
background: transparent !important;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
filter: none !important;
|
||||
mix-blend-mode: normal !important;
|
||||
opacity: 1;
|
||||
transform: none !important;
|
||||
}
|
||||
|
||||
.site-brand__name {
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.01em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Light/dark logo: single adaptive img (white-src/dark-src via theme.js) */
|
||||
.navbar-logo > img,
|
||||
.navbar-logo .site-brand__logo-img,
|
||||
.site-brand .site-brand__logo-img,
|
||||
.site-brand__logo-img,
|
||||
.site-brand .navbar-logo img {
|
||||
height: 36px !important;
|
||||
width: auto !important;
|
||||
max-width: min(180px, 40vw) !important;
|
||||
max-height: 36px !important;
|
||||
padding: 0 !important;
|
||||
object-fit: contain !important;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* Legacy dual-img classes (if any remain elsewhere) */
|
||||
.site-brand__logo-img--dark {
|
||||
display: none;
|
||||
}
|
||||
|
||||
html.dark .site-brand__logo-img--light,
|
||||
[data-theme="dark"] .site-brand__logo-img--light,
|
||||
body.dark-theme .site-brand__logo-img--light {
|
||||
display: none;
|
||||
}
|
||||
|
||||
html.dark .site-brand__logo-img--dark,
|
||||
[data-theme="dark"] .site-brand__logo-img--dark,
|
||||
body.dark-theme .site-brand__logo-img--dark {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Desktop menu
|
||||
* ============================================================ */
|
||||
ul.nav-desktop {
|
||||
display: none;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
align-items: center;
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.nav-desktop--fallback {
|
||||
display: none;
|
||||
align-items: center;
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
ul.nav-desktop a,
|
||||
.nav-desktop--fallback a {
|
||||
color: var(--color-ink-3);
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
padding: 0 12px; /* 对齐 zibll:仅水平 padding,垂直居中靠 flex 行高 */
|
||||
border-radius: 4px;
|
||||
transition: color var(--dur-fast, 0.15s) var(--ease),
|
||||
background var(--dur-fast, 0.15s) var(--ease);
|
||||
}
|
||||
|
||||
/* Hover — 对齐 zibll: 仅变色,无背景 */
|
||||
ul.nav-desktop a:hover,
|
||||
.nav-desktop--fallback a:hover {
|
||||
color: var(--color-primary);
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* Active page — 对齐 zibll: 仅变色(指示器走下方胶囊条) */
|
||||
ul.nav-desktop .current-menu-item > a,
|
||||
ul.nav-desktop .current_page_item > a {
|
||||
color: var(--color-primary);
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Desktop submenu (dropdown)
|
||||
* ============================================================ */
|
||||
ul.nav-desktop .menu-item {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 顶部 hover/current 胶囊指示器 — 对齐 zibll .navbar-nav>li:before
|
||||
(5px 高、底部 15px 圆角,从 header 顶缘垂下)。
|
||||
stretch 链(row→ul→li)让 li 充满 60px 行高,::before top:0 即锚定 header 顶部;
|
||||
::before 为 absolute 不进入 flex 流,不挤压链接。 */
|
||||
ul.nav-desktop {
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
ul.nav-desktop > .menu-item {
|
||||
align-self: stretch;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
ul.nav-desktop > .menu-item::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 5px;
|
||||
background: var(--focus-color, var(--color-primary));
|
||||
border-radius: 0 0 15px 15px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
ul.nav-desktop > .menu-item:hover::before,
|
||||
ul.nav-desktop > .current-menu-item::before,
|
||||
ul.nav-desktop > .current_page_item::before {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
ul.nav-desktop .sub-menu {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
z-index: 998; /* 保留较高 z-index(zibll 用 99,AKSRT 栈更深,避免被覆盖) */
|
||||
min-width: 140px;
|
||||
list-style: none;
|
||||
margin: 8px 0 0;
|
||||
padding: 8px 6px;
|
||||
background: var(--main-bg-color, #fff);
|
||||
border: none;
|
||||
border-radius: var(--main-radius, var(--radius, 8px));
|
||||
box-shadow: var(--shadow-lg);
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transform: translateY(6px);
|
||||
transition: opacity 0.4s ease, transform 0.4s ease, visibility 0.4s ease;
|
||||
}
|
||||
|
||||
ul.nav-desktop .menu-item:hover > .sub-menu {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
ul.nav-desktop .sub-menu .menu-item > a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 15px;
|
||||
font-size: 14px;
|
||||
border-radius: 4px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
ul.nav-desktop .sub-menu .menu-item > a:hover {
|
||||
background: var(--color-primary-soft, rgba(240, 68, 148, 0.08));
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
/* Nested submenus fly out to the right — 对齐 zibll top:-10px,去 margin-left */
|
||||
ul.nav-desktop .sub-menu .sub-menu {
|
||||
top: -10px;
|
||||
left: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ============================================================
|
||||
* Zibll .header.show-slide — transparent gradient over hero
|
||||
* ============================================================ */
|
||||
.header.show-slide {
|
||||
--header-bg: linear-gradient(0, rgba(0, 0, 0, 0) 5%, rgba(0, 0, 0, 0.1) 80%);
|
||||
--header-color: #fff;
|
||||
-webkit-backdrop-filter: unset;
|
||||
backdrop-filter: unset;
|
||||
}
|
||||
|
||||
body.nav-fixed .header.show-slide {
|
||||
position: absolute !important;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
z-index: 30;
|
||||
background: transparent !important;
|
||||
box-shadow: none !important;
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
/* Nav inside absolute header must not use sticky (avoids double offset) */
|
||||
body.nav-fixed .header.show-slide .site-nav,
|
||||
body.nav-fixed .header.show-slide .navbar.navbar-top {
|
||||
position: relative !important;
|
||||
top: auto !important;
|
||||
background: var(--header-bg, transparent) !important;
|
||||
border-bottom-color: transparent !important;
|
||||
box-shadow: none !important;
|
||||
color: var(--header-color, #fff);
|
||||
backdrop-filter: none !important;
|
||||
-webkit-backdrop-filter: none !important;
|
||||
}
|
||||
|
||||
.header.show-slide .navbar.navbar-top,
|
||||
.header.show-slide .site-nav {
|
||||
background: var(--header-bg, transparent);
|
||||
border-bottom-color: transparent;
|
||||
box-shadow: none;
|
||||
color: var(--header-color, #fff);
|
||||
backdrop-filter: none;
|
||||
-webkit-backdrop-filter: none;
|
||||
}
|
||||
|
||||
.header.show-slide .site-nav:not(.is-scrolled) a,
|
||||
.header.show-slide .site-nav:not(.is-scrolled) .icon-btn,
|
||||
.header.show-slide .site-nav:not(.is-scrolled) .site-brand__name {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.header.show-slide .site-nav.is-scrolled,
|
||||
.site-nav.is-scrolled {
|
||||
background: var(--blur-bg);
|
||||
color: var(--header-color, var(--color-ink-2));
|
||||
border-bottom-color: rgba(255, 255, 255, 0.45);
|
||||
backdrop-filter: saturate(5) blur(20px);
|
||||
-webkit-backdrop-filter: saturate(5) blur(20px);
|
||||
box-shadow: 0 4px 10px var(--main-shadow, rgba(116, 116, 116, 0.08));
|
||||
}
|
||||
|
||||
.navbar.navbar-top {
|
||||
margin: 0;
|
||||
border-radius: 0 !important;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.container-header,
|
||||
.container-footer {
|
||||
max-width: calc(var(--mian-max-width, var(--container, 1200px)) + 180px);
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: 100%;
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
}
|
||||
|
||||
.navbar-top .navbar-brand {
|
||||
padding: 7px 10px;
|
||||
}
|
||||
|
||||
.navbar-logo > img,
|
||||
.navbar-logo .site-brand__logo-img,
|
||||
.site-brand .site-brand__logo-img,
|
||||
.site-brand__logo-img {
|
||||
height: 36px !important;
|
||||
width: auto !important;
|
||||
max-width: min(180px, 40vw) !important;
|
||||
max-height: 36px !important;
|
||||
padding: 0 !important;
|
||||
object-fit: contain !important;
|
||||
}
|
||||
|
||||
.navbar-top .navbar-nav,
|
||||
.navbar-top ul.nav-desktop {
|
||||
margin-left: 20px;
|
||||
margin-right: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.navbar-top .navbar-nav > li > a,
|
||||
.navbar-top ul.nav-desktop > li > a {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
border-radius: 4px;
|
||||
display: inline-flex !important;
|
||||
align-items: center;
|
||||
min-height: 36px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.navbar-top .site-nav__row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
min-height: var(--nav-height, 60px);
|
||||
}
|
||||
|
||||
.navbar-top .nav-actions {
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
overflow: visible;
|
||||
position: relative;
|
||||
z-index: 25;
|
||||
}
|
||||
|
||||
.scroll-down.nav-fixed .header.scroll-down-hide,
|
||||
body.scroll-down.nav-fixed .header.scroll-down-hide {
|
||||
transform: translate3d(0, -105%, 0);
|
||||
-webkit-backdrop-filter: none;
|
||||
backdrop-filter: none;
|
||||
}
|
||||
|
||||
|
||||
/* Layout-1 style: keep search as icon; hide expanded desktop form */
|
||||
@media (min-width: 992px) {
|
||||
.navbar-top .nav-searchbox--desktop {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Transparent white controls on gradient hero */
|
||||
.header.show-slide .site-nav:not(.is-scrolled) .btn-outline {
|
||||
color: #fff;
|
||||
border-color: rgba(255, 255, 255, 0.55);
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.header.show-slide .site-nav:not(.is-scrolled) .btn-outline:hover {
|
||||
color: #fff;
|
||||
border-color: #fff;
|
||||
background: rgba(255, 255, 255, 0.12);
|
||||
}
|
||||
|
||||
.header.show-slide .site-nav:not(.is-scrolled) .nav-user__guest-avatar,
|
||||
.header.show-slide .site-nav:not(.is-scrolled) .icon-btn {
|
||||
color: #fff;
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
/* Cards submenu */
|
||||
.aksrt-nav__cards {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.aksrt-nav__card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 10px 12px;
|
||||
border-radius: 6px;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
transition: background 0.15s;
|
||||
}
|
||||
|
||||
.aksrt-nav__card:hover {
|
||||
background: var(--color-primary-soft, rgba(240, 68, 148, 0.06));
|
||||
}
|
||||
|
||||
.aksrt-nav__card-icon {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: var(--color-primary-soft, #e6f4ff);
|
||||
color: var(--color-primary);
|
||||
font-size: 16px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.aksrt-nav__card-text {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.aksrt-nav__card-title {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: var(--color-ink);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.aksrt-nav__card-desc {
|
||||
font-size: 11px;
|
||||
color: var(--color-ink-4);
|
||||
margin: 2px 0 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 导航溢出「更多」下拉
|
||||
* ============================================================ */
|
||||
.aksrt-nav-more {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.aksrt-nav-more__btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 6px 12px;
|
||||
border: none;
|
||||
background: none;
|
||||
color: var(--color-ink-2);
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
border-radius: var(--radius, 8px);
|
||||
transition: background 0.15s, color 0.15s;
|
||||
}
|
||||
|
||||
.aksrt-nav-more__btn:hover {
|
||||
background: var(--color-primary-soft, rgba(240, 68, 148, 0.08));
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
.aksrt-nav-more__dropdown {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
right: 0;
|
||||
min-width: 160px;
|
||||
padding: 6px 0;
|
||||
background: var(--surface-1, #fff);
|
||||
border: 1px solid var(--color-line, rgba(50, 50, 50, 0.06));
|
||||
border-radius: var(--radius, 8px);
|
||||
box-shadow: var(--shadow-lg, 0 0 10px rgba(116, 116, 116, 0.12));
|
||||
z-index: var(--z-dropdown, 100);
|
||||
list-style: none;
|
||||
margin: 4px 0 0;
|
||||
}
|
||||
|
||||
.aksrt-nav-more__dropdown.is-open {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.aksrt-nav-more__dropdown li {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.aksrt-nav-more__dropdown li a,
|
||||
.aksrt-nav-more__dropdown li button {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 8px 16px;
|
||||
border: none;
|
||||
background: none;
|
||||
color: var(--color-ink-2);
|
||||
font-size: 14px;
|
||||
text-align: left;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
transition: background 0.15s, color 0.15s;
|
||||
}
|
||||
|
||||
.aksrt-nav-more__dropdown li a:hover,
|
||||
.aksrt-nav-more__dropdown li button:hover {
|
||||
background: var(--color-primary-soft, rgba(240, 68, 148, 0.08));
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
/* Dark mode Mega Menu */
|
||||
html.dark ul.nav-desktop .mega-menu-item > .mega-menu__panel,
|
||||
body.dark-theme ul.nav-desktop .mega-menu-item > .mega-menu__panel {
|
||||
background: var(--surface-page);
|
||||
border-color: var(--color-line, #2d2d3f);
|
||||
}
|
||||
|
||||
html.dark .mega-menu__panel > .menu-item:hover,
|
||||
body.dark-theme .mega-menu__panel > .menu-item:hover {
|
||||
background: var(--surface-2);
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
/* Hover effects */
|
||||
.aksrt-nav__item--hover-underline > a::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
width: 0;
|
||||
height: 2px;
|
||||
background: var(--color-primary);
|
||||
transition: width 0.2s ease, left 0.2s ease;
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
.aksrt-nav__item--hover-underline:hover > a::after {
|
||||
width: 60%;
|
||||
left: 20%;
|
||||
}
|
||||
|
||||
.aksrt-nav__item--hover-background > a {
|
||||
transition: background-color 0.2s;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.aksrt-nav__item--hover-background:hover > a {
|
||||
background-color: var(--color-primary-soft, rgba(240, 68, 148, 0.08));
|
||||
}
|
||||
|
||||
.aksrt-nav__item--hover-color > a {
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.aksrt-nav__item--hover-color:hover > a {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
/* Mega submenu */
|
||||
.aksrt-nav__mega {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
z-index: 1001;
|
||||
background: var(--surface-1);
|
||||
border: 1px solid var(--color-line);
|
||||
border-radius: var(--radius);
|
||||
box-shadow: var(--shadow-lg);
|
||||
padding: 16px;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transform: translateY(8px);
|
||||
transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s ease;
|
||||
}
|
||||
|
||||
.aksrt-nav__item:hover > .aksrt-nav__mega {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.aksrt-nav__mega--columns {
|
||||
display: grid;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/* Menu item badge */
|
||||
.aksrt-nav__badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
padding: 2px 5px;
|
||||
border-radius: 3px;
|
||||
margin-left: 4px;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.aksrt-nav__badge--new {
|
||||
color: #fff;
|
||||
background: var(--color-error);
|
||||
}
|
||||
|
||||
.aksrt-nav__badge--hot {
|
||||
color: #fff;
|
||||
background: var(--color-warning);
|
||||
}
|
||||
|
||||
.aksrt-nav__badge--info {
|
||||
color: #fff;
|
||||
background: var(--color-info);
|
||||
}
|
||||
|
||||
.aksrt-nav__badge--success {
|
||||
color: #fff;
|
||||
background: var(--color-success);
|
||||
}
|
||||
|
||||
.aksrt-nav__badge--vip {
|
||||
color: #fff;
|
||||
background: linear-gradient(135deg, var(--color-warning), var(--color-error));
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
/* Menu item icon */
|
||||
.aksrt-nav__icon {
|
||||
font-size: 0.85em;
|
||||
width: 1.2em;
|
||||
text-align: center;
|
||||
margin-right: 4px;
|
||||
opacity: 0.7;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.aksrt-nav__item--has-icon > a {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.aksrt-nav__item--has-icon:hover .aksrt-nav__icon {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
/* Mobile theme toggle in drawer */
|
||||
.nav-drawer__theme-toggle {
|
||||
padding: 0 20px 16px;
|
||||
}
|
||||
|
||||
.nav-drawer__theme-toggle .theme-toggle-mobile {
|
||||
width: 100%;
|
||||
min-height: 44px;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Menu Decoration — Icons, Badges, Hover Effects
|
||||
* ============================================================ */
|
||||
|
||||
@@ -1,814 +0,0 @@
|
||||
/* Mobile toggle */
|
||||
.nav-toggle {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
@media (max-width: 991px) {
|
||||
.site-brand {
|
||||
max-width: min(46vw, 311px);
|
||||
}
|
||||
|
||||
.site-brand__media {
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.nav-publish-btn {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Desktop search icon: hide on mobile (use drawer search instead) */
|
||||
@media (max-width: 767px) {
|
||||
.site-brand {
|
||||
max-width: min(62vw, 260px);
|
||||
padding: 7px 0;
|
||||
}
|
||||
|
||||
.site-brand__media {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#search-toggle {
|
||||
display: none;
|
||||
}
|
||||
/* Search panel only makes sense alongside the desktop search icon */
|
||||
.nav-search-panel {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
ul.nav-desktop,
|
||||
.nav-desktop--fallback {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.nav-auth {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.nav-auth-dropdown {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.nav-toggle {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Header Layout Variants (desktop ≥768px)
|
||||
* Layout 1: Standard — brand left, nav flex-1, actions right
|
||||
* Layout 2: Centered — brand left, nav centered with flex, actions right
|
||||
* Layout 3: Compact — brand left, nav pushed right, actions right
|
||||
* ============================================================ */
|
||||
@media (min-width: 768px) {
|
||||
/* Layout 2: center the nav between brand and actions */
|
||||
body.header-layout-2 .nav-desktop {
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
body.header-layout-2 .nav-actions {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Layout 3: push nav to the right side */
|
||||
body.header-layout-3 .site-nav__row {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
body.header-layout-3 .nav-desktop {
|
||||
flex: 1;
|
||||
justify-content: flex-end;
|
||||
margin-left: 24px;
|
||||
}
|
||||
|
||||
body.header-layout-3 .nav-actions {
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-mobile-strip {
|
||||
display: none;
|
||||
width: calc(100% + 8px);
|
||||
margin: 0 -4px;
|
||||
padding: 0 0 12px;
|
||||
}
|
||||
|
||||
.nav-mobile-strip__menu,
|
||||
.nav-mobile-strip__menu ul {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
overflow-x: auto;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
}
|
||||
|
||||
.nav-mobile-strip__menu::-webkit-scrollbar,
|
||||
.nav-mobile-strip__menu ul::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nav-mobile-strip__menu a {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 34px;
|
||||
padding: 0 12px;
|
||||
border-radius: var(--radius-pill, 999px);
|
||||
background: var(--surface-2);
|
||||
color: var(--color-ink-2);
|
||||
white-space: nowrap;
|
||||
text-decoration: none;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.nav-mobile-strip__menu .current-menu-item > a,
|
||||
.nav-mobile-strip__menu .current_page_item > a {
|
||||
background: var(--color-primary);
|
||||
color: var(--color-on-primary, #fff);
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.nav-mobile-strip {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* User avatar + dropdown
|
||||
* ============================================================ */
|
||||
.nav-user {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nav-user__toggle {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: var(--radius-avatar);
|
||||
padding: 0;
|
||||
border: none; /* 对齐 zibll:头像无边框 */
|
||||
cursor: pointer;
|
||||
/* Allow unread corner badge to paint outside the avatar circle. */
|
||||
overflow: visible;
|
||||
background: var(--surface-2);
|
||||
transition: box-shadow var(--dur-fast, 0.15s) var(--ease);
|
||||
}
|
||||
|
||||
.nav-user__toggle:hover {
|
||||
box-shadow: 0 0 0 2px var(--color-primary-soft);
|
||||
}
|
||||
|
||||
.nav-user__toggle img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
border-radius: inherit;
|
||||
}
|
||||
|
||||
.user-dropdown {
|
||||
position: absolute;
|
||||
top: calc(100% + 8px);
|
||||
right: 0;
|
||||
width: 260px;
|
||||
max-width: calc(100vw - 32px);
|
||||
padding: 12px 0;
|
||||
background: var(--surface-1);
|
||||
border: 1px solid var(--color-line);
|
||||
border-radius: var(--radius-lg, 8px);
|
||||
box-shadow: var(--shadow-lg);
|
||||
z-index: 1100;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transform: translateY(-6px);
|
||||
transition: opacity 0.2s, transform 0.2s, visibility 0.2s;
|
||||
}
|
||||
|
||||
.user-dropdown.is-open {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.user-dropdown__profile {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 8px 16px 14px;
|
||||
}
|
||||
|
||||
.user-dropdown__profile img {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: var(--radius-avatar);
|
||||
object-fit: cover;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.user-dropdown__name {
|
||||
font-weight: 700;
|
||||
font-size: 0.9375rem;
|
||||
color: var(--color-ink);
|
||||
}
|
||||
|
||||
.user-dropdown__email {
|
||||
font-size: 0.75rem;
|
||||
color: var(--color-ink-4);
|
||||
word-break: break-all;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.user-dropdown__sep {
|
||||
height: 1px;
|
||||
background: var(--color-line);
|
||||
margin: 6px 0;
|
||||
}
|
||||
|
||||
.user-dropdown a,
|
||||
.user-dropdown button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
width: 100%;
|
||||
padding: 0 16px;
|
||||
height: 44px;
|
||||
border: none;
|
||||
background: none;
|
||||
font-size: 0.875rem;
|
||||
color: var(--color-ink);
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
transition: background var(--dur-fast, 0.15s) var(--ease),
|
||||
color var(--dur-fast, 0.15s) var(--ease);
|
||||
}
|
||||
|
||||
.user-dropdown a:hover,
|
||||
.user-dropdown button:hover {
|
||||
background: var(--surface-3);
|
||||
color: var(--color-primary-active);
|
||||
}
|
||||
|
||||
/* dropdown 项内的 SVG 图标 */
|
||||
.user-dropdown__item svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
flex-shrink: 0;
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.user-dropdown__item span:first-of-type:not(.user-dropdown__pill) {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* 未读消息数 badge */
|
||||
.user-dropdown__badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 18px;
|
||||
height: 18px;
|
||||
padding: 0 5px;
|
||||
margin-left: auto;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
background: var(--color-error, #ef4444);
|
||||
border-radius: 9px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.user-dropdown__credits {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 0 16px;
|
||||
height: 44px;
|
||||
font-size: 0.875rem;
|
||||
color: var(--color-ink-2);
|
||||
}
|
||||
|
||||
.user-dropdown__credits i {
|
||||
color: var(--color-warning);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.user-dropdown__credits-label {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.user-dropdown__credits-value {
|
||||
font-weight: 600;
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
.user-dropdown__logout {
|
||||
color: var(--color-error) !important;
|
||||
}
|
||||
|
||||
.user-dropdown__logout svg {
|
||||
color: var(--color-error);
|
||||
}
|
||||
|
||||
.user-dropdown__logout:hover {
|
||||
background: rgba(239, 68, 68, 0.08) !important;
|
||||
color: var(--color-error) !important;
|
||||
}
|
||||
|
||||
.user-dropdown .badge-dot {
|
||||
margin-left: auto;
|
||||
min-width: 8px;
|
||||
height: 8px;
|
||||
border-radius: var(--radius-pill);
|
||||
background: var(--color-error);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Search panel
|
||||
* ============================================================ */
|
||||
.nav-search-panel {
|
||||
display: none;
|
||||
padding: 12px 0 16px;
|
||||
border-top: 1px solid var(--color-line);
|
||||
}
|
||||
|
||||
.nav-search-panel.is-open {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.nav-searchbox {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.nav-searchbox__field {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
min-height: 42px;
|
||||
padding: 0 6px 0 14px;
|
||||
border: 1px solid var(--color-line);
|
||||
border-radius: var(--radius-pill, 999px);
|
||||
background: var(--surface-3);
|
||||
box-sizing: border-box;
|
||||
transition: border-color var(--dur-fast, 0.15s) var(--ease), box-shadow var(--dur-fast, 0.15s) var(--ease), background var(--dur-fast, 0.15s) var(--ease);
|
||||
}
|
||||
|
||||
.nav-searchbox__icon {
|
||||
order: 1;
|
||||
flex: 0 0 16px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
color: var(--color-ink-4);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.nav-searchbox__input {
|
||||
order: 2;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
width: auto;
|
||||
height: 40px;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: var(--color-ink);
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.2;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.nav-searchbox__input:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.nav-searchbox__input::placeholder {
|
||||
color: var(--color-ink-4);
|
||||
}
|
||||
|
||||
.nav-searchbox__submit {
|
||||
order: 3;
|
||||
flex: 0 0 auto;
|
||||
height: 30px;
|
||||
min-width: 64px;
|
||||
padding: 0 14px;
|
||||
border: 0;
|
||||
border-radius: var(--radius-pill, 999px);
|
||||
background: var(--color-primary);
|
||||
color: #fff;
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nav-searchbox__field:focus-within {
|
||||
border-color: var(--color-primary);
|
||||
box-shadow: 0 0 0 3px var(--color-primary-soft);
|
||||
background: var(--surface-1);
|
||||
}
|
||||
|
||||
.nav-searchbox__submit:hover {
|
||||
background: var(--color-primary-active);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Mobile drawer / mobile header
|
||||
* ============================================================ */
|
||||
.mobile-header.nav-drawer-backdrop {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.45);
|
||||
z-index: 1200;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: opacity 0.3s ease, visibility 0.3s;
|
||||
}
|
||||
|
||||
.mobile-header.nav-drawer-backdrop.is-open {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.mobile-header.nav-drawer {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: min(100vw, 360px);
|
||||
height: 100vh;
|
||||
max-height: 100dvh;
|
||||
background: var(--surface-page);
|
||||
z-index: 1210;
|
||||
box-shadow: var(--shadow-drawer);
|
||||
transform: translateX(100%);
|
||||
transition: transform 0.32s var(--ease-out, ease);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
pointer-events: none;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.mobile-header.nav-drawer.is-open {
|
||||
transform: translateX(0);
|
||||
pointer-events: auto;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.mobile-navbar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.mobile-navbar .navbar-brand {
|
||||
max-width: calc(100% - 52px);
|
||||
padding: 7px 0;
|
||||
}
|
||||
|
||||
.mobile-navbar .navbar-logo {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.nav-drawer-backdrop {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.45);
|
||||
z-index: 1200;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: opacity 0.3s ease, visibility 0.3s;
|
||||
}
|
||||
|
||||
.nav-drawer-backdrop.is-open {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.nav-drawer {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: min(100vw, 360px);
|
||||
height: 100vh;
|
||||
max-height: 100dvh;
|
||||
background: var(--surface-page);
|
||||
z-index: 1210;
|
||||
box-shadow: var(--shadow-drawer);
|
||||
transform: translateX(100%);
|
||||
transition: transform 0.32s var(--ease-out, ease);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
pointer-events: none;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.nav-drawer.is-open {
|
||||
transform: translateX(0);
|
||||
pointer-events: auto;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.nav-drawer__head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
padding: 16px 20px;
|
||||
border-bottom: 1px solid var(--color-line);
|
||||
font-weight: 700;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.site-brand--drawer {
|
||||
max-width: calc(100% - 52px);
|
||||
padding: 7px 0;
|
||||
}
|
||||
|
||||
.site-brand--drawer .site-brand__media {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.nav-drawer__search {
|
||||
padding: 16px 20px 0;
|
||||
}
|
||||
|
||||
.nav-drawer__search .nav-searchbox__field {
|
||||
min-height: 40px;
|
||||
}
|
||||
|
||||
.nav-drawer__search .nav-searchbox__input {
|
||||
height: 38px;
|
||||
}
|
||||
|
||||
.nav-drawer__search .nav-searchbox__submit {
|
||||
height: 28px;
|
||||
min-width: 58px;
|
||||
padding: 0 12px;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.nav-searchbox__meta {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.nav-searchbox__types {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.nav-searchbox__type {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 32px;
|
||||
padding: 0 12px;
|
||||
border: 1px solid var(--color-line);
|
||||
border-radius: var(--radius-pill, 999px);
|
||||
background: var(--surface-2);
|
||||
color: var(--color-ink-3);
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nav-searchbox__type.is-active {
|
||||
border-color: var(--color-primary);
|
||||
background: var(--color-primary-soft);
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
.nav-searchbox__category-wrap {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nav-searchbox__category {
|
||||
appearance: none;
|
||||
width: 100%;
|
||||
min-height: 36px;
|
||||
padding: 0 34px 0 12px;
|
||||
border: 1px solid var(--color-line);
|
||||
border-radius: var(--radius-pill, 999px);
|
||||
background: var(--surface-2);
|
||||
color: var(--color-ink);
|
||||
font: 500 0.875rem/1 var(--font-ui);
|
||||
}
|
||||
|
||||
.nav-searchbox__category-wrap::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 5px solid transparent;
|
||||
border-right: 5px solid transparent;
|
||||
border-top: 5px solid var(--color-ink-3);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.nav-searchbox__category:disabled {
|
||||
opacity: 0.56;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.nav-drawer__menu {
|
||||
flex: 1;
|
||||
padding: 16px 20px 32px;
|
||||
}
|
||||
|
||||
.nav-drawer__menu a {
|
||||
display: block;
|
||||
padding: 14px 0;
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
color: var(--color-ink);
|
||||
border-bottom: 1px solid var(--color-line-soft);
|
||||
}
|
||||
|
||||
.nav-drawer__menu a:hover {
|
||||
color: var(--color-primary-active);
|
||||
}
|
||||
|
||||
.nav-drawer__menu ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.nav-drawer__auth {
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
border-top: 1px solid var(--color-line);
|
||||
}
|
||||
|
||||
.nav-drawer__auth .btn-outline,
|
||||
.nav-drawer__auth .btn-primary {
|
||||
width: 100%;
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.nav-drawer__publish {
|
||||
padding: 0 20px 20px;
|
||||
}
|
||||
|
||||
.nav-drawer__publish .btn-primary {
|
||||
width: 100%;
|
||||
min-height: 44px;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ============================================================
|
||||
* Header user box (Zibll-like sub-user-box grid)
|
||||
* ============================================================ */
|
||||
.nav-user__toggle {
|
||||
position: relative;
|
||||
}
|
||||
.nav-user__dot {
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
right: -1px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background: var(--color-error, #ef4444);
|
||||
border: 2px solid var(--surface-1, #fff);
|
||||
box-sizing: content-box;
|
||||
pointer-events: none;
|
||||
z-index: 2;
|
||||
}
|
||||
.nav-user__guest-avatar {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: var(--surface-2);
|
||||
color: var(--color-ink-3);
|
||||
}
|
||||
.user-dropdown {
|
||||
width: 300px;
|
||||
padding: 14px 12px 12px;
|
||||
}
|
||||
.user-dropdown__profile.user-info {
|
||||
position: relative;
|
||||
padding-right: 42px;
|
||||
}
|
||||
.user-dropdown__meta {
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
}
|
||||
.user-dropdown__name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
/* Beat generic `.user-dropdown a { width:100%; height:44px }` sizing. */
|
||||
.user-dropdown a.user-dropdown__msg,
|
||||
.user-dropdown__msg {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
width: 34px !important;
|
||||
height: 34px !important;
|
||||
min-width: 34px;
|
||||
max-width: 34px;
|
||||
border-radius: 50%;
|
||||
display: inline-flex !important;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0 !important;
|
||||
padding: 0 !important;
|
||||
background: var(--surface-2);
|
||||
color: var(--color-ink-3);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.user-dropdown a.user-dropdown__msg:hover,
|
||||
.user-dropdown__msg:hover {
|
||||
background: var(--surface-3);
|
||||
color: var(--color-primary);
|
||||
}
|
||||
.user-dropdown__msg .user-dropdown__badge {
|
||||
position: absolute;
|
||||
top: -4px;
|
||||
right: -4px;
|
||||
margin: 0;
|
||||
}
|
||||
.user-dropdown__guest-title {
|
||||
padding: 4px 8px 12px;
|
||||
text-align: center;
|
||||
font-weight: 700;
|
||||
color: var(--color-ink);
|
||||
}
|
||||
.user-dropdown__actions {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 8px 4px;
|
||||
padding: 4px 2px 2px;
|
||||
}
|
||||
.user-dropdown__actions--admin {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
.user-dropdown__action {
|
||||
display: flex !important;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
gap: 6px !important;
|
||||
width: auto !important;
|
||||
height: auto !important;
|
||||
min-height: 0;
|
||||
padding: 6px 4px !important;
|
||||
text-align: center !important;
|
||||
font-size: 12px !important;
|
||||
line-height: 1.25;
|
||||
color: var(--color-ink-3) !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
.user-dropdown__action:hover {
|
||||
background: transparent !important;
|
||||
color: var(--color-primary) !important;
|
||||
}
|
||||
.user-dropdown__action-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 15px;
|
||||
color: #fff;
|
||||
}
|
||||
.user-dropdown__action-icon.is-blue { background: linear-gradient(135deg, #60a5fa, #3b82f6); }
|
||||
.user-dropdown__action-icon.is-purple { background: linear-gradient(135deg, #a78bfa, #8b5cf6); }
|
||||
.user-dropdown__action-icon.is-green { background: linear-gradient(135deg, #34d399, #10b981); }
|
||||
.user-dropdown__action-icon.is-red { background: linear-gradient(135deg, #f87171, #ef4444); }
|
||||
.user-dropdown__action-icon.is-yellow { background: linear-gradient(135deg, #fbbf24, #f59e0b); color: #1f2937; }
|
||||
.user-dropdown__action.is-danger {
|
||||
color: var(--color-error, #ef4444) !important;
|
||||
}
|
||||
.user-dropdown__credits {
|
||||
margin-top: 2px;
|
||||
border-radius: 12px;
|
||||
background: var(--surface-2);
|
||||
margin-left: 4px;
|
||||
margin-right: 4px;
|
||||
width: auto;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
/* ===== nav_fixed mobile fallback ===== */
|
||||
/* On mobile, static nav should remain sticky so the hamburger toggle stays accessible */
|
||||
@media (max-width: 767px) {
|
||||
.has-static-nav .site-nav--static {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
/* Responsive Mega Menu */
|
||||
@media (max-width: 767px) {
|
||||
ul.nav-desktop .mega-menu-item > .mega-menu__panel {
|
||||
position: static;
|
||||
transform: none;
|
||||
width: 100%;
|
||||
max-width: none;
|
||||
margin: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.mega-menu__columns-2,
|
||||
.mega-menu__columns-3,
|
||||
.mega-menu__columns-4,
|
||||
.mega-menu__columns-5 {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Right actions (icons + auth)
|
||||
* ============================================================ */
|
||||
.nav-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
flex-shrink: 0;
|
||||
margin-left: auto;
|
||||
overflow: visible;
|
||||
position: relative;
|
||||
z-index: 25;
|
||||
}
|
||||
|
||||
.nav-settings-link,
|
||||
.nav-publish-btn {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.nav-settings-link svg {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
.nav-publish-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
height: 36px;
|
||||
padding: 0 14px;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.nav-publish-btn i {
|
||||
font-size: 0.8125rem;
|
||||
}
|
||||
|
||||
.theme-toggle.is-animating svg {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Auth buttons (in nav, when logged out)
|
||||
* ============================================================ */
|
||||
.nav-auth {
|
||||
display: none;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
/* btn-outline / btn-primary 复用 core/buttons.css 的定义,
|
||||
* 这里仅做导航专用调整(高度对齐、字体) */
|
||||
.nav-auth .btn-outline,
|
||||
.nav-auth .btn-primary {
|
||||
height: 36px;
|
||||
font-size: 0.875rem;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
/* Auth dropdown variant (layouts 1/3) — icon trigger + panel */
|
||||
.nav-auth-dropdown {
|
||||
position: relative;
|
||||
display: none;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-auth-dropdown__trigger {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
.nav-auth-dropdown__trigger svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.nav-auth-dropdown__panel {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: calc(100% + 8px);
|
||||
right: 0;
|
||||
min-width: 180px;
|
||||
z-index: 1100;
|
||||
}
|
||||
|
||||
.nav-auth-dropdown.is-open .nav-auth-dropdown__panel {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
/* Utilities for zibll header chrome */
|
||||
.css-icon.i-menu {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 1.15em;
|
||||
height: 1em;
|
||||
vertical-align: -0.1em;
|
||||
}
|
||||
.css-icon.i-menu > i,
|
||||
.css-icon.i-menu::before,
|
||||
.css-icon.i-menu::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 2px;
|
||||
background: currentColor;
|
||||
border-radius: 1px;
|
||||
transition: 0.25s;
|
||||
}
|
||||
.css-icon.i-menu > i { top: 50%; margin-top: -1px; }
|
||||
.css-icon.i-menu::before { top: 0; }
|
||||
.css-icon.i-menu::after { bottom: 0; }
|
||||
|
||||
.list-inline { padding-left: 0; list-style: none; margin: 0; }
|
||||
.list-inline > li { display: inline-block; vertical-align: middle; }
|
||||
.list-inline.splitters > li + li { margin-left: 6px; }
|
||||
|
||||
.navbar-top .flex.ac { display: flex; align-items: center; }
|
||||
.navbar-top .flex.jsb { display: flex; justify-content: space-between; }
|
||||
.navbar-top .flex.jsa { display: flex; justify-content: space-around; }
|
||||
.navbar-top .flex.jc { display: flex; justify-content: center; }
|
||||
.mb6 { margin-bottom: 6px; }
|
||||
.mb10 { margin-bottom: 10px; }
|
||||
.mb20 { margin-bottom: 20px; }
|
||||
.mt6 { margin-top: 6px; }
|
||||
.mt10 { margin-top: 10px; }
|
||||
.ml6 { margin-left: 6px; }
|
||||
.ml10 { margin-left: 10px; }
|
||||
.em09 { font-size: 0.9em; }
|
||||
.em12 { font-size: 1.2em; }
|
||||
.muted-2-color { opacity: 0.7; }
|
||||
.muted-3-color { opacity: 0.55; }
|
||||
.text-ellipsis { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.padding-10 { padding: 10px; }
|
||||
.relative { position: relative; }
|
||||
.inline-block { display: inline-block; }
|
||||
.hide { display: none !important; }
|
||||
.pull-right { float: right; }
|
||||
.null { background: none; border: 0; padding: 0; color: inherit; }
|
||||
.abs-right { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); }
|
||||
|
||||
/* Mid breakpoint fold trigger (zibll ~991) */
|
||||
@media (max-width: 991px) {
|
||||
.navbar-top .show-nav-but { display: block !important; }
|
||||
.navbar-top .nav.navbar-nav:not(.show) {
|
||||
display: none;
|
||||
}
|
||||
.navbar-top .nav.navbar-nav.show {
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0; right: 0;
|
||||
top: 100%;
|
||||
background: var(--main-bg-color, #fff);
|
||||
z-index: 1001;
|
||||
padding: 10px;
|
||||
box-shadow: 0 8px 20px rgba(0,0,0,.08);
|
||||
}
|
||||
}
|
||||
|
||||
/* Language dropdown */
|
||||
.language-dropdown { position: relative; }
|
||||
.language-dropdown .dropdown-menu,
|
||||
.language-dropdown .hover-show-con {
|
||||
min-width: 140px;
|
||||
right: 0;
|
||||
left: auto;
|
||||
padding: 8px 0;
|
||||
}
|
||||
.language-dropdown .translate-button { display: flex; align-items: center; padding: 6px 14px; }
|
||||
.language-dropdown .translate-button.active { color: var(--focus-color); }
|
||||
|
||||
/* Layout2 inline search focus panel */
|
||||
.navbar-collapse .search-input {
|
||||
min-width: 160px;
|
||||
max-width: 240px;
|
||||
height: 34px;
|
||||
border-radius: 20px;
|
||||
border: 0;
|
||||
padding: 0 36px 0 14px;
|
||||
}
|
||||
.navbar-form.navbar-left.hover-show { margin: 0 8px; }
|
||||
.navbar-form .form-group.relative { position: relative; }
|
||||
.navbar-form .abs-right { right: 10px; }
|
||||
|
||||
/* Mobile drawer body scroll lock */
|
||||
body.mobile-navbar-show { overflow: hidden; }
|
||||
|
||||
/* Ensure container-header flex row */
|
||||
.container-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
max-width: var(--nav-max-width, 100%);
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
}
|
||||
.navbar-collapse {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
.navbar-header { display: flex; align-items: center; flex-shrink: 0; }
|
||||
.navbar-top .navbar-toggle { display: none; background: none; border: 0; color: inherit; }
|
||||
@media (max-width: 767px) {
|
||||
.navbar-top .navbar-toggle { display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; }
|
||||
.navbar-collapse { display: none; }
|
||||
}
|
||||
|
||||
/* Senior submenu full width under fixed header */
|
||||
.navbar-top .sub-menu.senior-submenu {
|
||||
position: fixed;
|
||||
left: 0; right: 0;
|
||||
top: 59px;
|
||||
width: 100%;
|
||||
min-width: 100%;
|
||||
padding: 20px 0;
|
||||
border-radius: 0;
|
||||
z-index: 998;
|
||||
}
|
||||
+51
-24
@@ -1,13 +1,15 @@
|
||||
/**
|
||||
* AKSRT nav chrome — zibll contract (body.mobile-navbar-show, folding, chevron).
|
||||
* Drawer open/close is handled by aksrt-runtime [data-toggle-class].
|
||||
* AKSRT nav chrome — zibll contract (folding, chevron, language, drawer a11y).
|
||||
* Drawer open/close via aksrt-runtime [data-toggle-class] → body.mobile-navbar-show.
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function appendChevrons() {
|
||||
document.querySelectorAll(".navbar-top li.menu-item-has-children > a").forEach(function (a) {
|
||||
if (a.querySelector(".fa-angle-down")) return;
|
||||
var foldTimer = null;
|
||||
|
||||
function appendChevrons(root) {
|
||||
(root || document).querySelectorAll(".navbar-top li.menu-item-has-children > a").forEach(function (a) {
|
||||
if (a.querySelector(".fa-angle-down, .fas.fa-angle-down")) return;
|
||||
var i = document.createElement("i");
|
||||
i.className = "fa fa-angle-down ml6";
|
||||
i.setAttribute("aria-hidden", "true");
|
||||
@@ -15,18 +17,30 @@
|
||||
});
|
||||
}
|
||||
|
||||
function clearFolding() {
|
||||
var more = document.querySelector(".navbar-nav > li.aksrt-nav-more");
|
||||
if (!more) return;
|
||||
var sub = more.querySelector(".sub-menu");
|
||||
var nav = more.parentNode;
|
||||
if (sub && nav) {
|
||||
while (sub.firstChild) {
|
||||
nav.insertBefore(sub.firstChild, more);
|
||||
}
|
||||
}
|
||||
more.remove();
|
||||
}
|
||||
|
||||
function navFolding() {
|
||||
var collapse = document.querySelector(".navbar-collapse");
|
||||
var nav = document.querySelector(".navbar-nav");
|
||||
if (!collapse || !nav) return;
|
||||
if (window.innerWidth <= 996) return;
|
||||
|
||||
clearFolding();
|
||||
|
||||
if (window.innerWidth <= 996) return;
|
||||
var header = document.querySelector(".header");
|
||||
if (header && header.offsetHeight <= 81) return;
|
||||
|
||||
// Already folded?
|
||||
if (nav.querySelector("li.aksrt-nav-more")) return;
|
||||
|
||||
var surplus = collapse.clientWidth;
|
||||
Array.prototype.forEach.call(collapse.children, function (child) {
|
||||
if (!child.classList.contains("navbar-nav")) {
|
||||
@@ -40,9 +54,7 @@
|
||||
var foldItems = [];
|
||||
Array.prototype.forEach.call(nav.children, function (li) {
|
||||
navsWidth += li.offsetWidth || 0;
|
||||
if (navsWidth > surplus) {
|
||||
foldItems.push(li);
|
||||
}
|
||||
if (navsWidth > surplus) foldItems.push(li);
|
||||
});
|
||||
if (!foldItems.length) return;
|
||||
|
||||
@@ -51,14 +63,33 @@
|
||||
more.innerHTML =
|
||||
'<a href="javascript:void(0);"><i class="fas fa-bars" aria-hidden="true"></i></a><ul class="sub-menu"></ul>';
|
||||
var sub = more.querySelector(".sub-menu");
|
||||
foldItems.forEach(function (li) {
|
||||
sub.appendChild(li);
|
||||
});
|
||||
foldItems.forEach(function (li) { sub.appendChild(li); });
|
||||
nav.appendChild(more);
|
||||
appendChevrons(more);
|
||||
}
|
||||
|
||||
function scheduleFold() {
|
||||
if (foldTimer) clearTimeout(foldTimer);
|
||||
foldTimer = setTimeout(function () {
|
||||
try { navFolding(); } catch (e) {}
|
||||
}, 80);
|
||||
}
|
||||
|
||||
function bindLanguage() {
|
||||
document.addEventListener("click", function (e) {
|
||||
var btn = e.target && e.target.closest ? e.target.closest(".translate-button[data-language]") : null;
|
||||
if (!btn) return;
|
||||
e.preventDefault();
|
||||
var lang = btn.getAttribute("data-language");
|
||||
if (!lang) return;
|
||||
try { localStorage.setItem("aksrt_lang", lang); } catch (err) {}
|
||||
var url = new URL(window.location.href);
|
||||
url.searchParams.set("lang", lang);
|
||||
window.location.href = url.toString();
|
||||
});
|
||||
}
|
||||
|
||||
function bindDrawerA11y() {
|
||||
// Esc closes mobile nav via body class.
|
||||
document.addEventListener("keydown", function (e) {
|
||||
if (e.key === "Escape" && document.body.classList.contains("mobile-navbar-show")) {
|
||||
document.body.classList.remove("mobile-navbar-show");
|
||||
@@ -68,18 +99,14 @@
|
||||
|
||||
function init() {
|
||||
appendChevrons();
|
||||
try {
|
||||
navFolding();
|
||||
} catch (err) {
|
||||
// ignore fold failures
|
||||
}
|
||||
scheduleFold();
|
||||
bindLanguage();
|
||||
bindDrawerA11y();
|
||||
window.addEventListener("resize", scheduleFold, { passive: true });
|
||||
}
|
||||
|
||||
if (window.AksrtFrontend && typeof window.AksrtFrontend.register === "function") {
|
||||
window.AksrtFrontend.register("aksrt-nav-chrome", function () {
|
||||
init();
|
||||
});
|
||||
window.AksrtFrontend.register("aksrt-nav-chrome", function () { init(); });
|
||||
} else if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", init);
|
||||
} else {
|
||||
|
||||
+127
-155
@@ -1,9 +1,7 @@
|
||||
/**
|
||||
* AKSRT Section Navs — Article TOC / Scrollspy
|
||||
* AKSRT Section Navs — zibll section_navs parity (posts-nav-lists + scrollspy).
|
||||
*
|
||||
* Auto-generates a table of contents from h1~h4 headings within
|
||||
* [data-nav] content areas. Scrollspy highlights the current section.
|
||||
* Collapsible sub-items when the TOC is tall.
|
||||
* Builds TOC from [data-nav] h1–h4 into .posts-nav-box / .posts-nav-lists.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
@@ -12,164 +10,138 @@
|
||||
|
||||
var HEADING_SEL = 'h1, h2, h3, h4';
|
||||
var MIN_HEADINGS = 2;
|
||||
var SCROLL_OFFSET = 105;
|
||||
var MAX_HEIGHT_COLLAPSE = 380;
|
||||
var NAVBOX = '.posts-nav-box';
|
||||
var NAV_CLASS = 'posts-nav-lists';
|
||||
|
||||
function initSectionNavs() {
|
||||
var navContainer = document.querySelector('[data-nav]');
|
||||
if (!navContainer) return;
|
||||
function isExcluded(el) {
|
||||
return el.classList.contains('item-heading') || !!el.closest('.no-nav');
|
||||
}
|
||||
|
||||
// Single-post TOC is owned by page-template.js (.posts-nav-box .toc-list).
|
||||
// Do not invent a second .aksrt-section-nav tree on article singles.
|
||||
if (document.querySelector('.posts-nav-box .toc-list, .posts-nav-box.toc-widget')) {
|
||||
function ensureId(el, index) {
|
||||
if (!el.id) {
|
||||
el.id = 'section-nav-' + index;
|
||||
}
|
||||
return el.id;
|
||||
}
|
||||
|
||||
function buildLists(root) {
|
||||
var headings = root.querySelectorAll(HEADING_SEL);
|
||||
var html = '';
|
||||
var count = 0;
|
||||
headings.forEach(function (h, i) {
|
||||
if (isExcluded(h)) return;
|
||||
var id = ensureId(h, i);
|
||||
var tag = h.tagName.toUpperCase();
|
||||
var text = (h.textContent || '').trim();
|
||||
if (!text) return;
|
||||
html += '<li class="n-' + tag + '"><a href="#' + id + '">' + text + '</a></li>';
|
||||
count++;
|
||||
});
|
||||
return count >= MIN_HEADINGS ? html : '';
|
||||
}
|
||||
|
||||
function fillBoxes(listsHtml) {
|
||||
document.querySelectorAll(NAVBOX).forEach(function (box) {
|
||||
var existing = box.querySelector('.' + NAV_CLASS);
|
||||
if (existing) {
|
||||
existing.innerHTML = listsHtml;
|
||||
return;
|
||||
}
|
||||
var title = box.getAttribute('data-title') || '';
|
||||
var titleHtml = title
|
||||
? '<div class="box-body notop"><div class="title-theme">' + title + '</div></div>'
|
||||
: '';
|
||||
box.insertAdjacentHTML(
|
||||
'beforeend',
|
||||
titleHtml +
|
||||
'<div class="zib-widget"><div class="' +
|
||||
NAV_CLASS +
|
||||
' scroll-y mini-scrollbar list-unstyled">' +
|
||||
listsHtml +
|
||||
'</div></div>'
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function smoothTo(hash) {
|
||||
var el = document.querySelector(hash);
|
||||
if (!el) return;
|
||||
var offset = 0;
|
||||
var header = document.querySelector('.header');
|
||||
if (document.body.classList.contains('nav-fixed') && header) {
|
||||
offset = header.offsetHeight + 12;
|
||||
}
|
||||
var top = el.getBoundingClientRect().top + window.pageYOffset - offset;
|
||||
window.scrollTo({ top: top, behavior: 'smooth' });
|
||||
}
|
||||
|
||||
function bindClicks() {
|
||||
document.addEventListener('click', function (e) {
|
||||
var a = e.target && e.target.closest ? e.target.closest('.' + NAV_CLASS + ' a[href^="#"]') : null;
|
||||
if (!a) return;
|
||||
var href = a.getAttribute('href');
|
||||
if (!href || href.length < 2) return;
|
||||
e.preventDefault();
|
||||
history.replaceState(null, '', href);
|
||||
smoothTo(href);
|
||||
});
|
||||
}
|
||||
|
||||
function scrollspy() {
|
||||
var links = document.querySelectorAll('.' + NAV_CLASS + ' a[href^="#"]');
|
||||
if (!links.length) return;
|
||||
var map = [];
|
||||
links.forEach(function (a) {
|
||||
var id = a.getAttribute('href').slice(1);
|
||||
var el = document.getElementById(id);
|
||||
if (el) map.push({ el: el, a: a, li: a.parentElement });
|
||||
});
|
||||
function update() {
|
||||
var y = window.scrollY + 110;
|
||||
var current = null;
|
||||
for (var i = 0; i < map.length; i++) {
|
||||
if (map[i].el.offsetTop <= y) current = map[i];
|
||||
}
|
||||
map.forEach(function (m) {
|
||||
if (m.li) m.li.classList.toggle('active', m === current);
|
||||
});
|
||||
}
|
||||
window.addEventListener('scroll', update, { passive: true });
|
||||
update();
|
||||
}
|
||||
|
||||
function autoHash() {
|
||||
if (window.location.hash) {
|
||||
setTimeout(function () {
|
||||
smoothTo(window.location.hash);
|
||||
}, 40);
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
if (document.querySelector('.posts-nav-box .toc-list, .posts-nav-box.toc-widget .toc-list')) {
|
||||
return;
|
||||
}
|
||||
|
||||
var headings = navContainer.querySelectorAll(HEADING_SEL);
|
||||
if (headings.length < MIN_HEADINGS) return;
|
||||
|
||||
var tocContainer = document.querySelector('.posts-nav-lists, .aksrt-section-nav');
|
||||
if (!tocContainer) {
|
||||
// Docs / page-navs only: create a dedicated container. Never inject into single sidebars.
|
||||
if (document.body.classList.contains('single') || document.body.classList.contains('single-post')) {
|
||||
return;
|
||||
}
|
||||
tocContainer = document.createElement('nav');
|
||||
tocContainer.className = 'aksrt-section-nav';
|
||||
tocContainer.setAttribute('aria-label', '文章目录');
|
||||
var sidebar = document.querySelector('.content-layout__aside, .sidebar, .widget-area');
|
||||
if (sidebar) {
|
||||
sidebar.insertBefore(tocContainer, sidebar.firstChild);
|
||||
} else if (navContainer.parentNode) {
|
||||
navContainer.parentNode.insertBefore(tocContainer, navContainer);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
var root = document.querySelector('[data-nav], .article-content, .entry-content, main.article');
|
||||
if (!root) return;
|
||||
var listsHtml = buildLists(root);
|
||||
if (!listsHtml) return;
|
||||
if (!document.querySelector(NAVBOX) && !document.querySelector('.' + NAV_CLASS)) {
|
||||
return;
|
||||
}
|
||||
fillBoxes(listsHtml);
|
||||
bindClicks();
|
||||
scrollspy();
|
||||
autoHash();
|
||||
}
|
||||
|
||||
var list = document.createElement('ul');
|
||||
list.className = 'aksrt-section-nav__list';
|
||||
|
||||
var items = [];
|
||||
headings.forEach(function (heading, i) {
|
||||
if (!heading.id) {
|
||||
heading.id = 'section-nav-' + i;
|
||||
}
|
||||
|
||||
var level = parseInt(heading.tagName.charAt(1), 10);
|
||||
var li = document.createElement('li');
|
||||
li.className = 'aksrt-section-nav__item aksrt-section-nav__item--h' + level;
|
||||
|
||||
var link = document.createElement('a');
|
||||
link.href = '#' + heading.id;
|
||||
link.textContent = heading.textContent.trim();
|
||||
link.className = 'aksrt-section-nav__link';
|
||||
|
||||
link.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
smoothScrollTo(heading);
|
||||
|
||||
// Expand collapsed panels containing the target
|
||||
var panel = heading.closest('[data-collapse], .collapse');
|
||||
if (panel) {
|
||||
panel.classList.add('show', 'is-open');
|
||||
var readMore = panel.previousElementSibling;
|
||||
if (readMore && readMore.classList.contains('read-more-open')) readMore.click();
|
||||
}
|
||||
});
|
||||
|
||||
li.appendChild(link);
|
||||
list.appendChild(li);
|
||||
items.push({ el: heading, link: link, li: li, level: level });
|
||||
if (window.AksrtFrontend && typeof window.AksrtFrontend.register === 'function') {
|
||||
window.AksrtFrontend.register('aksrt-section-navs', function () {
|
||||
init();
|
||||
});
|
||||
|
||||
tocContainer.innerHTML = '';
|
||||
tocContainer.appendChild(list);
|
||||
|
||||
// Collapse sub-items if TOC is tall
|
||||
if (tocContainer.scrollHeight > MAX_HEIGHT_COLLAPSE) {
|
||||
collapseSubItems(list, items);
|
||||
}
|
||||
|
||||
// Scrollspy
|
||||
var ticking = false;
|
||||
function onScroll() {
|
||||
if (ticking) return;
|
||||
ticking = true;
|
||||
requestAnimationFrame(function () {
|
||||
ticking = false;
|
||||
var scrollTop = window.pageYOffset + SCROLL_OFFSET;
|
||||
var activeIdx = 0;
|
||||
for (var i = items.length - 1; i >= 0; i--) {
|
||||
if (items[i].el.offsetTop <= scrollTop) {
|
||||
activeIdx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
items.forEach(function (item, idx) {
|
||||
item.link.classList.toggle('is-active', idx === activeIdx);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', onScroll, { passive: true });
|
||||
onScroll();
|
||||
|
||||
// URL hash auto-scroll
|
||||
if (window.location.hash) {
|
||||
var target = document.querySelector(window.location.hash);
|
||||
if (target) setTimeout(function () { smoothScrollTo(target); }, 100);
|
||||
}
|
||||
}
|
||||
|
||||
function smoothScrollTo(el) {
|
||||
if (window.aksrt && aksrt.scrollTopTo) {
|
||||
aksrt.scrollTopTo(el);
|
||||
} else {
|
||||
var top = el.getBoundingClientRect().top + window.pageYOffset - SCROLL_OFFSET;
|
||||
window.scrollTo({ top: Math.max(0, top), behavior: 'smooth' });
|
||||
}
|
||||
}
|
||||
|
||||
function collapseSubItems(list, items) {
|
||||
var parentStack = [];
|
||||
items.forEach(function (item) {
|
||||
while (parentStack.length && parentStack[parentStack.length - 1].level >= item.level) {
|
||||
parentStack.pop();
|
||||
}
|
||||
|
||||
if (item.level >= 3 && parentStack.length) {
|
||||
item.li.classList.add('yc');
|
||||
// Add collapse toggle to parent if not already there
|
||||
var parentLi = parentStack[parentStack.length - 1].li;
|
||||
if (!parentLi.querySelector('.nav-toggle-collapse')) {
|
||||
var toggle = document.createElement('span');
|
||||
toggle.className = 'nav-toggle-collapse';
|
||||
toggle.innerHTML = '<i class="fas fa-chevron-right"></i>';
|
||||
toggle.addEventListener('click', function (e) {
|
||||
e.stopPropagation();
|
||||
toggle.classList.toggle('fa-rotate-90');
|
||||
var next = parentLi.nextElementSibling;
|
||||
while (next && next.classList.contains('yc')) {
|
||||
next.classList.toggle('yc-open');
|
||||
next = next.nextElementSibling;
|
||||
}
|
||||
});
|
||||
parentLi.appendChild(toggle);
|
||||
}
|
||||
}
|
||||
|
||||
parentStack.push(item);
|
||||
});
|
||||
}
|
||||
|
||||
if (window.AksrtFrontend) {
|
||||
AksrtFrontend.register('aksrt-section-navs', function () { initSectionNavs(); });
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initSectionNavs);
|
||||
} else if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
initSectionNavs();
|
||||
init();
|
||||
}
|
||||
})();
|
||||
|
||||
@@ -147,3 +147,56 @@ function aksrt_render_language_switcher(string $style = 'dropdown'): string {
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Header language dropdown (zibll zib_get_translate_language_btn).
|
||||
* Uses SPA i18n_available_langs when i18n enabled and position includes header.
|
||||
*
|
||||
* @param string $class Extra classes.
|
||||
*/
|
||||
function aksrt_get_translate_language_btn(string $class = ''): string {
|
||||
if (!class_exists('\AKSRT\Settings\Settings')) {
|
||||
return '';
|
||||
}
|
||||
$cfg = \AKSRT\Settings\Settings::get_i18n_config();
|
||||
if (empty($cfg['enabled'])) {
|
||||
return '';
|
||||
}
|
||||
$pos = (string) ($cfg['switcherPosition'] ?? 'footer');
|
||||
if (!in_array($pos, ['header', 'both'], true)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$raw = (string) ($cfg['availableLangs'] ?? '');
|
||||
$buttons = [];
|
||||
foreach (preg_split('/
|
||||
|␍|
|
||||
/', $raw) as $line) {
|
||||
$line = trim($line);
|
||||
if ($line === '' || strpos($line, '|') === false) {
|
||||
continue;
|
||||
}
|
||||
[$code, $label] = array_map('trim', explode('|', $line, 2));
|
||||
if ($code === '' || $label === '') {
|
||||
continue;
|
||||
}
|
||||
$buttons[] = ['language' => $code, 'text' => $label];
|
||||
}
|
||||
if (!$buttons) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$buttons_html = '';
|
||||
foreach ($buttons as $button) {
|
||||
$buttons_html .= '<li><a href="javascript:;" class="translate-button translate-ignore flex ac" data-language="'
|
||||
. esc_attr($button['language']) . '">' . esc_html($button['text']) . '</a></li>';
|
||||
}
|
||||
$is_mobile = wp_is_mobile();
|
||||
$dropdown = '<ul class="dropdown-menu hover-show-con">' . $buttons_html . '</ul>';
|
||||
$hover = !$is_mobile ? ' hover-show' : '';
|
||||
$toggle = !$is_mobile ? '' : ' data-toggle="dropdown"';
|
||||
return '<div class="dropdown language-dropdown ' . esc_attr($class) . $hover . '">'
|
||||
. '<a href="javascript:;" class="toggle-radius"' . $toggle . ' title="' . esc_attr__('切换语言', 'aksrt') . '">'
|
||||
. '<i class="fas fa-language" aria-hidden="true"></i></a>' . $dropdown . '</div>';
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,9 @@ if (!function_exists('aksrt_nav_mobile_content')) :
|
||||
$top_btns .= '<a href="javascript:;" class="toggle-radius main-search-btn" data-toggle-class 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')) {
|
||||
$top_btns .= aksrt_get_translate_language_btn('pull-right');
|
||||
}
|
||||
if ($top_btns !== '') {
|
||||
echo '<div class="flex ac pull-right" style="margin-right: -3px;">' . $top_btns . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
@@ -116,6 +119,10 @@ if (!function_exists('aksrt_nav_mobile_content')) :
|
||||
}
|
||||
echo $menu; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
|
||||
if (is_singular('post')) {
|
||||
echo '<div class="posts-nav-box" data-title="' . esc_attr__('文章目录', 'aksrt') . '"></div>';
|
||||
}
|
||||
|
||||
// User box at bottom of drawer.
|
||||
if (!empty($ctx['user_menu'])) {
|
||||
echo aksrt_header_user_box_html($ctx); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
|
||||
@@ -104,6 +104,7 @@ 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'] : [];
|
||||
|
||||
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">';
|
||||
@@ -112,9 +113,22 @@ if (!function_exists('aksrt_get_menu_search')) :
|
||||
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) . '">';
|
||||
. 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>';
|
||||
if ($hots) {
|
||||
echo '<div class="dropdown-menu hover-show-con navbar-inline-search-panel">';
|
||||
echo '<div class="muted-2-color em09 mb6">' . esc_html__('热门搜索', 'aksrt') . '</div>';
|
||||
echo '<div class="navbar-inline-search-hots">';
|
||||
foreach ($hots as $kw) {
|
||||
$kw = trim((string) $kw);
|
||||
if ($kw === '') {
|
||||
continue;
|
||||
}
|
||||
echo '<a class="but jb-sm" href="' . esc_url(home_url('/?s=' . rawurlencode($kw))) . '">' . esc_html($kw) . '</a> ';
|
||||
}
|
||||
echo '</div></div>';
|
||||
}
|
||||
echo '</div></form>';
|
||||
}
|
||||
endif;
|
||||
@@ -179,13 +193,25 @@ if (!function_exists('aksrt_header_user_box_html')) :
|
||||
}
|
||||
|
||||
if (!empty($ctx['can_publish'])) {
|
||||
$pub_text = class_exists('\AKSRT\Settings\Settings')
|
||||
? (string) (\AKSRT\Settings\Settings::get_all()['header_user_newposts_text'] ?? '')
|
||||
: '';
|
||||
$all = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_all() : [];
|
||||
$pub_text = (string) ($all['header_user_newposts_text'] ?? '');
|
||||
if ($pub_text === '') {
|
||||
$pub_text = __('发布内容', 'aksrt');
|
||||
}
|
||||
$href .= '<a rel="nofollow" href="' . esc_url((string) $ctx['publish_url']) . '">';
|
||||
$pub_type = sanitize_key((string) ($all['header_user_newposts_btn'] ?? 'post'));
|
||||
$pub_url = (string) $ctx['publish_url'];
|
||||
if ($pub_type === 'topic' && function_exists('aksrt_get_forum_compose_url')) {
|
||||
$u = aksrt_get_forum_compose_url();
|
||||
if ($u) { $pub_url = $u; }
|
||||
} elseif ($pub_type === 'product') {
|
||||
if (function_exists('aksrt_get_product_edit_url')) {
|
||||
$u = (string) aksrt_get_product_edit_url();
|
||||
if ($u !== '') { $pub_url = $u; }
|
||||
} else {
|
||||
$pub_url = admin_url('post-new.php?post_type=aksrt_product');
|
||||
}
|
||||
}
|
||||
$href .= '<a rel="nofollow" href="' . esc_url($pub_url) . '">';
|
||||
$href .= '<div class="badg mb6 toggle-radius c-green"><i class="fas fa-pen" aria-hidden="true"></i></div>';
|
||||
$href .= '<div class="c-green">' . esc_html($pub_text) . '</div></a>';
|
||||
}
|
||||
@@ -284,6 +310,9 @@ if (!function_exists('aksrt_menu_button')) :
|
||||
$radius_but .= '<i class="fas fa-sun theme-icon-sun" aria-hidden="true" style="display:none"></i>';
|
||||
$radius_but .= '</a>';
|
||||
}
|
||||
if (function_exists('aksrt_get_translate_language_btn')) {
|
||||
$radius_but .= aksrt_get_translate_language_btn('ml10 pull-right');
|
||||
}
|
||||
if ($radius_but !== '') {
|
||||
$button .= '<div class="navbar-form navbar-right flex ac">' . $radius_but . '</div>';
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* Native WP nav-menu item options (aksrt_menu_options).
|
||||
* Native WP nav-menu item options (aksrt_menu_options) with senior submenu JSON.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
@@ -29,6 +29,12 @@ class NavMenuOptions {
|
||||
$badge_class = (string) ($opts['badge_class'] ?? '');
|
||||
$submenu_s = !empty($opts['submenu_s']);
|
||||
$submenu_type = (string) ($opts['submenu_type'] ?? '');
|
||||
$graphic_json = !empty($opts['graphic_card_opts'])
|
||||
? wp_json_encode($opts['graphic_card_opts'], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)
|
||||
: self::sample_graphic_json();
|
||||
$multi_json = !empty($opts['multi_column_links_opts'])
|
||||
? wp_json_encode($opts['multi_column_links_opts'], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)
|
||||
: self::sample_multi_json();
|
||||
?>
|
||||
<p class="field-aksrt-icon description description-wide">
|
||||
<label for="edit-menu-item-aksrt-icon-<?php echo esc_attr((string) $item_id); ?>">
|
||||
@@ -57,7 +63,7 @@ class NavMenuOptions {
|
||||
<p class="field-aksrt-submenu description description-wide">
|
||||
<label>
|
||||
<input type="checkbox" name="aksrt_menu_options[<?php echo esc_attr((string) $item_id); ?>][submenu_s]" value="1" <?php checked($submenu_s); ?>>
|
||||
<?php esc_html_e('启用高级子菜单(一级菜单)', 'aksrt'); ?>
|
||||
<?php esc_html_e('启用高级子菜单(仅一级菜单)', 'aksrt'); ?>
|
||||
</label>
|
||||
</p>
|
||||
<p class="field-aksrt-submenu-type description description-wide">
|
||||
@@ -71,8 +77,19 @@ class NavMenuOptions {
|
||||
</select>
|
||||
</label>
|
||||
</p>
|
||||
<p class="description description-wide">
|
||||
<?php esc_html_e('高级子菜单内容(graphic_card_opts / multi_column_links_opts)可在后续可视化编辑;也可通过 meta 写入 JSON。', 'aksrt'); ?>
|
||||
<p class="field-aksrt-graphic description description-wide">
|
||||
<label for="edit-menu-item-aksrt-graphic-<?php echo esc_attr((string) $item_id); ?>">
|
||||
<?php esc_html_e('图文卡片 JSON(type=graphic_card)', 'aksrt'); ?><br>
|
||||
<textarea rows="8" class="widefat code" id="edit-menu-item-aksrt-graphic-<?php echo esc_attr((string) $item_id); ?>"
|
||||
name="aksrt_menu_options[<?php echo esc_attr((string) $item_id); ?>][graphic_card_opts_json]"><?php echo esc_textarea((string) $graphic_json); ?></textarea>
|
||||
</label>
|
||||
</p>
|
||||
<p class="field-aksrt-multi description description-wide">
|
||||
<label for="edit-menu-item-aksrt-multi-<?php echo esc_attr((string) $item_id); ?>">
|
||||
<?php esc_html_e('多列链接 JSON(type=multi_column_links)', 'aksrt'); ?><br>
|
||||
<textarea rows="8" class="widefat code" id="edit-menu-item-aksrt-multi-<?php echo esc_attr((string) $item_id); ?>"
|
||||
name="aksrt_menu_options[<?php echo esc_attr((string) $item_id); ?>][multi_column_links_opts_json]"><?php echo esc_textarea((string) $multi_json); ?></textarea>
|
||||
</label>
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
@@ -83,15 +100,12 @@ class NavMenuOptions {
|
||||
*/
|
||||
public static function save($menu_id, $menu_item_db_id): void {
|
||||
$menu_item_db_id = (int) $menu_item_db_id;
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- WP core nav-menu form nonce.
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
if (empty($_POST['aksrt_menu_options'][ $menu_item_db_id ]) || !is_array($_POST['aksrt_menu_options'][ $menu_item_db_id ])) {
|
||||
// If fields absent, leave existing meta (WP may not resubmit all fields in bulk edits).
|
||||
return;
|
||||
}
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
$raw = wp_unslash($_POST['aksrt_menu_options'][ $menu_item_db_id ]);
|
||||
$existing = get_post_meta($menu_item_db_id, 'aksrt_menu_options', true);
|
||||
$existing = is_array($existing) ? $existing : [];
|
||||
|
||||
$clean = [
|
||||
'icon' => sanitize_text_field((string) ($raw['icon'] ?? '')),
|
||||
@@ -100,13 +114,138 @@ class NavMenuOptions {
|
||||
'submenu_s' => !empty($raw['submenu_s']),
|
||||
'submenu_type' => sanitize_key((string) ($raw['submenu_type'] ?? '')),
|
||||
];
|
||||
// Preserve complex opts not edited by this form.
|
||||
if (!empty($existing['graphic_card_opts'])) {
|
||||
$clean['graphic_card_opts'] = $existing['graphic_card_opts'];
|
||||
|
||||
$graphic = self::decode_json_field((string) ($raw['graphic_card_opts_json'] ?? ''));
|
||||
if (is_array($graphic)) {
|
||||
$clean['graphic_card_opts'] = self::sanitize_graphic_opts($graphic);
|
||||
}
|
||||
if (!empty($existing['multi_column_links_opts'])) {
|
||||
$clean['multi_column_links_opts'] = $existing['multi_column_links_opts'];
|
||||
$multi = self::decode_json_field((string) ($raw['multi_column_links_opts_json'] ?? ''));
|
||||
if (is_array($multi)) {
|
||||
$clean['multi_column_links_opts'] = self::sanitize_multi_opts($multi);
|
||||
}
|
||||
|
||||
update_post_meta($menu_item_db_id, 'aksrt_menu_options', $clean);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string,mixed>|null
|
||||
*/
|
||||
private static function decode_json_field(string $json): ?array {
|
||||
$json = trim($json);
|
||||
if ($json === '') {
|
||||
return null;
|
||||
}
|
||||
$data = json_decode($json, true);
|
||||
return is_array($data) ? $data : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string,mixed> $opts
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
private static function sanitize_graphic_opts(array $opts): array {
|
||||
$items_in = is_array($opts['items'] ?? null) ? $opts['items'] : [];
|
||||
$items = [];
|
||||
foreach ($items_in as $item) {
|
||||
if (!is_array($item)) {
|
||||
continue;
|
||||
}
|
||||
$items[] = [
|
||||
'img' => esc_url_raw((string) ($item['img'] ?? '')),
|
||||
'title' => sanitize_text_field((string) ($item['title'] ?? '')),
|
||||
'badge' => sanitize_text_field((string) ($item['badge'] ?? '')),
|
||||
'badge_class' => sanitize_html_class((string) ($item['badge_class'] ?? '')),
|
||||
'link' => [
|
||||
'url' => esc_url_raw((string) ($item['link']['url'] ?? '')),
|
||||
'text' => sanitize_text_field((string) ($item['link']['text'] ?? '')),
|
||||
'target' => sanitize_text_field((string) ($item['link']['target'] ?? '')),
|
||||
],
|
||||
];
|
||||
}
|
||||
return [
|
||||
'arrangement' => sanitize_key((string) ($opts['arrangement'] ?? '')),
|
||||
'align' => sanitize_key((string) ($opts['align'] ?? '')),
|
||||
'size' => sanitize_key((string) ($opts['size'] ?? '')),
|
||||
'img_scale' => max(0, min(200, (int) ($opts['img_scale'] ?? 100))),
|
||||
'items' => $items,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string,mixed> $opts
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
private static function sanitize_multi_opts(array $opts): array {
|
||||
$columns_in = is_array($opts['columns'] ?? null) ? $opts['columns'] : [];
|
||||
$columns = [];
|
||||
foreach ($columns_in as $col) {
|
||||
if (!is_array($col)) {
|
||||
continue;
|
||||
}
|
||||
$items = [];
|
||||
if (!empty($col['items']) && is_array($col['items'])) {
|
||||
foreach ($col['items'] as $item) {
|
||||
if (!is_array($item)) {
|
||||
continue;
|
||||
}
|
||||
$items[] = [
|
||||
'title' => sanitize_text_field((string) ($item['title'] ?? '')),
|
||||
'icon' => sanitize_text_field((string) ($item['icon'] ?? '')),
|
||||
'img_icon' => esc_url_raw((string) ($item['img_icon'] ?? '')),
|
||||
'link' => [
|
||||
'url' => esc_url_raw((string) ($item['link']['url'] ?? '')),
|
||||
'text' => sanitize_text_field((string) ($item['link']['text'] ?? '')),
|
||||
'target' => sanitize_text_field((string) ($item['link']['target'] ?? '')),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
$columns[] = [
|
||||
'title' => sanitize_text_field((string) ($col['title'] ?? '')),
|
||||
'icon' => sanitize_text_field((string) ($col['icon'] ?? '')),
|
||||
'img_icon' => esc_url_raw((string) ($col['img_icon'] ?? '')),
|
||||
'link' => [
|
||||
'url' => esc_url_raw((string) ($col['link']['url'] ?? '')),
|
||||
'text' => sanitize_text_field((string) ($col['link']['text'] ?? '')),
|
||||
'target' => sanitize_text_field((string) ($col['link']['target'] ?? '')),
|
||||
],
|
||||
'items' => $items,
|
||||
];
|
||||
}
|
||||
return ['columns' => $columns];
|
||||
}
|
||||
|
||||
private static function sample_graphic_json(): string {
|
||||
$sample = [
|
||||
'arrangement' => '',
|
||||
'size' => 'md',
|
||||
'img_scale' => 100,
|
||||
'items' => [
|
||||
[
|
||||
'img' => '',
|
||||
'title' => '卡片标题',
|
||||
'badge' => '',
|
||||
'badge_class' => 'jb-red',
|
||||
'link' => ['url' => home_url('/'), 'text' => '', 'target' => ''],
|
||||
],
|
||||
],
|
||||
];
|
||||
return (string) wp_json_encode($sample, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
||||
}
|
||||
|
||||
private static function sample_multi_json(): string {
|
||||
$sample = [
|
||||
'columns' => [
|
||||
[
|
||||
'title' => '栏目一',
|
||||
'icon' => 'fas fa-folder',
|
||||
'link' => ['url' => '', 'text' => '', 'target' => ''],
|
||||
'items' => [
|
||||
['title' => '链接 A', 'icon' => '', 'link' => ['url' => home_url('/'), 'text' => '', 'target' => '']],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
return (string) wp_json_encode($sample, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,11 @@ class SchemaPageDisplay {
|
||||
['label' => '帖子', 'value' => 'topic'],
|
||||
['label' => '商品', 'value' => 'product'],
|
||||
]],
|
||||
['key' => 'header_user_newposts_btn', 'label' => '用户卡发布类型', 'type' => 'select', 'default' => 'post', 'options' => [
|
||||
['label' => '文章', 'value' => 'post'],
|
||||
['label' => '帖子', 'value' => 'topic'],
|
||||
['label' => '商品', 'value' => 'product'],
|
||||
]],
|
||||
['key' => 'header_user_newposts_text', 'label' => '用户卡发布文案', 'type' => 'input', 'default' => '发布内容'],
|
||||
]],
|
||||
['key' => 'color', 'title' => '颜色设置', 'fields' => [
|
||||
|
||||
@@ -475,6 +475,17 @@ trait ScriptsPart1b {
|
||||
|
||||
// 文章导航页(zibll postsnavs.php)
|
||||
if (is_page_template('templates/pages/page-posts-navs.php')) {
|
||||
$page_navs_js = get_template_directory() . '/assets/js/page-navs.js';
|
||||
if (file_exists($page_navs_js)) {
|
||||
wp_enqueue_script(
|
||||
'aksrt-page-navs',
|
||||
$base_uri . '/assets/js/page-navs.js',
|
||||
[],
|
||||
(string) filemtime($page_navs_js),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
$pn_css = get_template_directory() . '/assets/css/routes/posts-navs.css';
|
||||
if (file_exists($pn_css)) {
|
||||
wp_enqueue_style(
|
||||
|
||||
Reference in New Issue
Block a user