fix(frontend): align search and header components with reference

This commit is contained in:
kate522 committed 2026-10-29 22:21:01 +08:00
1 parent 4c13ef478c
commit 542daca457
34 files changed
+803 -705

No files matched your search

+1 -7
View File
@@ -2522,13 +2522,7 @@ main.container,
* math), so the card container gets no extra gutter either. The
* <=991.98px media rule below restores 15px for every .container. */
/* Header multifunc icon cards: pin typography baseline so cards render
* identically on all pages. .px12-sm is only defined globally in
* legacy-utilities.css, which is @import'd by the single-post aggregator;
* vendor CSS pins it at <=640px / .sidebar / .mobile-nav-widget only. */
.header-slider-card .icon-cover-card {
font-size: 12px;
}
/* Let the reference .px12-sm utility apply at its mobile breakpoint only. */
/* Keep the header multifunction search stable across route-specific CSS.
* Some routes load a later .abs-right utility, while the global input focus
+1 -1
View File
@@ -1 +1 @@
:root{--color-primary: #f04494;--color-primary-hover: #e0307e;--color-primary-active: #c9206d;--color-primary-soft: rgba(240, 68, 148, .1);--color-primary-softer: rgba(240, 68, 148, .05);--color-on-primary: #FFFFFF;--color-ink: #333333;--color-ink-2: #4e5358;--color-ink-3: #777777;--color-ink-4: #999999;--surface-page: #f5f6f7;--surface-1: #FFFFFF;--surface-2: #eeeeee;--surface-3: #e9ecef;--surface-4: #f8f8f8;--color-line: rgba(50, 50, 50, .06);--color-line-soft: rgba(0, 0, 0, .03);--color-line-stronger: rgba(50, 50, 50, .12);--color-success: #10B981;--color-warning: #F59E0B;--color-error: #EF4444;--color-info: #3B82F6;--color-accent: #18a058;--color-accent-soft: rgba(24, 160, 88, .12);--color-accent-shadow: rgba(24, 160, 88, .28);--font-display: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;--font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;--font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;--font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;--text-xs: .75rem;--text-sm: .875rem;--text-base: .875rem;--text-md: 1.125rem;--text-lg: 1.25rem;--text-xl: 1.5rem;--text-2xl: 1.875rem;--text-3xl: 2.25rem;--text-4xl: 3rem;--text-5xl: 3.75rem;--leading-tight: 1.2;--leading-snug: 1.4;--leading-normal: 1.6;--leading-relaxed: 1.6;--space-1: 4px;--space-2: 8px;--space-3: 12px;--space-4: 16px;--space-5: 20px;--space-6: 24px;--space-7: 32px;--space-8: 40px;--space-9: 48px;--space-10: 64px;--space-11: 80px;--space-12: 96px;--radius-xs: 3px;--radius-sm: 4px;--radius: 8px;--radius-lg: 8px;--radius-xl: 12px;--radius-2xl: 16px;--radius-pill: 100px;--radius-avatar: 50%;--shadow-xs: 0 1px 2px rgba(0, 0, 0, .03);--shadow-sm: 0 0 10px rgba(116, 116, 116, .08);--shadow: 0 0 10px rgba(116, 116, 116, .12);--shadow-lg: 0 12px 32px rgba(18, 18, 18, .1);--shadow-drawer: 0 18px 60px rgba(0, 0, 0, .2);--nav-height: 60px;--container: 1200px;--container-wide: 1440px;--container-read: 760px;--container-page: 880px;--sidebar-width: 311px;--content-gap: 24px;--section-gap: 24px;--sidebar-bp: 992px;--ease: cubic-bezier(.4, 0, .2, 1);--ease-out: cubic-bezier(.16, 1, .3, 1);--ease-spring: cubic-bezier(.34, 1.56, .64, 1);--dur-fast: .15s;--dur: .25s;--dur-slow: .4s;--focus-ring: 0 0 2px 3px rgba(253, 83, 161, .4);--z-dropdown: 100;--z-sticky: 200;--z-fixed: 300;--z-overlay: 400;--z-modal: 500;--z-popover: 600;--z-toast: 700;--z-tooltip: 800;--radius-btn: 4px;--btn-sm-h: 28px;--btn-md-h: 34px;--btn-lg-h: 44px;--card-padding: 15px;--card-padding-sm: 10px;--card-gap: 16px;--card-gap-lg: 20px;--color-primary-light: var(--color-primary-soft);--color-surface: var(--surface-1);--color-line-strong: var(--color-line);--color-bg-hover: var(--surface-2);--color-border-light: var(--color-line-soft);--color-fill: var(--surface-2);--color-warning-bg: #fffbe6;--color-warning-text: #ad6800;--text-secondary: var(--color-ink-3);--text-tertiary: var(--color-ink-4);--surface-active: var(--surface-2);--surface-card: var(--surface-1);--surface-hover: var(--surface-2);--surface-secondary: var(--surface-2);--radius-code: var(--radius);--radius-full: 100px;--shadow-xl: 0 0 10px rgba(116, 116, 116, .12);--space-16: 64px;--z-floating: 900;--transition-fast: .15s ease;--transition-base: .25s ease;--header-bg: var(--blur-bg);--header-color: var(--color-ink-2);--footer-bg: var(--surface-1);--footer-color: var(--color-ink-4);--blur-bg: rgba(255, 255, 255, .8);--float-btn-bg: rgba(200, 200, 200, .4);--font-heading: var(--font-ui);--radius-card: var(--radius);--radius-md: var(--radius);--color-primary-50: var(--color-primary-soft);--color-primary-dark: var(--color-primary-active);--shadow-md: var(--shadow);--mini-radius: calc(var(--radius) / 1.4);--aksrt-avatar-size-xs: 24px;--aksrt-avatar-size-sm: 32px;--aksrt-avatar-size: 40px;--aksrt-avatar-size-lg: 56px;--aksrt-avatar-size-xl: 80px;--aksrt-card-thumb-scale: 56.25%;--aksrt-rose: #f43f5e;--aksrt-rose-soft: rgba(244, 63, 94, .12);--aksrt-blue: #3b82f6;--aksrt-blue-soft: rgba(59, 130, 246, .12);--aksrt-green: #10b981;--aksrt-green-soft: rgba(16, 185, 129, .12);--aksrt-orange: #f97316;--aksrt-orange-soft:rgba(249, 115, 22, .12);--aksrt-purple: #8b5cf6;--aksrt-purple-soft:rgba(139, 92, 246, .12);--aksrt-cyan: #06b6d4;--aksrt-cyan-soft: rgba(6, 182, 212, .12);--aksrt-yellow: #eab308;--aksrt-yellow-soft:rgba(234, 179, 8, .12);--aksrt-red: #ef4444;--aksrt-red-soft: rgba(239, 68, 68, .12);--aksrt-teal: #14b8a6;--aksrt-teal-soft: rgba(20, 184, 166, .12);--aksrt-indigo: #6366f1;--aksrt-indigo-soft:rgba(99, 102, 241, .12);--aksrt-pink: #ec4899;--aksrt-pink-soft: rgba(236, 72, 153, .12);--aksrt-vip-gold-1: #f6d365;--aksrt-vip-gold-2: #fda085;--aksrt-grad-sunset-1: #f093fb;--aksrt-grad-sunset-2: #f5576c;--aksrt-graLine truncated
:root{--color-primary: #f04494;--color-primary-hover: #e0307e;--color-primary-active: #c9206d;--color-primary-soft: rgba(240, 68, 148, .1);--color-primary-softer: rgba(240, 68, 148, .05);--color-on-primary: #FFFFFF;--color-ink: #333333;--color-ink-2: #4e5358;--color-ink-3: #777777;--color-ink-4: #999999;--surface-page: #f5f6f7;--surface-1: #FFFFFF;--surface-2: #eeeeee;--surface-3: #e9ecef;--surface-4: #f8f8f8;--color-line: rgba(50, 50, 50, .06);--color-line-soft: rgba(0, 0, 0, .03);--color-line-stronger: rgba(50, 50, 50, .12);--color-success: #10B981;--color-warning: #F59E0B;--color-error: #EF4444;--color-info: #3B82F6;--color-accent: #18a058;--color-accent-soft: rgba(24, 160, 88, .12);--color-accent-shadow: rgba(24, 160, 88, .28);--font-display: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;--font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;--font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;--font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;--text-xs: .75rem;--text-sm: .875rem;--text-base: .875rem;--text-md: 1.125rem;--text-lg: 1.25rem;--text-xl: 1.5rem;--text-2xl: 1.875rem;--text-3xl: 2.25rem;--text-4xl: 3rem;--text-5xl: 3.75rem;--leading-tight: 1.2;--leading-snug: 1.4;--leading-normal: 1.6;--leading-relaxed: 1.6;--space-1: 4px;--space-2: 8px;--space-3: 12px;--space-4: 16px;--space-5: 20px;--space-6: 24px;--space-7: 32px;--space-8: 40px;--space-9: 48px;--space-10: 64px;--space-11: 80px;--space-12: 96px;--radius-xs: 3px;--radius-sm: 4px;--radius: 8px;--radius-lg: 8px;--radius-xl: 12px;--radius-2xl: 16px;--radius-pill: 100px;--radius-avatar: 50%;--shadow-xs: 0 1px 2px rgba(0, 0, 0, .03);--shadow-sm: 0 0 10px rgba(116, 116, 116, .08);--shadow: 0 0 10px rgba(116, 116, 116, .12);--shadow-lg: 0 12px 32px rgba(18, 18, 18, .1);--shadow-drawer: 0 18px 60px rgba(0, 0, 0, .2);--nav-height: 60px;--container: 1200px;--container-wide: 1440px;--container-read: 760px;--container-page: 880px;--sidebar-width: 311px;--content-gap: 24px;--section-gap: 24px;--sidebar-bp: 992px;--ease: cubic-bezier(.4, 0, .2, 1);--ease-out: cubic-bezier(.16, 1, .3, 1);--ease-spring: cubic-bezier(.34, 1.56, .64, 1);--dur-fast: .15s;--dur: .25s;--dur-slow: .4s;--focus-ring: 0 0 2px 3px rgba(253, 83, 161, .4);--z-dropdown: 100;--z-sticky: 200;--z-fixed: 300;--z-overlay: 400;--z-modal: 500;--z-popover: 600;--z-toast: 700;--z-tooltip: 800;--radius-btn: 4px;--btn-sm-h: 28px;--btn-md-h: 34px;--btn-lg-h: 44px;--card-padding: 15px;--card-padding-sm: 10px;--card-gap: 16px;--card-gap-lg: 20px;--color-primary-light: var(--color-primary-soft);--color-surface: var(--surface-1);--color-line-strong: var(--color-line);--color-bg-hover: var(--surface-2);--color-border-light: var(--color-line-soft);--color-fill: var(--surface-2);--color-warning-bg: #fffbe6;--color-warning-text: #ad6800;--text-secondary: var(--color-ink-3);--text-tertiary: var(--color-ink-4);--surface-active: var(--surface-2);--surface-card: var(--surface-1);--surface-hover: var(--surface-2);--surface-secondary: var(--surface-2);--radius-code: var(--radius);--radius-full: 100px;--shadow-xl: 0 0 10px rgba(116, 116, 116, .12);--space-16: 64px;--z-floating: 900;--transition-fast: .15s ease;--transition-base: .25s ease;--header-bg: var(--blur-bg);--header-color: var(--color-ink-2);--footer-bg: var(--surface-1);--footer-color: var(--color-ink-4);--blur-bg: rgba(255, 255, 255, .8);--float-btn-bg: rgba(200, 200, 200, .4);--font-heading: var(--font-ui);--radius-card: var(--radius);--radius-md: var(--radius);--color-primary-50: var(--color-primary-soft);--color-primary-dark: var(--color-primary-active);--shadow-md: var(--shadow);--mini-radius: calc(var(--radius) / 1.4);--aksrt-avatar-size-xs: 24px;--aksrt-avatar-size-sm: 32px;--aksrt-avatar-size: 40px;--aksrt-avatar-size-lg: 56px;--aksrt-avatar-size-xl: 80px;--aksrt-card-thumb-scale: 56.25%;--aksrt-rose: #f43f5e;--aksrt-rose-soft: rgba(244, 63, 94, .12);--aksrt-blue: #3b82f6;--aksrt-blue-soft: rgba(59, 130, 246, .12);--aksrt-green: #10b981;--aksrt-green-soft: rgba(16, 185, 129, .12);--aksrt-orange: #f97316;--aksrt-orange-soft:rgba(249, 115, 22, .12);--aksrt-purple: #8b5cf6;--aksrt-purple-soft:rgba(139, 92, 246, .12);--aksrt-cyan: #06b6d4;--aksrt-cyan-soft: rgba(6, 182, 212, .12);--aksrt-yellow: #eab308;--aksrt-yellow-soft:rgba(234, 179, 8, .12);--aksrt-red: #ef4444;--aksrt-red-soft: rgba(239, 68, 68, .12);--aksrt-teal: #14b8a6;--aksrt-teal-soft: rgba(20, 184, 166, .12);--aksrt-indigo: #6366f1;--aksrt-indigo-soft:rgba(99, 102, 241, .12);--aksrt-pink: #ec4899;--aksrt-pink-soft: rgba(236, 72, 153, .12);--aksrt-vip-gold-1: #f6d365;--aksrt-vip-gold-2: #fda085;--aksrt-grad-sunset-1: #f093fb;--aksrt-grad-sunset-2: #f5576c;--aksrt-graLine truncated
-1
View File
@@ -240,7 +240,6 @@
.text-center { text-align: center; }
.em09 { font-size: 0.9em; }
.em12 { font-size: 1.2em; }
.px12-sm { font-size: 12px; }
.ml3 { margin-left: 3px; }
.ml6 { margin-left: 6px; }
.ml10 { margin-left: 10px; }
+1 -1
View File
@@ -1 +1 @@
.relative{position:relative}.flex{display:flex}.flex.ac,.ac{align-items:center}.flex.jc,.jc{justify-content:center}.flex.jsb,.jsb{justify-content:space-between}.flex.at,.at{align-items:flex-start}.flex.ae,.ae{align-items:flex-end}.flex0{flex:0 0 auto}.flex1{flex:1 1 auto;min-width:0}.flex.column{flex-direction:column}.flex.wrap{flex-wrap:wrap}.flex.flex-row,.flex-row{flex-direction:row}.flex.jse,.jse{justify-content:space-evenly}.flex.jsa,.jsa{justify-content:space-around}.flex>.flex1,.flex .flex1{flex:1;overflow:hidden;min-width:0}.relative-h{position:relative;height:100%}.padding-10{padding:10px}.font-bold{font-weight:700}.mt6{margin-top:6px}.gutters-5{margin:-5px}.gutters-5>*{padding:5px}@media(max-width:767px){.flex.flex-row.flex-col-sm-2{flex-wrap:wrap}.flex.flex-row.flex-col-sm-2>*{flex-basis:50%}}.clearfix:before,.clearfix:after{content:"";display:table}.clearfix:after{clear:both}.abs-right{position:absolute;right:0;top:0}.abs-center{position:absolute;left:0;width:100%;top:50%;right:.7em;transform:translateY(-50%);z-index:1}.abs-center.left-top,.abs-center.right-top{transform:unset;top:0}.abs-center.right-top{left:auto;width:auto;text-align:right}.abs-center.left-top{text-align:left}.abs-center.conter-bottom,.abs-center.conter-conter{text-align:center}.abs-center.right-top,.abs-center.right-bottom,.abs-center.right-conter{text-align:right}.abs-center.conter-bottom,.abs-center.right-bottom,.abs-center.left-bottom{top:auto;transform:unset;bottom:0}.abs-center.left-bottom{left:0;right:auto;text-align:left}.abs-center.right-bottom,.abs-center.right-conter{left:auto;right:0;text-align:right}.graphic,.page-cover{text-shadow:0 0 5px rgba(0,0,0,.2);--main-color: #fff;color:#fff;position:relative;overflow:hidden;box-shadow:0 0 10px var(--main-shadow, rgba(116, 116, 116, .08));padding:0 0 70%;border-radius:var(--main-radius, var(--radius, 8px))}.graphic>.fit-cover,.graphic>img.fit-cover{position:absolute;width:100%;height:100%;object-fit:cover;inset:0}.fit-cover{object-fit:cover;max-width:100%}.title-h-left{position:relative;padding-bottom:8px}.title-h-left:before{transition:.4s;transform-origin:left;position:absolute;content:"";width:40px;height:3px;background:var(--theme-color, var(--focus-color, #f04494));left:0;bottom:3px;border-radius:5px;box-shadow:1px 1px 3px -1px var(--theme-color, var(--focus-color, #f04494))}.line-form-line,.line-form-line:before{position:absolute;bottom:0;left:0;height:1px;width:100%;transition:.8s;background:var(--main-border-color, rgba(50, 50, 50, .06))}.line-form-line:before{content:"";width:0;background:var(--focus-color, #f04494)}.avatar-img{position:relative;display:inline-block;flex-shrink:0;--this-size: 38px;width:var(--this-size);height:var(--this-size)}.avatar-img .avatar,.avatar-img img{width:100%;height:100%;border-radius:50%;object-fit:cover}.avatar-lg{--this-size: 80px}.avatar-md{--this-size: 55px}.avatar-mini{--this-size: 20px}.shrink0{flex-shrink:0}.opacity8{opacity:.8}.muted-color{color:var(--muted-color, var(--color-ink-3))}.muted-2-color{color:var(--muted-2-color, var(--color-ink-4))}.muted-3-color{color:var(--muted-3-color, #b1b1b1)}.muted-4-color{color:var(--muted-4-color, #d2d2d2)}.text-center{text-align:center}.em09{font-size:.9em}.em12{font-size:1.2em}.px12-sm{font-size:12px}.ml3{margin-left:3px}.ml6{margin-left:6px}.ml10{margin-left:10px}.mr3{margin-right:3px}.mr6{margin-right:6px}.mt10{margin-top:10px}.mt20{margin-top:20px}.mb10{margin-bottom:10px}.mb20{margin-bottom:20px}.text-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%}.text-ellipsis-2{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;word-break:break-word}.main-bg{background-color:var(--main-bg-color, var(--surface-1))}.separator{position:relative;letter-spacing:.08em}.icon-circle+.icon-circle:before{content:"·";display:inline-block;margin:0 .45em;opacity:.55}.article-avatar name,.article-avatar .name,.user-name{display:inline-flex;align-items:center;gap:4px;min-width:0;max-width:100%}.pull-right{float:right}.pull-left{float:left}body.single main.container .content-layout{display:block;min-width:0}body.single main.container .content-layout>*{min-width:0;max-width:100%}body.single main.container .content-layout>.breadcrumb,body.single main.container .content-layout>ul.breadcrumb,body.single main.container .content-layout>.breadcrumb-nav,body.single main.container .content-layout>.breadcrumbs-wrap{position:relative;z-index:1;margin-top:0;margin-bottom:12px;padding-top:2px}body.single .sidebar .aksrt-panel,body.single .sidebar .widget{margin-bottom:15px}body.single main.container{box-sizing:border-box}.article,article.article.box-body,.article.main-bg.box-body{padding:0 30px;overflow:hidden}@media(max-width:767px){.article,article.article.box-body,.article.main-bg.box-body{padding:0 15px}.article-header .article-title{font-size:18px}}.entry-header,.article-header{margin-bottom:10px;padding-bottom:0;border-bottom:none;background:tranLine truncated
.relative{position:relative}.flex{display:flex}.flex.ac,.ac{align-items:center}.flex.jc,.jc{justify-content:center}.flex.jsb,.jsb{justify-content:space-between}.flex.at,.at{align-items:flex-start}.flex.ae,.ae{align-items:flex-end}.flex0{flex:0 0 auto}.flex1{flex:1 1 auto;min-width:0}.flex.column{flex-direction:column}.flex.wrap{flex-wrap:wrap}.flex.flex-row,.flex-row{flex-direction:row}.flex.jse,.jse{justify-content:space-evenly}.flex.jsa,.jsa{justify-content:space-around}.flex>.flex1,.flex .flex1{flex:1;overflow:hidden;min-width:0}.relative-h{position:relative;height:100%}.padding-10{padding:10px}.font-bold{font-weight:700}.mt6{margin-top:6px}.gutters-5{margin:-5px}.gutters-5>*{padding:5px}@media(max-width:767px){.flex.flex-row.flex-col-sm-2{flex-wrap:wrap}.flex.flex-row.flex-col-sm-2>*{flex-basis:50%}}.clearfix:before,.clearfix:after{content:"";display:table}.clearfix:after{clear:both}.abs-right{position:absolute;right:0;top:0}.abs-center{position:absolute;left:0;width:100%;top:50%;right:.7em;transform:translateY(-50%);z-index:1}.abs-center.left-top,.abs-center.right-top{transform:unset;top:0}.abs-center.right-top{left:auto;width:auto;text-align:right}.abs-center.left-top{text-align:left}.abs-center.conter-bottom,.abs-center.conter-conter{text-align:center}.abs-center.right-top,.abs-center.right-bottom,.abs-center.right-conter{text-align:right}.abs-center.conter-bottom,.abs-center.right-bottom,.abs-center.left-bottom{top:auto;transform:unset;bottom:0}.abs-center.left-bottom{left:0;right:auto;text-align:left}.abs-center.right-bottom,.abs-center.right-conter{left:auto;right:0;text-align:right}.graphic,.page-cover{text-shadow:0 0 5px rgba(0,0,0,.2);--main-color: #fff;color:#fff;position:relative;overflow:hidden;box-shadow:0 0 10px var(--main-shadow, rgba(116, 116, 116, .08));padding:0 0 70%;border-radius:var(--main-radius, var(--radius, 8px))}.graphic>.fit-cover,.graphic>img.fit-cover{position:absolute;width:100%;height:100%;object-fit:cover;inset:0}.fit-cover{object-fit:cover;max-width:100%}.title-h-left{position:relative;padding-bottom:8px}.title-h-left:before{transition:.4s;transform-origin:left;position:absolute;content:"";width:40px;height:3px;background:var(--theme-color, var(--focus-color, #f04494));left:0;bottom:3px;border-radius:5px;box-shadow:1px 1px 3px -1px var(--theme-color, var(--focus-color, #f04494))}.line-form-line,.line-form-line:before{position:absolute;bottom:0;left:0;height:1px;width:100%;transition:.8s;background:var(--main-border-color, rgba(50, 50, 50, .06))}.line-form-line:before{content:"";width:0;background:var(--focus-color, #f04494)}.avatar-img{position:relative;display:inline-block;flex-shrink:0;--this-size: 38px;width:var(--this-size);height:var(--this-size)}.avatar-img .avatar,.avatar-img img{width:100%;height:100%;border-radius:50%;object-fit:cover}.avatar-lg{--this-size: 80px}.avatar-md{--this-size: 55px}.avatar-mini{--this-size: 20px}.shrink0{flex-shrink:0}.opacity8{opacity:.8}.muted-color{color:var(--muted-color, var(--color-ink-3))}.muted-2-color{color:var(--muted-2-color, var(--color-ink-4))}.muted-3-color{color:var(--muted-3-color, #b1b1b1)}.muted-4-color{color:var(--muted-4-color, #d2d2d2)}.text-center{text-align:center}.em09{font-size:.9em}.em12{font-size:1.2em}.ml3{margin-left:3px}.ml6{margin-left:6px}.ml10{margin-left:10px}.mr3{margin-right:3px}.mr6{margin-right:6px}.mt10{margin-top:10px}.mt20{margin-top:20px}.mb10{margin-bottom:10px}.mb20{margin-bottom:20px}.text-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%}.text-ellipsis-2{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;word-break:break-word}.main-bg{background-color:var(--main-bg-color, var(--surface-1))}.separator{position:relative;letter-spacing:.08em}.icon-circle+.icon-circle:before{content:"·";display:inline-block;margin:0 .45em;opacity:.55}.article-avatar name,.article-avatar .name,.user-name{display:inline-flex;align-items:center;gap:4px;min-width:0;max-width:100%}.pull-right{float:right}.pull-left{float:left}body.single main.container .content-layout{display:block;min-width:0}body.single main.container .content-layout>*{min-width:0;max-width:100%}body.single main.container .content-layout>.breadcrumb,body.single main.container .content-layout>ul.breadcrumb,body.single main.container .content-layout>.breadcrumb-nav,body.single main.container .content-layout>.breadcrumbs-wrap{position:relative;z-index:1;margin-top:0;margin-bottom:12px;padding-top:2px}body.single .sidebar .aksrt-panel,body.single .sidebar .widget{margin-bottom:15px}body.single main.container{box-sizing:border-box}.article,article.article.box-body,.article.main-bg.box-body{padding:0 30px;overflow:hidden}@media(max-width:767px){.article,article.article.box-body,.article.main-bg.box-body{padding:0 15px}.article-header .article-title{font-size:18px}}.entry-header,.article-header{margin-bottom:10px;padding-bottom:0;border-bottom:none;background:transparent;box-shadow:none;Line truncated
+1 -7
View File
@@ -107,13 +107,7 @@ main.container,
* math), so the card container gets no extra gutter either. The
* <=991.98px media rule below restores 15px for every .container. */
/* Header multifunc icon cards: pin typography baseline so cards render
* identically on all pages. .px12-sm is only defined globally in
* legacy-utilities.css, which is @import'd by the single-post aggregator;
* vendor CSS pins it at <=640px / .sidebar / .mobile-nav-widget only. */
.header-slider-card .icon-cover-card {
font-size: 12px;
}
/* Let the reference .px12-sm utility apply at its mobile breakpoint only. */
/* Keep the header multifunction search stable across route-specific CSS.
* Some routes load a later .abs-right utility, while the global input focus
-1
View File
@@ -239,7 +239,6 @@
.text-center { text-align: center; }
.em09 { font-size: 0.9em; }
.em12 { font-size: 1.2em; }
.px12-sm { font-size: 12px; }
.ml3 { margin-left: 3px; }
.ml6 { margin-left: 6px; }
.ml10 { margin-left: 10px; }
-436
View File
@@ -1,436 +0,0 @@
/**
* AKSRT - Search Results Route Stylesheet
*
* 搜索结果页 (search.php) 专用样式:
* 顶部 hero 卡片、Pill 形搜索框、清空按钮、提交按钮、
* 工具栏、空状态、关键词高亮 mark。
*
* Tokens: 颜色 / 间距 / 圆角 / 阴影 全部来自 core/tokens.css
*/
/* ========== 搜索页大框 ========== */
.search-hero-form {
max-width: 600px;
margin: 0 auto 28px;
position: relative;
}
.search-page-header {
display: grid;
gap: 10px;
margin-bottom: 24px;
padding: 24px;
border: 1px solid var(--color-line);
border-radius: var(--radius-lg);
background: linear-gradient(180deg, var(--surface-2), var(--surface-page));
}
.search-page-header__eyebrow {
margin: 0;
color: var(--color-primary);
font-size: 13px;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
}
.search-page-header__summary {
margin: 0;
max-width: 720px;
color: var(--color-ink-3);
}
.search-page-form {
display: flex;
align-items: center;
gap: 12px;
max-width: none;
margin: 0 0 16px;
}
.search-hero-form input[type="search"] {
width: 100%;
height: 52px;
padding: 0 116px 0 48px;
border-radius: var(--radius-pill);
border: 1px solid var(--color-line);
font-size: 16px;
background: var(--surface-2);
color: var(--color-ink);
box-sizing: border-box;
transition: border-color 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
}
.search-hero-form input[type="search"]:focus {
border-color: var(--color-primary);
box-shadow: 0 0 0 3px var(--color-primary-soft, rgba(59, 130, 246, 0.16));
background: var(--surface-page);
outline: none;
}
.search-hero-form .search-icon {
position: absolute;
left: 16px;
top: 50%;
transform: translateY(-50%);
color: var(--color-ink-4);
}
.search-hero-form .clear-search {
position: absolute;
right: 92px;
top: 50%;
transform: translateY(-50%);
width: 40px;
height: 40px;
border: none;
border-radius: var(--radius-btn);
background: var(--surface-3);
cursor: pointer;
color: var(--color-ink-4);
opacity: 0;
pointer-events: none;
transition: opacity 0.2s ease, color 0.2s ease, background 0.2s ease;
}
.search-hero-form .clear-search.is-visible {
opacity: 1;
pointer-events: auto;
}
.search-hero-form .clear-search:hover {
color: var(--color-ink);
background: var(--color-line);
}
.search-page-form__submit {
position: absolute;
right: 6px;
top: 50%;
transform: translateY(-50%);
min-width: 74px;
height: 40px;
padding: 0 16px;
border: none;
border-radius: var(--radius-pill);
background: var(--color-primary);
color: #fff;
font-weight: 600;
cursor: pointer;
transition: transform 0.2s ease, background 0.2s ease;
}
.search-page-form__submit:hover {
background: var(--color-primary-active, var(--color-primary));
}
.search-page-toolbar {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
margin-bottom: 0;
padding-bottom: 14px;
border-bottom: 1px solid var(--color-line);
}
.search-page-filters {
display: grid;
gap: 14px;
margin: 0;
padding: 16px 18px;
border: 1px solid var(--color-line);
border-radius: var(--radius-lg);
background: var(--surface-2);
}
.search-page-toolbar__count {
color: var(--color-ink-3);
}
.search-page-toolbar__reset {
color: var(--color-primary);
font-weight: 600;
}
.search-page-filters {
display: grid;
gap: 14px;
margin: 0 0 18px;
padding: 16px 18px;
border: 1px solid var(--color-line);
border-radius: var(--radius-lg);
background: var(--surface-2);
}
.search-page-filters__group {
display: flex;
align-items: flex-start;
gap: 12px;
}
.search-page-filters__label {
min-width: 36px;
padding-top: 6px;
color: var(--color-ink-4);
font-size: 13px;
font-weight: 700;
}
.search-page-filters__chips {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.search-page-filters__chip {
display: inline-flex;
align-items: center;
min-height: 34px;
padding: 0 14px;
border: 1px solid var(--color-line);
border-radius: var(--radius-pill);
background: var(--surface-page);
color: var(--color-ink-3);
font-weight: 500;
text-decoration: none;
transition: border-color 0.2s ease, color 0.2s ease, background 0.2s ease;
}
.search-page-filters__chip:hover,
.search-page-filters__chip.is-active {
border-color: var(--color-primary);
color: var(--color-primary);
background: var(--color-primary-soft, rgba(59, 130, 246, 0.12));
}
/* ========== 分类筛选下拉 ========== */
.search-page-filters__select-wrap {
position: relative;
}
.search-page-filters__select {
appearance: none;
min-height: 34px;
padding: 0 32px 0 14px;
border: 1px solid var(--color-line);
border-radius: var(--radius-pill);
background: var(--surface-page);
color: var(--color-ink);
font: 500 14px/1 var(--font-ui);
cursor: pointer;
transition: border-color 0.2s ease;
}
.search-page-filters__select-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;
}
.search-page-filters__select:hover,
.search-page-filters__select:focus {
border-color: var(--color-primary);
outline: none;
}
.search-page-form__meta {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 12px;
margin: 0 0 16px;
}
.search-page-form__types {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.search-page-form__type {
display: inline-flex;
align-items: center;
min-height: 34px;
padding: 0 14px;
border: 1px solid var(--color-line);
border-radius: var(--radius-pill);
background: var(--surface-2);
color: var(--color-ink-3);
font-weight: 500;
cursor: pointer;
transition: border-color 0.2s ease, color 0.2s ease, background 0.2s ease;
}
.search-page-form__type:hover,
.search-page-form__type.is-active {
border-color: var(--color-primary);
color: var(--color-primary);
background: var(--color-primary-soft, rgba(59, 130, 246, 0.12));
}
.search-page-form__category-wrap {
position: relative;
}
.search-page-form__category {
appearance: none;
min-height: 36px;
padding: 0 34px 0 14px;
border: 1px solid var(--color-line);
border-radius: var(--radius-pill);
background: var(--surface-2);
color: var(--color-ink);
font: 500 14px/1 var(--font-ui);
cursor: pointer;
}
.search-page-form__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;
}
.search-page-form__category:disabled {
opacity: 0.56;
cursor: not-allowed;
}
/* ========== 空状态 ========== */
.search-page-empty {
display: grid;
gap: 14px;
justify-items: center;
padding-top: 32px;
}
.search-page-empty__icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 72px;
height: 72px;
margin: 0;
border-radius: 999px;
background: var(--surface-2);
color: var(--color-ink-4);
}
.search-page-empty__icon svg {
width: 36px;
height: 36px;
}
.search-page-empty__text {
margin: 0;
color: var(--color-ink-4);
}
.search-page-empty__tips {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 8px;
max-width: 720px;
}
.search-page-empty__tips span,
.search-page-empty__chip {
display: inline-flex;
align-items: center;
min-height: 34px;
padding: 0 12px;
border: 1px solid var(--color-line);
border-radius: var(--radius-pill);
background: var(--surface-2);
color: var(--color-ink-3);
}
.search-page-empty__actions {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 10px;
}
.search-page-empty__chip:hover {
border-color: var(--color-primary);
color: var(--color-primary);
}
@media (max-width: 767px) {
.search-page-header {
padding: 20px 16px;
}
.search-page-form {
margin-bottom: 14px;
}
.search-hero-form input[type="search"] {
height: 54px;
padding-right: 100px;
}
.search-hero-form .clear-search {
right: 76px;
width: 36px;
height: 36px;
}
.search-page-form__submit {
min-width: 64px;
height: 36px;
padding: 0 14px;
}
.search-page-form__meta {
flex-direction: column;
align-items: stretch;
}
.search-page-form__category-wrap {
width: 100%;
}
.search-page-form__category {
width: 100%;
}
.search-page-toolbar {
flex-direction: column;
align-items: flex-start;
}
.search-page-filters {
padding: 14px;
}
.search-page-filters__group {
flex-direction: column;
gap: 8px;
}
.search-page-filters__label {
min-width: 0;
padding-top: 0;
}
}
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="579" height="455"><g fill="none" fill-rule="evenodd"><path fill="none" d="M-30-89h640v640H-30z"/><g fill-rule="nonzero"><path fill="#F3F9FF" d="M251.432 154.715a24.006 24.006 0 0 1-10.305-19.712 24.008 24.008 0 0 1 10.3-19.717c15.255-10.602 22.268-21.828 16.644-35.407-5.624-13.577-18.519-16.557-36.8-13.268a24.006 24.006 0 0 1-21.224-6.65 24.008 24.008 0 0 1-6.659-21.227c3.29-18.284.312-31.18-13.267-36.805-13.58-5.625-24.806 1.39-35.408 16.644a24.005 24.005 0 0 1-39.429-.004C104.684 3.317 93.46-3.693 79.881 1.93 66.304 7.555 63.323 20.45 66.612 38.73a24.004 24.004 0 0 1-6.65 21.224 24.008 24.008 0 0 1-21.227 6.659C20.451 63.323 7.555 66.3 1.93 79.88c-5.624 13.578 1.39 24.805 16.644 35.406a24.005 24.005 0 0 1-.004 39.43c-15.252 10.6-22.264 21.826-16.64 35.403 5.624 13.578 18.522 16.558 36.805 13.267a24.002 24.002 0 0 1 21.229 6.654 24.012 24.012 0 0 1 6.648 21.23c-3.29 18.281-.309 31.176 13.268 36.8 13.579 5.624 24.805-1.389 35.407-16.645a24.005 24.005 0 0 1 39.429.004c10.6 15.252 21.826 22.264 35.403 16.64 13.577-5.624 16.557-18.52 13.268-36.8a24.009 24.009 0 0 1 6.651-21.226 24.004 24.004 0 0 1 21.226-6.659c18.284 3.29 31.181.312 36.807-13.267 5.625-13.577-1.386-24.803-16.638-35.403Z"/><ellipse cx="136.067" cy="136.601" fill="#DCEEFD" rx="70.968" ry="72.569"/><path fill="#FFF" d="M205.968 137.684c0 39.437-32.049 71.486-71.485 71.486-21.207 0-40.39-9.293-53.376-24.067 12.51 11.318 29.19 18.11 47.419 18.11 39.436 0 71.485-32.05 71.485-71.486 0-18.23-6.791-34.908-18.11-47.419 14.774 12.987 24.067 32.17 24.067 53.376Z"/><path fill="#D0E7FE" d="M188.893 88.098c-12.51-11.318-29.19-18.11-47.419-18.11-39.436 0-71.485 32.05-71.485 71.486 0 18.228 6.791 34.909 18.11 47.42-14.774-12.987-24.067-32.17-24.067-53.377 0-39.436 32.049-71.485 71.485-71.485 21.207 0 40.39 9.293 53.376 24.066Z"/></g><g fill-rule="nonzero"><path fill="#71E5CB" d="M358.462 378.825c-6-14.731-14.95-35.603 3.343-47.927 18.292-12.324 1.592-19.623.999-37.486-.594-17.863 18.078-22.454 17.52-30.924-.559-8.47-1.486-23.448.238-29.839 2.883-10.694 24.469-15.55 26.672 14.562 1.385 18.923 3.244 30.348 12.86 43.845 9.617 13.498-11.564 27.768-11.174 38.635.391 10.867 10.83 9.257 9.688 32.284-1.142 23.028-15.564 40.442-29.276 39.416-9.313-.7-25.393-9.12-30.87-22.566Z"/><path fill="#39B499" d="M404.709 300.97a.825.825 0 0 0-1.127.388c-.16.335-3.97 8.042-10.183 5.524.736-5.103 1.068-9.882.716-14.195.008-.03.027-.054.032-.086a.894.894 0 0 0-.086-.563 34.072 34.072 0 0 0-.29-2.25c-1.886-11.23-.618-25.764.138-34.446.442-5.065.642-7.546.387-8.597-.114-.473-.578-.76-1.018-.635-.449.118-.72.598-.605 1.068.195.804-.097 4.14-.432 8.002-.765 8.772-2.044 23.452-.12 34.914.063.366.104.744.153 1.119-2.682-.884-9.075-3.655-11.196-10.53-.14-.46-.612-.714-1.056-.564-.441.15-.68.645-.538 1.108 2.587 8.385 10.574 11.212 12.985 11.888.682 9.208-1.87 20.798-4.567 33.006-2.141 9.688-4.356 19.705-5.079 29.177-.317 4.149-.17 9.021.257 14.219-4.57-2.355-17.029-9.662-17.357-19.542-.015-.484-.425-.82-.867-.848-.463.018-.825.424-.808.911.39 11.758 15.412 19.702 19.203 21.522 1.237 13.057 4.13 27.885 6.272 38.863 1.524 7.805 2.84 14.546 2.575 15.866-.096.477.194.943.647 1.043.059.014.116.02.175.02a.85.85 0 0 0 .82-.699c.321-1.603-.661-6.786-2.572-16.582-2.115-10.832-4.961-25.434-6.209-38.293.09-.085.185-.17.235-.298a.89.89 0 0 0-.359-1.083c-.46-5.175-.635-10.02-.379-14.179 2.842-.19 12.422-1.52 15.019-10.807.13-.467-.124-.956-.569-1.091-.444-.134-.908.13-1.04.596-2.274 8.133-10.508 9.37-13.277 9.546.784-9.057 2.893-18.65 4.947-27.942 1.365-6.178 2.693-12.197 3.595-17.863.935.338 1.836.5 2.694.5 4.569 0 7.94-4.262 9.256-7 .206-.44.04-.97-.372-1.187Z"/><g><path fill="#55CEB3" d="M520.478 364.37c8.427-20.703 20.998-50.036-4.694-67.357-25.694-17.321-2.237-27.577-1.403-52.682.834-25.106-25.394-31.558-24.608-43.462.784-11.904 2.086-32.953-.334-41.935-4.052-15.03-34.37-21.855-37.462 20.466-1.944 26.593-4.557 42.649-18.063 61.619-13.505 18.97 16.245 39.025 15.695 54.295-.55 15.27-15.21 13.01-13.607 45.372 1.603 32.363 21.859 56.838 41.12 55.394 13.079-.98 35.663-12.812 43.356-31.71Z"/><path fill="#39B499" d="M512.297 323.893c.016-.486-.347-.895-.81-.913-.445.04-.85.365-.868.85-.483 14.503-19.195 25.066-25.133 28.059.662-7.443.902-14.486.438-20.561-1.012-13.286-4.12-27.353-7.124-40.956-3.82-17.292-7.43-33.704-6.401-46.741 3.01-.807 14.56-4.629 18.231-16.536.143-.463-.099-.96-.538-1.11-.442-.152-.915.105-1.058.565-3.162 10.248-12.997 14.122-16.457 15.19.085-.721.174-1.439.292-2.136 2.695-16.06.9-36.662-.172-48.97-.495-5.69-.886-10.178-.599-11.368.114-.472-.157-.952-.606-1.07-.443-.125-.906.164-1.018.637-.344 1.415-.046 5.076.554 11.962 1.064 12.22 2.846 32.675.19 48.504a46.89 46.89 0 0 0-.407 3.165.916.916 0 0 0-.12.656c.01.054.036.098.055.148-.509 6.133-.022 12.95 1.043 20.239-.008.003-.016.001-.023.005-9.137 3.935-14.73-7.37-14.962-7.85-.21-.436-.717-.61-1.128-.39-.415.22-.58.751-.371 1.185.055.112 4.75 9.651 12.675 9.651 1.275 0 2.64-.263 4.078-.83Line truncated

After

Width:  |  Height:  |  Size: 15 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 400 240"><defs><style>.cls-1,.cls-5,.cls-6{isolation:isolate;}.cls-2{fill:url(#未命名的渐变_37);}.cls-3{fill:url(#未命名的渐变_32);}.cls-4{opacity:0.36;mix-blend-mode:multiply;fill:url(#radial-gradient);}.cls-5{opacity:0.84;fill:url(#未命名的渐变_36);}.cls-6{opacity:0.66;fill:url(#未命名的渐变_35);}.cls-7{fill:url(#未命名的渐变_34);}.cls-8{fill:url(#未命名的渐变_18);}.cls-9{fill:url(#未命名的渐变_32-2);}.cls-10{fill:#fff;}.cls-11{fill:url(#未命名的渐变_31);}.cls-12{fill:url(#未命名的渐变_31-2);}.cls-13{fill:url(#未命名的渐变_30);}.cls-14{fill:url(#未命名的渐变_26);}.cls-15{fill-rule:evenodd;fill:url(#未命名的渐变_22);}.cls-16{fill:#fbdbbe;}.cls-17{fill:url(#未命名的渐变_19);}.cls-18{fill:none;stroke:#fff;stroke-miterlimit:10;}.cls-19{fill:url(#未命名的渐变_48);}.cls-20{fill:url(#未命名的渐变_18-2);}</style><linearGradient id="未命名的渐变_37" x1="861.66" y1="-2991.52" x2="861.66" y2="-2992.02" gradientTransform="matrix(390, 0, 0, -196, -335845.8, -586227.47)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#a8a8a8" stop-opacity="0.15"/><stop offset="1" stop-color="#a8a8a8" stop-opacity="0"/></linearGradient><linearGradient id="未命名的渐变_32" x1="108.61" y1="106.35" x2="298.51" y2="106.35" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#ededed"/><stop offset="0.03" stop-color="#dcdcdc"/><stop offset="1" stop-color="#d7d7d7"/></linearGradient><radialGradient id="radial-gradient" cx="522.21" cy="16016.09" r="98.54" gradientTransform="translate(-839.13 -2602.83) scale(2 0.17)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#808083"/><stop offset="0.07" stop-color="#9a9a9c"/><stop offset="0.17" stop-color="#b9b9ba"/><stop offset="0.28" stop-color="#d2d2d4"/><stop offset="0.4" stop-color="#e6e6e7"/><stop offset="0.53" stop-color="#f4f4f5"/><stop offset="0.7" stop-color="#fdfdfd"/><stop offset="0.99" stop-color="#fff"/></radialGradient><radialGradient id="未命名的渐变_36" cx="1030.02" cy="-3021.58" r="1.3" gradientTransform="matrix(0, 21, 22.62, 0, 68425.11, -21468.04)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#c1c1c1"/></radialGradient><radialGradient id="未命名的渐变_35" cx="1075.82" cy="-3011.86" r="0.94" gradientTransform="matrix(0, 16, 17.23, 0, 52239.31, -17129.56)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#d7d7d7"/></radialGradient><linearGradient id="未命名的渐变_34" x1="114.19" y1="106.35" x2="300.78" y2="106.35" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f2f2f2"/><stop offset="1" stop-color="#f3f3f3"/></linearGradient><linearGradient id="未命名的渐变_18" x1="200" y1="85.58" x2="286.28" y2="85.58" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#d7d7d7"/><stop offset="1" stop-color="#ededed"/></linearGradient><linearGradient id="未命名的渐变_32-2" x1="184.99" y1="56.58" x2="229.99" y2="56.58" xlink:href="#未命名的渐变_32"/><linearGradient id="未命名的渐变_31" x1="298" y1="188.71" x2="288.59" y2="188.71" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#1f1f49"/><stop offset="1" stop-color="#424776"/></linearGradient><linearGradient id="未命名的渐变_31-2" x1="303" y1="190.71" x2="293.59" y2="190.71" xlink:href="#未命名的渐变_31"/><linearGradient id="未命名的渐变_30" x1="306" y1="166.5" x2="287" y2="166.5" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#8caff7"/><stop offset="1" stop-color="#6a95f5"/></linearGradient><linearGradient id="未命名的渐变_26" x1="2762.45" y1="103.71" x2="2774.62" y2="103.71" gradientTransform="matrix(-1, 0, 0, 1, 3062.8, 0)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff6ec"/><stop offset="1" stop-color="#fdead6"/></linearGradient><linearGradient id="未命名的渐变_22" x1="963.82" y1="-3150.31" x2="963.82" y2="-3151.06" gradientTransform="translate(17643.86 -59763.03) rotate(180) scale(18 19)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#494b80"/><stop offset="1" stop-color="#272756"/></linearGradient><linearGradient id="未命名的渐变_19" x1="2747.71" y1="129.44" x2="2778.99" y2="129.44" gradientTransform="matrix(-1, 0, 0, 1, 3062.8, 0)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#faa35e"/><stop offset="1" stop-color="#f66357"/></linearGradient><linearGradient id="未命名的渐变_48" x1="207.49" y1="57" x2="207.49" y2="26" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#b2b2b2" stop-opacity="0.8"/><stop offset="0.02" stop-color="#b7b7b7" stop-opacity="0.82"/><stop offset="0.09" stop-color="#c8c8c8" stop-opacity="0.87"/><stop offset="0.17" stop-color="#d6d6d6" stop-opacity="0.92"/><stop offset="0.26" stop-color="#e0e0e0" stop-opacity="0.96"/><stoLine truncated

After

Width:  |  Height:  |  Size: 8.4 KiB

+1 -42
View File
@@ -1,5 +1,5 @@
/**
* AKSRT Article Tools — password toggles, search clear, article actions, interaction bar
* AKSRT Article Tools — password toggles, article actions, interaction bar
*/
(function () {
"use strict";
@@ -19,46 +19,6 @@
});
}
function initSearchClear() {
var btn = document.getElementById("search-clear-btn");
var input = document.getElementById("search-page-input");
if (btn && input && !btn.dataset.aksrtSearchClearBound) {
btn.dataset.aksrtSearchClearBound = "1";
var syncClearButton = function () {
var hasValue = input.value.trim().length > 0;
btn.classList.toggle("is-visible", hasValue);
btn.hidden = !hasValue;
};
btn.addEventListener("click", function () {
input.value = "";
input.focus();
syncClearButton();
});
input.addEventListener("input", syncClearButton);
syncClearButton();
}
var categorySelect = document.getElementById("search-category-filter");
if (categorySelect) {
categorySelect.addEventListener("change", function () {
var url = new URL(window.location.href);
if (this.value) {
url.searchParams.set("aksrt_category", this.value);
} else {
url.searchParams.delete("aksrt_category");
}
if (url.searchParams.get("aksrt_search_type") && url.searchParams.get("aksrt_search_type") !== "post") {
url.searchParams.delete("aksrt_category");
}
url.searchParams.delete("paged");
window.location.href = url.toString();
});
}
}
function initArticleTools() {
var buttons = document.querySelectorAll("[data-article-tool]");
if (!buttons.length) return;
@@ -343,7 +303,6 @@
}
function init(root) {
initSearchClear();
initArticleTools();
initPostMetaMenus(root);
initPasswordToggles(root);
+9 -24
View File
@@ -1165,8 +1165,6 @@ function get_new_dplayer(_this, func) {
v_u.indexOf('.mpd') != -1 && _win.dplayer.tbquire.push('dash');
v_u.indexOf('.flv') != -1 && _win.dplayer.tbquire.push('flv');
jQuery('link#dplayer').length || jQuery('dplayer').append('<link type="text/css" id="dplayer" rel="stylesheet" href="' + _win.uri + '/css/dplayer.min.css?ver=' + _win.ver + '">');
_win.dplayer.tbquire.push('dplayer');
tbquire(_win.dplayer.tbquire, function () {
@@ -3004,24 +3002,6 @@ _win.bd.on('click', '.rewards', function () {
//作者页、文章导航、前台编辑、通用模板、微信分享均由 AKSRT 自有脚本按路由入队,
//legacy main 不再通过 tbquire 重复加载同功能的旧模块副本。
//搜索关键词高亮
if (_win.bd.hasClass('search')) {
var val = jQuery('.search-desc-text .search-key').text();
try {
var reg = eval('/' + val + '/i');
jQuery('.search-tab .item-heading a,.search-tab .item-excerpt,.search-tab .forum-title a,.search-tab .excerpt,#search-tab-user .display-name').each(function () {
var $this = jQuery(this);
if ($this.text().search(reg) != -1) {
$this.html(
$this.html().replace(reg, function (w) {
return '<b class="focus-color">' + w + '</b>';
})
);
}
});
} catch (e) {}
}
//数字填写翻页
_win.bd.on('click', '.pag-jump .jump-icon', function () {
var _input = jQuery(this).siblings('.jump-input');
@@ -3449,7 +3429,7 @@ jQuery.fn.AutoSearch = function () {
//搜索功能-恢复默认占位符
_win.bd.on('click', '.main-search [data-for]', function () {
var _placeholder = jQuery('.main-search').find('.scale-placeholder');
var _placeholder = jQuery(this).closest('form').find('.scale-placeholder');
if (_placeholder.length) {
_placeholder.text(_placeholder.attr('default'));
}
@@ -3534,6 +3514,8 @@ if (jQuery('.search-page-ajaxpager').length) {
_win.bd.on('submit', '.page-search-box .search-form', function () {
var $this = jQuery(this);
var data = $this.serializeObject();
// The empty-search page has no results pager to replace.
if (!String(data.s || '').trim()) return;
var url = new URL($this.attr('action'));
url.search = new URLSearchParams(data).toString();
@@ -3679,12 +3661,15 @@ jQuery.fn.serializeObject = function () {
//清空搜索关键词
_win.bd.on('click', '.trash-history-search', function () {
if (confirm(aksrt__('confirm_clear_search')) == true) {
var control = jQuery(this);
jQuery('.history-search')
.slideUp()
.delay(1000, function () {
.slideUp(300, function () {
jQuery(this).remove();
});
jQuery.cookie('history_search', '');
jQuery.cookie('history_search', null, {
path: control.attr('data-cookie-path') || '/',
domain: control.attr('data-cookie-domain') || '',
});
}
});
+1 -1
View File
@@ -1 +1 @@
(function($,window2,document2){"use strict";function closeNotyf($element){$element.addClass("notyn-out"),window2.setTimeout(function(){$element.remove()},1e3)}function notyf2(message,type,time,id){var $body=jQuery(document2.body);jQuery(".notyn").length||$body.append('<div class="notyn"></div>'),type=type||"success",type==="error"&&(type="danger"),time=time||5e3,time=time<100?time*1e3:time;var idAttribute=id?' id="'+id+'"':"",$notification=jQuery('<div class="noty1"'+idAttribute+'><div class="notyf '+type+'">'+message+"</div></div>"),shouldClose=!id;id&&jQuery("#"+id).length?(jQuery("#"+id).find(".notyf").removeClass().addClass("notyf "+type).html(message),$notification=jQuery("#"+id),shouldClose=!0):jQuery(".notyn").append($notification),shouldClose&&window2.setTimeout(function(){closeNotyf($notification)},time)}jQuery(document2.body).on("click",".noty1",function(){closeNotyf(jQuery(this))}),window2.notyf=notyf2})(jQuery,window,document),(function(window2){"use strict";var allowedKinds={identity:!0,badges:!0,orders:!0,vip:!0},allowedEvents={click:!0,shell:!0,"first-content":!0,ready:!0,"action-start":!0,"action-end":!0,unauthorized:!0,error:!0},sessions=Object.create(null),sequence=0,maxSessions=100;function normalize(value,fallback){var normalized=String(value||fallback||"").toLowerCase().replace(/[^a-z0-9-]/g,"");return normalized||fallback}function now(){return window2.performance&&typeof window2.performance.now=="function"?window2.performance.now():0}function markName(session,event){return"aksrt-modal-"+session.kind+"-"+session.id+"-"+event}function emit(session,event){if(!(!window2.performance||typeof window2.performance.mark!="function")){var name=markName(session,event);if(window2.performance.mark(name),session.marks[event]=name,typeof window2.performance.measure=="function"&&session.marks.click&&event!=="click")try{window2.performance.measure("aksrt-modal-"+session.kind+"-"+session.id+"-click-to-"+event,session.marks.click,name)}catch{}}}function start(kind){var safeKind=normalize(kind,"unknown");allowedKinds[safeKind]||(safeKind="unknown"),sequence+=1;var id=String(sequence),session={id,kind:safeKind,startedAt:now(),marks:Object.create(null)};sessions[id]=session,emit(session,"click");for(var ids=Object.keys(sessions);ids.length>maxSessions;)delete sessions[ids.shift()];return id}function mark(id,event){var session=sessions[String(id||"")],safeEvent=normalize(event,"error");!session||!allowedEvents[safeEvent]||emit(session,safeEvent)}function finish(id){mark(id,"ready")}function fail(id){mark(id,"error")}window2.AksrtModalTelemetry={start,mark,finish,error:fail}})(window),(function(window2){"use strict";function data(){return window2.aksrtData||window2.aksrt||{}}function createIdempotencyKey(){if(window2.crypto&&typeof window2.crypto.randomUUID=="function")return window2.crypto.randomUUID();if(!window2.crypto||typeof window2.crypto.getRandomValues!="function")throw new Error("当前浏览器无法生成安全的操作标识");var bytes=new Uint8Array(16);window2.crypto.getRandomValues(bytes),bytes[6]=bytes[6]&15|64,bytes[8]=bytes[8]&63|128;var hex=Array.prototype.map.call(bytes,function(value){return value.toString(16).padStart(2,"0")}).join("");return hex.slice(0,8)+"-"+hex.slice(8,12)+"-"+hex.slice(12,16)+"-"+hex.slice(16,20)+"-"+hex.slice(20)}function restBase(){var config=data(),raw=config.restUrl||config.apiUrl||config.rest_url||"",siteUrl=config.siteUrl||config.homeUrl||window2.location.origin+"/";return window2.location.protocol==="https:"&&siteUrl.substring(0,5)==="http:"&&(siteUrl="https:"+siteUrl.substring(5)),raw?String(raw).replace(/\/$/,""):String(siteUrl).replace(/\/$/,"")+"/index.php?rest_route=/aksrt/v1"}function appendQuery(url2,query){if(!query)return url2;var parts=[];return typeof query=="string"?parts=query.replace(/^\?/,"").split("&").filter(Boolean):typeof query=="object"&&Object.keys(query).forEach(function(key){query[key]===void 0||query[key]===null||parts.push(encodeURIComponent(key)+"="+encodeURIComponent(String(query[key])))}),parts.length?url2+(url2.indexOf("?")>=0?"&":"?")+parts.join("&"):url2}function url(path,query){path=String(path||"");var inlineQuery="",queryIndex=path.indexOf("?");if(queryIndex>=0&&(inlineQuery=path.slice(queryIndex+1),path=path.slice(0,queryIndex)),/^https?:\/\//i.test(path))return appendQuery(path,query||inlineQuery);path.charAt(0)!=="/"&&(path="/"+path);var base=restBase(),result=(base.indexOf("rest_route=")>=0,base+path);return appendQuery(result,query||inlineQuery)}function headers(options){var config=data(),source=options&&options.headers||{},result={},nonce=config.restNonce||config.nonce||"";return Object.keys(source).forEach(function(key){result[key]=source[key]}),result.Accept||(result.Accept="application/json, text/html;q=0.9, */*;q=0.8"),nonce&&!result["X-WP-Nonce"]&&(result["X-WP-Nonce"]=nonce),options&&options.body!==void 0&&options.body!==null&&!(window2.FormData&&options.body instanceof window2.FormData)&&!result["Content-Type"]&Line truncated
(function($,window2,document2){"use strict";function closeNotyf($element){$element.addClass("notyn-out"),window2.setTimeout(function(){$element.remove()},1e3)}function notyf2(message,type,time,id){var $body=jQuery(document2.body);jQuery(".notyn").length||$body.append('<div class="notyn"></div>'),type=type||"success",type==="error"&&(type="danger"),time=time||5e3,time=time<100?time*1e3:time;var idAttribute=id?' id="'+id+'"':"",$notification=jQuery('<div class="noty1"'+idAttribute+'><div class="notyf '+type+'">'+message+"</div></div>"),shouldClose=!id;id&&jQuery("#"+id).length?(jQuery("#"+id).find(".notyf").removeClass().addClass("notyf "+type).html(message),$notification=jQuery("#"+id),shouldClose=!0):jQuery(".notyn").append($notification),shouldClose&&window2.setTimeout(function(){closeNotyf($notification)},time)}jQuery(document2.body).on("click",".noty1",function(){closeNotyf(jQuery(this))}),window2.notyf=notyf2})(jQuery,window,document),(function(window2){"use strict";var allowedKinds={identity:!0,badges:!0,orders:!0,vip:!0},allowedEvents={click:!0,shell:!0,"first-content":!0,ready:!0,"action-start":!0,"action-end":!0,unauthorized:!0,error:!0},sessions=Object.create(null),sequence=0,maxSessions=100;function normalize(value,fallback){var normalized=String(value||fallback||"").toLowerCase().replace(/[^a-z0-9-]/g,"");return normalized||fallback}function now(){return window2.performance&&typeof window2.performance.now=="function"?window2.performance.now():0}function markName(session,event){return"aksrt-modal-"+session.kind+"-"+session.id+"-"+event}function emit(session,event){if(!(!window2.performance||typeof window2.performance.mark!="function")){var name=markName(session,event);if(window2.performance.mark(name),session.marks[event]=name,typeof window2.performance.measure=="function"&&session.marks.click&&event!=="click")try{window2.performance.measure("aksrt-modal-"+session.kind+"-"+session.id+"-click-to-"+event,session.marks.click,name)}catch{}}}function start(kind){var safeKind=normalize(kind,"unknown");allowedKinds[safeKind]||(safeKind="unknown"),sequence+=1;var id=String(sequence),session={id,kind:safeKind,startedAt:now(),marks:Object.create(null)};sessions[id]=session,emit(session,"click");for(var ids=Object.keys(sessions);ids.length>maxSessions;)delete sessions[ids.shift()];return id}function mark(id,event){var session=sessions[String(id||"")],safeEvent=normalize(event,"error");!session||!allowedEvents[safeEvent]||emit(session,safeEvent)}function finish(id){mark(id,"ready")}function fail(id){mark(id,"error")}window2.AksrtModalTelemetry={start,mark,finish,error:fail}})(window),(function(window2){"use strict";function data(){return window2.aksrtData||window2.aksrt||{}}function createIdempotencyKey(){if(window2.crypto&&typeof window2.crypto.randomUUID=="function")return window2.crypto.randomUUID();if(!window2.crypto||typeof window2.crypto.getRandomValues!="function")throw new Error("当前浏览器无法生成安全的操作标识");var bytes=new Uint8Array(16);window2.crypto.getRandomValues(bytes),bytes[6]=bytes[6]&15|64,bytes[8]=bytes[8]&63|128;var hex=Array.prototype.map.call(bytes,function(value){return value.toString(16).padStart(2,"0")}).join("");return hex.slice(0,8)+"-"+hex.slice(8,12)+"-"+hex.slice(12,16)+"-"+hex.slice(16,20)+"-"+hex.slice(20)}function restBase(){var config=data(),raw=config.restUrl||config.apiUrl||config.rest_url||"",siteUrl=config.siteUrl||config.homeUrl||window2.location.origin+"/";return window2.location.protocol==="https:"&&siteUrl.substring(0,5)==="http:"&&(siteUrl="https:"+siteUrl.substring(5)),raw?String(raw).replace(/\/$/,""):String(siteUrl).replace(/\/$/,"")+"/index.php?rest_route=/aksrt/v1"}function appendQuery(url2,query){if(!query)return url2;var parts=[];return typeof query=="string"?parts=query.replace(/^\?/,"").split("&").filter(Boolean):typeof query=="object"&&Object.keys(query).forEach(function(key){query[key]===void 0||query[key]===null||parts.push(encodeURIComponent(key)+"="+encodeURIComponent(String(query[key])))}),parts.length?url2+(url2.indexOf("?")>=0?"&":"?")+parts.join("&"):url2}function url(path,query){path=String(path||"");var inlineQuery="",queryIndex=path.indexOf("?");if(queryIndex>=0&&(inlineQuery=path.slice(queryIndex+1),path=path.slice(0,queryIndex)),/^https?:\/\//i.test(path))return appendQuery(path,query||inlineQuery);path.charAt(0)!=="/"&&(path="/"+path);var base=restBase(),result=(base.indexOf("rest_route=")>=0,base+path);return appendQuery(result,query||inlineQuery)}function headers(options){var config=data(),source=options&&options.headers||{},result={},nonce=config.restNonce||config.nonce||"";return Object.keys(source).forEach(function(key){result[key]=source[key]}),result.Accept||(result.Accept="application/json, text/html;q=0.9, */*;q=0.8"),nonce&&!result["X-WP-Nonce"]&&(result["X-WP-Nonce"]=nonce),options&&options.body!==void 0&&options.body!==null&&!(window2.FormData&&options.body instanceof window2.FormData)&&!result["Content-Type"]&Line truncated
+2 -2
View File
@@ -11,12 +11,12 @@ if (!function_exists('aksrt_get_ajax_null')) {
/**
* Empty state for AJAX list replace.
*/
function aksrt_get_ajax_null(?string $text = null, $margin = 60, string $img = 'null.svg'): string {
function aksrt_get_ajax_null(?string $text = null, $margin = 60, string $img = 'null.svg', int $width = 280): string {
if (null === $text) {
$text = __('内容空空如也', 'aksrt');
}
if (function_exists('aksrt_get_null')) {
return aksrt_get_null($text, $margin, $img, 'ajax-item aksrt-ajax-null');
return aksrt_get_null($text, $margin, $img, 'ajax-item aksrt-ajax-null', $width);
}
return '<div class="text-center ajax-item aksrt-ajax-null" style="padding:' . esc_attr((string) $margin) . 'px 0;">'
. '<p class="muted-3-color">' . esc_html((string) $text) . '</p></div>';
+8 -4
View File
@@ -214,7 +214,7 @@ if (!function_exists('aksrt_author_minicard')) :
* @param string $class
* @param bool $blur_bg
*/
function aksrt_author_minicard(int $user_id, string $class = '', bool $blur_bg = false): string {
function aksrt_author_minicard(int $user_id, string $class = '', bool $blur_bg = false, string $highlight_query = ''): string {
if ($user_id <= 0) {
return '';
}
@@ -240,6 +240,7 @@ if (!function_exists('aksrt_author_minicard')) :
'medal' => true,
'auth' => true,
'level' => true,
'highlight_query' => $highlight_query,
])
: '<a href="' . esc_url($home) . '">' . esc_html($user->display_name) . '</a>';
@@ -248,20 +249,23 @@ if (!function_exists('aksrt_author_minicard')) :
? aksrt_get_user_follow('focus-color px12 ml10 follow flex0 but', $user_id)
: '';
$desc = function_exists('aksrt_get_user_description') ? aksrt_get_user_description($user_id) : trim((string) get_user_meta($user_id, 'description', true));
$blur = '';
if ($blur_bg) {
$blur = '<div class="abs-blur-bg blur"><img' . aksrt_get_lazy_attr('lazy_avatar', $avatar_url, '', aksrt_get_lazy_thumb('sm')) . ' alt=""></div>';
}
$description = function_exists('aksrt_get_user_description') ? aksrt_get_user_description($user_id) : trim((string) get_user_meta($user_id, 'description', true));
$description_html = $highlight_query !== '' && function_exists('aksrt_renderer_highlight_text')
? aksrt_renderer_highlight_text($description, $highlight_query)
: esc_html($description);
return '<div class="author-minicard radius8 relative-h ' . esc_attr($class) . '">'
. $blur
. '<ul class="list-inline relative">'
. '<li>' . $avatar_box . '</li>'
. '<li><dl>'
. '<dt class="flex ac">' . $name . $follow . '</dt>'
. '<dd class="mt6 em09 muted-color text-ellipsis">' . esc_html($desc) . '</dd>'
. '<dd class="mt6 em09 muted-color text-ellipsis">' . $description_html . '</dd>'
. '</dl></li>'
. '</ul></div>';
}
+5 -1
View File
@@ -186,6 +186,7 @@ if (!function_exists('aksrt_get_user_name')) {
'auth' => true,
'level' => true,
'follow' => false,
'highlight_query' => '',
];
if (is_numeric($args)) {
$defaults['id'] = (int) $args;
@@ -221,7 +222,10 @@ if (!function_exists('aksrt_get_user_name')) {
}
}
$name_class = trim('display-name text-ellipsis ' . (string) $args['name_class']);
$name_link = '<a class="' . esc_attr($name_class) . '" href="' . esc_url($home) . '">' . esc_html($display) . '</a>';
$name_markup = !empty($args['highlight_query']) && function_exists('aksrt_renderer_highlight_text')
? aksrt_renderer_highlight_text((string) $display, (string) $args['highlight_query'])
: esc_html($display);
$name_link = '<a class="' . esc_attr($name_class) . '" href="' . esc_url($home) . '">' . $name_markup . '</a>';
$auth_html = '';
$medal_html = '';
+32 -9
View File
@@ -114,8 +114,11 @@ if (!function_exists('aksrt_header_slide_is_show')) {
return false;
}
// legacy (Zibll) renders the slider on paged archive pages too; no
// pagination exclusion here.
// Zibll only displays this component on the first archive page.
if ((int) $wp_query->get('paged') > 1) {
return false;
}
$settings = class_exists('\\AKSRT\\Settings\\Settings')
? \AKSRT\Settings\Settings::get_header_slider_settings()
: [];
@@ -199,6 +202,18 @@ if (!function_exists('aksrt_header_slider_allowed_html')) {
}
}
if (!function_exists('aksrt_header_slider_image')) {
/** @param string $src @param string $class @param string $alt */
function aksrt_header_slider_image(string $src, string $class, string $alt): string {
$lazy = function_exists('aksrt_is_lazy') && aksrt_is_lazy('lazy_sider');
if ($lazy) {
$class .= ' swiper-lazy';
}
$attrs = aksrt_get_lazy_attr('lazy_sider', $src, $class, aksrt_get_lazy_thumb('lg'));
return '<img' . $attrs . ' alt="' . esc_attr($alt) . '">';
}
}
if (!function_exists('aksrt_get_header_slider_markup')) {
/** @param array<string,mixed> $options */
function aksrt_get_header_slider_markup(array $options): string {
@@ -228,6 +243,7 @@ if (!function_exists('aksrt_get_header_slider_markup')) {
}
$is_mobile = wp_is_mobile();
$lazy = function_exists('aksrt_is_lazy') && aksrt_is_lazy('lazy_sider');
$slides_html = '';
$slide_count = 0;
$allow = aksrt_header_slider_allowed_html();
@@ -249,23 +265,30 @@ if (!function_exists('aksrt_get_header_slider_markup')) {
$link = is_array($slide['link'] ?? null) ? $slide['link'] : [];
$title = (string) ($text['title'] ?? '');
$alt = trim(wp_strip_all_tags($title));
if ($alt === '') {
$alt = trim(wp_strip_all_tags((string) ($link['text'] ?? '')));
}
$alt = $alt !== '' ? $alt . $site_suffix : __('幻灯片', 'aksrt') . $site_suffix;
$slide_class = trim((string) ($slide['class'] ?? ''));
$background_html = '';
if ($background_video !== '' && !$is_mobile) {
$slide_class .= ' slide-background-video';
$background_html = '<video autoplay loop muted playsinline class="fit-cover radius8" src="' . esc_url($background_video) . '"'
$background_html = '<video autoplay="" loop="" muted="" class="fit-cover radius8' . ($lazy ? ' lazyload' : '') . '"'
. ($lazy ? ' data-src="' . esc_url($background_video) . '" src=""' : ' src="' . esc_url($background_video) . '"')
. ($background !== '' ? ' poster="' . esc_url($background) . '"' : '') . '></video><div class="absolute"></div>';
} elseif ($video !== '') {
$slide_class .= ' slide-dplayer';
$background_html = '<video controls playsinline preload="metadata" class="fit-cover radius8" src="' . esc_url($video) . '"'
. ($background !== '' ? ' poster="' . esc_url($background) . '"' : '') . '></video>';
$background_html = '<div class="new-dplayer" video-url="' . esc_url($video) . '" video-type="auto"><div class="graphic" style="padding-bottom:50%;"><div class="abs-center text-center"><i class="fa fa-play-circle fa-4x muted-3-color opacity5" aria-hidden="true"></i></div></div></div>';
if ($background !== '') {
$background_html .= '<div class="absolute dplayer-poster"><img class="no-imgbox radius8" src="' . esc_url($background) . '" alt="' . esc_attr($alt) . '"><div class="absolute flex jc play-icon"><span class="toggle-radius"><i class="fa fas fa-play" aria-hidden="true"></i></span></div></div>';
$poster_class = 'absolute dplayer-poster' . (!empty($options['gradient_bg']) ? ' gradient-bg' : '');
$poster_attrs = !empty($options['gradient_bg']) ? ' data-opacity="0.2"' : '';
$background_html .= '<div class="' . esc_attr($poster_class) . '"' . $poster_attrs . '>'
. aksrt_header_slider_image($background, 'no-imgbox radius8', $alt)
. '<div class="absolute flex jc play-icon"><span class="toggle-radius"><i class="fa fa-play" aria-hidden="true"></i></span></div></div>';
}
} elseif ($background !== '') {
$background_html = '<img class="radius8" src="' . esc_url($background) . '" alt="' . esc_attr($alt) . '">';
$background_html = aksrt_header_slider_image($background, 'radius8', $alt);
}
if ($background_html === '') {
@@ -274,7 +297,7 @@ if (!function_exists('aksrt_get_header_slider_markup')) {
$blur_html = '';
if (!empty($options['blur_bg']) && $background !== '') {
$blur_html = '<div class="slide-blur-bg"><img class="no-imgbox" src="' . esc_url($background) . '" alt="' . esc_attr($alt) . '"></div>';
$blur_html = '<div class="slide-blur-bg">' . aksrt_header_slider_image($background, 'no-imgbox', $alt) . '</div>';
}
$layers_html = '';
@@ -300,7 +323,7 @@ if (!function_exists('aksrt_get_header_slider_markup')) {
if ($scale !== 100) {
$layer_attrs .= ' data-swiper-parallax-scale="' . esc_attr((string) ($scale / 100)) . '"';
}
$layers_html .= '<div class="' . esc_attr($layer_class) . '"' . $layer_attrs . '><img class="radius8" src="' . esc_url((string) $layer['image']) . '" alt="' . esc_attr($alt) . '"></div>';
$layers_html .= '<div class="' . esc_attr($layer_class) . '"' . $layer_attrs . '>' . aksrt_header_slider_image((string) $layer['image'], 'radius8', $alt) . '</div>';
}
$text_html = '';
+11 -2
View File
@@ -111,8 +111,17 @@ if (!function_exists('aksrt_renderer_highlight_text')) {
if (!$words) {
return esc_html($text);
}
$pattern = '/' . implode('|', array_map(static fn(string $word): string => preg_quote($word, '/'), $words)) . '/iu';
return (string) preg_replace($pattern, '<span class="focus-color">$0</span>', esc_html($text));
$pattern = '/(' . implode('|', array_map(static fn(string $word): string => preg_quote($word, '/'), $words)) . ')/iu';
$parts = preg_split($pattern, $text, -1, PREG_SPLIT_DELIM_CAPTURE);
if (!is_array($parts)) {
return esc_html($text);
}
$html = '';
foreach ($parts as $index => $part) {
$escaped = esc_html($part);
$html .= ($index % 2) === 1 ? '<b class="focus-color">' . $escaped . '</b>' : $escaped;
}
return $html;
}
}
+62 -45
View File
@@ -180,15 +180,6 @@ if (!function_exists('aksrt_get_search_box')) :
}
$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')
@@ -201,33 +192,36 @@ if (!function_exists('aksrt_get_search_box')) :
'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">'
$category_terms = [];
if (!empty($args['show_input_cat'])) {
$category_ids = is_array($args['more_cats'])
? $args['more_cats']
: (preg_split('/[,,\s]+/', (string) $args['more_cats']) ?: []);
if ($category_ids && function_exists('aksrt_get_search_categories')) {
$category_terms = aksrt_get_search_categories($category_ids);
}
if ((int) $args['in_cat'] > 0) {
$selected_term = get_term((int) $args['in_cat']);
if ($selected_term && !is_wp_error($selected_term)) {
$selected_term_name = (string) $selected_term->name;
if (!$category_terms) {
$category_terms = [$selected_term];
}
}
}
}
if ($category_terms) {
$in_cat_id = (int) $args['in_cat'];
$in_cat_name = $in_cat_id > 0 ? (string) ($selected_term_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)) {
foreach ($category_terms as $cat) {
if (!$cat instanceof WP_Term) {
continue;
}
$cid = (int) ($cat['id'] ?? 0);
$cname = (string) ($cat['name'] ?? '');
$cid = (int) $cat->term_id;
$cname = (string) $cat->name;
if ($cid <= 0 || $cname === '') {
continue;
}
@@ -249,37 +243,57 @@ if (!function_exists('aksrt_get_search_box')) :
. $input_cat . '</div></div>';
}
$s = esc_attr(wp_strip_all_tags((string) $args['s']));
if ($s === '' && is_search()) {
$s = esc_attr(get_search_query());
$type_html = '';
$type_dropdown_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_name = (string) ($types[$in_type] ?? reset($types));
if ($cat_html !== '') {
$type_items = '';
foreach ($types as $key => $label) {
$cls = $in_type === (string) $key ? ' active' : '';
$type_items .= '<a class="but' . esc_attr($cls) . '" data-for="type" data-value="'
. esc_attr((string) $key) . '" href="javascript:;">' . esc_html((string) $label) . '</a>';
}
$type_html = '<div class="flex jc mb10 search-type-but-average"><div class="but-average radius">'
. $type_items . '</div></div>';
} else {
$type_items = '';
foreach ($types as $key => $label) {
$type_items .= '<li><a href="javascript:;" class="text-ellipsis" data-for="type" data-value="'
. esc_attr((string) $key) . '">' . esc_html((string) $label) . '</a></li>';
}
$type_dropdown_html = '<div class="option-dropdown splitters-this-r search-drop"><div class="dropdown">'
. '<a href="javascript:;" class="padding-h10" data-toggle="dropdown"><span name="type">'
. esc_html($type_name) . '</span><i class="fa ml6 fa-sort opacity5" aria-hidden="true"></i></a>'
. '<ul class="dropdown-menu">' . $type_items . '</ul></div></div>';
}
}
$s = esc_attr(wp_strip_all_tags((string) $args['s']));
$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="fa fas fa-search" aria-hidden="true"></i></button></div>';
. esc_attr__('搜索', 'aksrt') . '"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-search"></use></svg></button></div>';
$input_html .= '</div>';
$input_html .= '<input type="hidden" name="type" value="' . esc_attr($in_type) . '">';
if ($cat_html !== '' || (string) $args['in_cat'] !== '') {
$input_html .= '<input type="hidden" name="trem" value="'
. esc_attr((string) ($args['in_cat'] !== '' ? $args['in_cat'] : ($state['category_id'] ?? 0))) . '">';
. esc_attr((string) $args['in_cat']) . '">';
}
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('/')) . '">'
. $type_html
. '<div class="line-form">' . $cat_html . $input_html . '</div>'
. '<div class="line-form">' . ($cat_html !== '' ? $cat_html : $type_dropdown_html) . $input_html . '</div>'
. '</form>';
}
@@ -318,7 +332,8 @@ if (!function_exists('aksrt_get_search_box')) :
if ($keyword_link !== '') {
$history_html = '<div class="search-keywords history-search">';
$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:;" aria-label="'
$history_html .= '<a class="pull-right trash-history-search muted-3-color" href="javascript:;" data-cookie-path="'
. esc_attr(COOKIEPATH ?: '/') . '" data-cookie-domain="' . esc_attr(COOKIE_DOMAIN) . '" aria-label="'
. esc_attr__('清空历史', 'aksrt') . '"><i class="fa fas fa-trash-alt em12" aria-hidden="true"></i></a></p>';
$history_html .= '<div>' . $keyword_link . '</div></div>';
}
@@ -345,7 +360,9 @@ if (!function_exists('aksrt_get_search_box')) :
}
}
$class = $args['class'] ? ' ' . sanitize_html_class((string) $args['class']) : '';
$class_tokens = preg_split('/\s+/', trim((string) $args['class'])) ?: [];
$class_tokens = array_values(array_filter(array_map('sanitize_html_class', $class_tokens)));
$class = $class_tokens ? ' ' . implode(' ', $class_tokens) : '';
$html = '<div class="search-input' . esc_attr($class) . '">'
. $form_html . $keywords_html . $history_html . $posts_html
. '</div>';
-67
View File
@@ -7,73 +7,6 @@
defined('ABSPATH') || exit;
// ============================================================
// 模板标签:图标覆盖卡片(顶部多功能组件叠加层)
// 完全模仿 legacy 的 legacy
// ============================================================
if (!function_exists('aksrt_render_icon_cover_card')):
/**
* 渲染单个图标覆盖卡片(模仿 legacy 的 legacy)
*
* 结构:左侧圆形/方形图标 + 右侧标题和描述
*
* @param array $card 卡片配置
* - icon: string Font Awesome 类名 (如 'fa fas fa-magic')
* - custom_icon: string 自定义 SVG/HTML 图标(优先于 icon)
* - icon_class: string 图标颜色类 (c-yellow, c-blue, c-green, c-red, c-orange, c-cyan, c-pink, jb-cyan, jb-green, jb-orange)
* - icon_shape: string 图标形状 'circle' | 'square'
* - title: string 主标题
* - desc: string 描述文字
* - url: string 跳转链接
* - target: string 链接打开方式 '_blank' | '_self'
* @return string HTML
*/
function aksrt_render_icon_cover_card(array $card): string {
// Prefer canonical legacy-aligned renderer.
if (function_exists('aksrt_icon_cover_card')) {
return aksrt_icon_cover_card($card);
}
$icon = $card['icon'] ?? 'fa fas fa-star';
$custom_icon = $card['custom_icon'] ?? ($card['customize_icon'] ?? '');
$icon_class = trim((string) ($card['icon_class'] ?? 'c-blue'));
if (($card['icon_shape'] ?? '') === 'square' && !str_contains($icon_class, 'radius4')) {
$icon_class .= ' radius4';
}
$title = $card['title'] ?? '';
$desc = $card['desc'] ?? '';
$url = $card['url'] ?? ($card['link']['url'] ?? '');
$target = $card['target'] ?? ($card['link']['target'] ?? '');
$tgt = ($target !== '' && $target !== '_self') ? ' target="' . esc_attr((string) $target) . '"' : '';
$icon_html = $custom_icon !== ''
? wp_kses_post((string) $custom_icon)
: '<i class="' . esc_attr((string) $icon) . ' em09" aria-hidden="true"></i>';
$icon_container = '<div class="icon-cover-icon badg cir ' . esc_attr($icon_class) . '" style="font-size: 25px;">' . $icon_html . '</div>';
$text_html = '<div class="icon-cover-desc ml10 flex1 px12-sm">';
if ($title !== '') {
$text_html .= '<div class="em12 text-ellipsis font-bold"> ' . aksrt_icon_card_kses((string) $title) . '</div>';
}
if ($desc !== '') {
$text_html .= '<div class="muted-color mt6 text-ellipsis"> ' . aksrt_icon_card_kses((string) $desc) . '</div>';
}
$text_html .= '</div>';
$card_inner = $icon_container . $text_html;
$cls = 'icon-cover-card flex ac ' . esc_attr((string) ($card['class'] ?? 'aksrt-panel'));
if ($url !== '') {
return '<a class="main-color" ' . ($tgt !== '' ? ltrim($tgt) . ' ' : '') . 'href="' . esc_url((string) $url) . '"><div class="' . $cls . '">' . $card_inner . '</div></a>';
}
return '<div class="' . $cls . '">' . $card_inner . '</div>';
}
endif;
// ============================================================
// 模板标签:友情链接
// ============================================================
+9 -3
View File
@@ -227,8 +227,14 @@ if (!function_exists('aksrt_get_search_categories')):
*
* @return WP_Term[]
*/
function aksrt_get_search_categories(): array {
$include = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::search_more_cat_obj() : [];
function aksrt_get_search_categories(?array $include = null): array {
if ($include === null) {
$include = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::search_more_cat_obj() : [];
}
$include = array_values(array_filter(array_map('absint', (array) $include)));
if (!$include) {
return [];
}
$args = [
'taxonomy' => 'category',
'hide_empty' => true,
@@ -335,7 +341,7 @@ if (!function_exists('aksrt_get_search_filter_url')):
/** Build a search filter URL while preserving the reference request contract. */
function aksrt_get_search_filter_url(array $changes): string {
$params = [
's' => get_search_query(),
's' => get_search_query(false),
'type' => function_exists('aksrt_get_search_form_type') ? aksrt_get_search_form_type() : 'post',
'trem' => isset($_REQUEST['trem']) ? absint(wp_unslash($_REQUEST['trem'])) : 0,
'user' => isset($_REQUEST['user']) ? absint(wp_unslash($_REQUEST['user'])) : 0,
+49 -23
View File
@@ -9,7 +9,7 @@ defined('ABSPATH') || exit;
global $wp_query;
$search_query = trim(wp_strip_all_tags(get_search_query()));
$search_query = trim(wp_strip_all_tags(get_search_query(false)));
$search_type = function_exists('aksrt_get_search_form_type') ? aksrt_get_search_form_type() : 'post';
$search_types = function_exists('aksrt_get_search_type_options') ? aksrt_get_search_type_options() : ['post' => __('文章', 'aksrt')];
$search_category = isset($_REQUEST['trem']) ? absint(wp_unslash($_REQUEST['trem'])) : 0;
@@ -44,9 +44,10 @@ if ($search_query !== '' && $search_total > 0 && $paged <= 1 && function_exists(
get_header();
if (is_active_sidebar('search_top_fluid')) {
if (is_active_sidebar('all_top_fluid') || is_active_sidebar('search_top_fluid')) {
echo '<div class="fluid-widget-wrap">';
dynamic_sidebar('search_top_fluid');
if (is_active_sidebar('all_top_fluid')) dynamic_sidebar('all_top_fluid');
if (is_active_sidebar('search_top_fluid')) dynamic_sidebar('search_top_fluid');
echo '</div>';
}
?>
@@ -73,62 +74,87 @@ if (is_active_sidebar('search_top_fluid')) {
if ($search_type === $key) {
$tab_nav .= '<li class="active"><a class="focus-color" href="javascript:;">' . esc_html($label) . '</a></li>';
} else {
$tab_nav .= '<li><a ajax-replace="true" route="1" class="ajax-next" href="' . esc_url(add_query_arg('type', $key, $base_url)) . '">' . esc_html($label) . '</a></li>';
$route_title = $search_query . ' ' . __('搜索', 'aksrt') . $label . ' - ' . get_bloginfo('name');
$tab_nav .= '<li><a ajax-replace="true" route="1" route-title="' . esc_attr($route_title) . '" class="ajax-next" href="' . esc_url(add_query_arg('type', $key, $base_url)) . '">' . esc_html($label) . '</a></li>';
}
}
$tab_nav = '<div class="list-inline scroll-x mini-scrollbar tab-nav-theme">' . $tab_nav . '</div>';
$description = sprintf(
$search_scope_parts = [];
if ($search_user > 0) {
$filtered_user = get_userdata($search_user);
if ($filtered_user) {
$user_home = function_exists('aksrt_get_user_home_url') ? aksrt_get_user_home_url($search_user) : get_author_posts_url($search_user);
$search_scope_parts[] = __('用户', 'aksrt') . ' <a class="focus-color" href="' . esc_url($user_home) . '"><b>' . esc_html($filtered_user->display_name) . '</b></a>';
}
}
if ($search_category > 0) {
$filtered_term = get_term($search_category);
if ($filtered_term && !is_wp_error($filtered_term)) {
$term_url = get_term_link($filtered_term);
if (!is_wp_error($term_url)) {
$taxonomy = get_taxonomy($filtered_term->taxonomy);
$taxonomy_label = $taxonomy && !empty($taxonomy->labels->singular_name) ? $taxonomy->labels->singular_name : __('分类', 'aksrt');
$search_scope_parts[] = esc_html($taxonomy_label) . ' <a class="focus-color" href="' . esc_url($term_url) . '"><b>' . esc_html($filtered_term->name) . '</b></a>';
}
}
}
$description = ($search_scope_parts ? sprintf(__('在%s中,', 'aksrt'), implode(__('、', 'aksrt'), $search_scope_parts)) : '')
. sprintf(
__('搜索 %1$s ,共找到 %2$s 个%3$s', 'aksrt'),
'<b class="search-key focus-color">' . esc_html($search_query) . '</b>',
'<b class="focus-color">' . esc_html(number_format_i18n($search_total)) . '</b>',
esc_html($search_types[$search_type] ?? __('内容', 'aksrt'))
);
?>
<?php if ($search_query === '') : ?>
<div class="aksrt-panel search-content"><?php echo function_exists('aksrt_get_ajax_null') ? aksrt_get_ajax_null(__('请输入搜索关键词', 'aksrt'), 60, 'null-search.svg', 300) : '<div class="ajax-item text-center muted-2-color padding-20">' . esc_html__('请输入搜索关键词', 'aksrt') . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></div>
<?php else : ?>
<div class="ajaxpager search-page-ajaxpager">
<div class="ajax-item-header type-<?php echo esc_attr($search_type); ?>">
<div class="search-desc-text mb10 mt10 muted-2-color"><?php echo wp_kses_post($description); ?></div>
<div class="search-tab-header aksrt-panel relative padding-h10"><div><?php echo $tab_nav; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></div><div class="search-tab-filter"><?php echo function_exists('aksrt_get_search_tab_nav_filter') ? aksrt_get_search_tab_nav_filter($search_type) : ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></div></div>
</div>
<?php if ($search_query === '') : ?>
<div class="aksrt-panel search-content"><div class="text-center muted-2-color padding-20"><?php esc_html_e('请输入搜索关键词', 'aksrt'); ?></div></div>
<?php elseif ($user_query instanceof WP_User_Query && $user_query->get_results()) : ?>
<div class="aksrt-panel">
<?php if ($user_query instanceof WP_User_Query && $user_query->get_results()) : ?>
<?php foreach ($user_query->get_results() as $result_user) :
$user_id = (int) $result_user->ID;
$user_url = function_exists('aksrt_get_user_home_url') ? aksrt_get_user_home_url($user_id) : get_author_posts_url($user_id);
?>
<a class="author-minicard radius8 flex ac ajax-item" href="<?php echo esc_url($user_url); ?>">
<span class="avatar-img mr10"><?php echo function_exists('aksrt_get_avatar_html') ? aksrt_get_avatar_html($user_id, 48) : get_avatar($user_id, 48); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></span>
<span class="flex1"><b><?php echo esc_html($result_user->display_name); ?></b><span class="muted-2-color em09 block text-ellipsis"><?php echo esc_html(wp_trim_words((string) $result_user->description, 16)); ?></span></span>
</a>
<?php echo function_exists('aksrt_author_minicard') ? aksrt_author_minicard($user_id, 'ajax-item', false, $search_query) : ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<?php endforeach; ?>
</div>
<?php
$user_pages = (int) ceil($search_total / 12);
if ($user_pages > 1) {
echo '<div class="text-center theme-pagination ajax-pag">' . paginate_links(['base' => esc_url_raw(add_query_arg('user_paged', '%#%')), 'current' => $user_page, 'total' => $user_pages, 'prev_text' => '<i class="fa fas fa-angle-left"></i>', 'next_text' => '<i class="fa fas fa-angle-right"></i>']) . '</div>';
if (function_exists('aksrt_get_ajax_next_paginate')) {
$user_next_url = add_query_arg([
's' => $search_query,
'type' => 'user',
'orderby' => $orderby,
'user_paged' => $user_page + 1,
], home_url('/'));
echo aksrt_get_ajax_next_paginate($search_total, $user_page, 12, $user_next_url, 'text-center theme-pagination ajax-pag', 'next-page ajax-next'); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
?>
<?php elseif ($search_type === 'post' && $wp_query->have_posts()) : ?>
<?php
$config = function_exists('aksrt_archive_get_render_config') ? aksrt_archive_get_render_config(['context' => 'search', 'highlight_query' => $search_query]) : ['context' => 'search', 'mode' => 'list'];
aksrt_render_post_list(array_merge($config, ['wrapper_class' => 'mtn6']), $wp_query);
$config = function_exists('aksrt_archive_get_render_config') ? aksrt_archive_get_render_config(['context' => 'search', 'highlight_query' => $search_query, 'no_margin' => false]) : ['context' => 'search', 'mode' => 'list'];
aksrt_render_post_list(array_merge($config, ['skip_wrapper' => true]), $wp_query);
?>
<?php aksrt_render_pagination($wp_query, ['query_context' => 'search', 'render_config' => $config]); ?>
<?php else : ?>
<div class="aksrt-panel search-content"><div class="text-center muted-2-color padding-20"><?php esc_html_e('未找到相关内容', 'aksrt'); ?></div></div>
<?php echo function_exists('aksrt_get_ajax_null')
? aksrt_get_ajax_null($search_type === 'user' ? __('未找到相关用户', 'aksrt') : __('暂无内容', 'aksrt'), $search_type === 'user' ? 75 : 100, $search_type === 'user' ? 'null-user.svg' : 'null-post.svg')
: '<div class="ajax-item text-center muted-2-color padding-20">' . esc_html($search_type === 'user' ? __('未找到相关用户', 'aksrt') : __('暂无内容', 'aksrt')) . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<?php endif; ?>
<div class="post_ajax_loader search-loader"><?php echo function_exists('aksrt_render_placeholder') ? aksrt_render_placeholder('list', 6) : ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- 固定骨架结构。 ?></div>
</div>
<?php endif; ?>
<?php if (is_active_sidebar('search_bottom_content')) dynamic_sidebar('search_bottom_content'); ?>
</div>
</div>
<?php get_sidebar(); ?>
</main>
<?php
if (is_active_sidebar('search_bottom_fluid')) {
if (is_active_sidebar('search_bottom_fluid') || is_active_sidebar('all_bottom_fluid')) {
echo '<div class="fluid-widget-wrap">';
dynamic_sidebar('search_bottom_fluid');
if (is_active_sidebar('search_bottom_fluid')) dynamic_sidebar('search_bottom_fluid');
if (is_active_sidebar('all_bottom_fluid')) dynamic_sidebar('all_bottom_fluid');
echo '</div>';
}
get_footer();
+7 -5
View File
@@ -282,7 +282,11 @@ final class PageConfigMetaBox {
],
];
}
return ['icon_radius4' => !empty($value['icon_radius4']), 'cards' => $cards];
return [
'show_widget_bg' => !empty($value['show_widget_bg']),
'icon_radius4' => !empty($value['icon_radius4']),
'cards' => $cards,
];
}
/** @return array<string,mixed> */
@@ -298,9 +302,7 @@ final class PageConfigMetaBox {
$slides[] = [
'background' => $base . $image,
'link' => ['url' => home_url('/'), 'target' => '_blank'],
'text' => ['desc' => '', 'title' => ''],
'text_align' => 'left-bottom', 'text_parallax' => 30,
'text_size_m' => 20, 'text_size_pc' => 30,
'text' => ['desc' => '', 'title' => '', 'text_align' => 'left-bottom', 'parallax' => 40, 'text_size_m' => 20, 'text_size_pc' => 30],
];
}
return $slides;
@@ -313,7 +315,7 @@ final class PageConfigMetaBox {
/** @return array<string,mixed> */
private static function card_defaults(): array {
return ['icon_radius4' => false, 'cards' => [
return ['show_widget_bg' => false, 'icon_radius4' => false, 'cards' => [
['icon' => 'fa fas fa-gem', 'customize_icon' => '', 'icon_class' => 'c-yellow', 'link' => [], 'title' => '图标卡片', 'desc' => '这是一个图标卡片示例'],
['icon' => 'fa fas fa-star', 'customize_icon' => '', 'icon_class' => 'c-blue-2', 'link' => [], 'title' => '原创作品', 'desc' => '这是一个图标卡片示例'],
['icon' => 'fa fas fa-fire', 'customize_icon' => '', 'icon_class' => 'jb-pink', 'link' => [], 'title' => '灵感来源<badge class="ml6 jb-yellow">NEW</badge>', 'desc' => '这是一个图标卡片示例'],
+3 -3
View File
@@ -181,16 +181,16 @@ class SchemaPageDisplay {
}
private static function card_fields(): array {
return [self::field('icon_radius4', '方形图标', 'switcher', false), self::field('cards', '添加卡片', 'group', [], ['button_title' => '添加内容', 'fields' => [self::field('title', '文案标题', 'textarea', '', ['sanitize_type' => 'rich_html']), self::field('desc', '文案简介', 'textarea', '', ['sanitize_type' => 'rich_html']), self::field('icon', '选择图标', 'icon', 'fa fas fa-magic'), self::field('customize_icon', '自定义图标', 'textarea', '', ['sanitize_type' => 'html']), self::field('icon_class', '图标颜色', 'palette', 'c-yellow', ['options' => self::aksrt_palette(true)]), self::field('link', '跳转链接', 'link', [])]])];
return [self::field('show_widget_bg', '模块背景', 'switcher', false, ['description' => '开启后整个模块显示统一背景;关闭后每张卡片单独显示背景。']), self::field('icon_radius4', '方形图标', 'switcher', false), self::field('cards', '添加卡片', 'group', [], ['button_title' => '添加内容', 'fields' => [self::field('title', '文案标题', 'textarea', '', ['sanitize_type' => 'rich_html']), self::field('desc', '文案简介', 'textarea', '', ['sanitize_type' => 'rich_html']), self::field('icon', '选择图标', 'icon', 'fa fas fa-magic'), self::field('customize_icon', '自定义图标', 'textarea', '', ['sanitize_type' => 'html']), self::field('icon_class', '图标颜色', 'palette', 'c-yellow', ['options' => self::aksrt_palette(true)]), self::field('link', '跳转链接', 'link', [])]])];
}
private static function orderby_fields(): array { return [self::field('lists', '显示排序方式', 'select', ['modified', 'views', 'like', 'comment_count'], ['multiple' => true, 'sortable' => true, 'options' => self::post_order_options(false)]), self::field('dropdown', '更多排序方式', 'switcher', false)]; }
private static function ajax_fields(string $source): array { return [self::field('lists', '按钮列表', 'async_select', [], ['source' => $source, 'multiple' => true, 'sortable' => true]), self::field('dropdown', '下拉列表', 'switcher', false), self::field('dropdown_lists', '下拉菜单列表', 'async_select', [], ['dependsOn' => self::enabled('dropdown'), 'source' => $source, 'multiple' => true, 'sortable' => true])]; }
private static function footer_image_fields(): array { return [self::field('text', '显示文字', 'text', ''), self::field('image', '显示图片', 'upload', ''), self::field('link', '点击跳转', 'link', [])]; }
private static function header_slider_defaults(): array { $img = self::asset('assets/img/'); return [['background' => $img . 'slider-bg.jpg', 'link' => ['url' => home_url('/'), 'target' => '_blank'], 'text' => ['title' => '', 'desc' => ''], 'text_align' => 'left-bottom', 'text_parallax' => 30, 'text_size_m' => 20, 'text_size_pc' => 30], ['background' => $img . 'user_t.jpg', 'link' => ['url' => home_url('/'), 'target' => '_blank'], 'text' => ['title' => '', 'desc' => ''], 'text_align' => 'left-bottom', 'text_parallax' => 30, 'text_size_m' => 20, 'text_size_pc' => 30]]; }
private static function header_slider_defaults(): array { $img = self::asset('assets/img/'); return [['background' => $img . 'slider-bg.jpg', 'link' => ['url' => home_url('/'), 'target' => '_blank'], 'text' => ['title' => '', 'desc' => '', 'text_align' => 'left-bottom', 'parallax' => 40, 'text_size_m' => 20, 'text_size_pc' => 30]], ['background' => $img . 'user_t.jpg', 'link' => ['url' => home_url('/'), 'target' => '_blank'], 'text' => ['title' => '', 'desc' => '', 'text_align' => 'left-bottom', 'parallax' => 40, 'text_size_m' => 20, 'text_size_pc' => 30]]]; }
private static function slider_options_defaults(): array { return ['direction' => 'horizontal', 'loop' => true, 'button' => true, 'pagination' => true, 'effect' => 'slide', 'scale_height' => false, 'auto_height' => false, 'pc_height' => 550, 'm_height' => 280, 'spacebetween' => 0, 'speed' => 0, 'autoplay' => true, 'interval' => 6]; }
private static function search_defaults(): array { return ['show_keywords' => true, 'popular_limit' => 6, 'show_input_cat' => false, 'in_cat' => '', 'more_cats' => '', 'show_type' => false, 'in_type' => 'post', 'before_html' => '<div class="em16 font-bold mb10">更优雅的Wordpress主题</div>' . "\n" . '<div>这是导航栏幻灯片多功能组件,可在后台进行配置</div>', 'after_html' => '']; }
private static function card_defaults(): array { return ['icon_radius4' => false, 'cards' => [['icon' => 'fa fas fa-gem', 'customize_icon' => '', 'icon_class' => 'c-yellow', 'link' => [], 'title' => '图标卡片', 'desc' => '这是一个图标卡片示例'], ['icon' => 'fa fas fa-star', 'customize_icon' => '', 'icon_class' => 'c-blue-2', 'link' => [], 'title' => '原创作品', 'desc' => '这是一个图标卡片示例'], ['icon' => 'fa fas fa-fire', 'customize_icon' => '', 'icon_class' => 'jb-pink', 'link' => [], 'title' => '灵感来源<badge class="ml6 jb-yellow">NEW</badge>', 'desc' => '这是一个图标卡片示例'], ['icon' => 'fa fas fa-wrench', 'customize_icon' => '', 'icon_class' => 'jb-cyan', 'link' => [], 'title' => '系统工具 <badge class="ml6 jb-blue">GO <span class="fa fas fa-angle-right em12"></span></badge>', 'desc' => '这是一个图标卡片示例']]]; }
private static function card_defaults(): array { return ['show_widget_bg' => false, 'icon_radius4' => false, 'cards' => [['icon' => 'fa fas fa-gem', 'customize_icon' => '', 'icon_class' => 'c-yellow', 'link' => [], 'title' => '图标卡片', 'desc' => '这是一个图标卡片示例'], ['icon' => 'fa fas fa-star', 'customize_icon' => '', 'icon_class' => 'c-blue-2', 'link' => [], 'title' => '原创作品', 'desc' => '这是一个图标卡片示例'], ['icon' => 'fa fas fa-fire', 'customize_icon' => '', 'icon_class' => 'jb-pink', 'link' => [], 'title' => '灵感来源<badge class="ml6 jb-yellow">NEW</badge>', 'desc' => '这是一个图标卡片示例'], ['icon' => 'fa fas fa-wrench', 'customize_icon' => '', 'icon_class' => 'jb-cyan', 'link' => [], 'title' => '系统工具 <badge class="ml6 jb-blue">GO <span class="fa fas fa-angle-right em12"></span></badge>', 'desc' => '这是一个图标卡片示例']]]; }
private static function field(string $key, string $label, string $type, $default = null, array $extra = []): array { return array_merge(['key' => $key, 'label' => $label, 'type' => $type, 'default' => $default], $extra); }
private static function notice(string $content): array { return ['key' => '_notice_' . md5($content), 'type' => 'notice', 'content' => $content, 'tone' => 'warning']; }
-10
View File
@@ -501,16 +501,6 @@ trait ScriptsPart1b {
}
}
// 搜索结果页:路由专属 CSS(顶部卡片/胶囊搜索框/工具栏/空状态/关键词高亮)
if (is_search()) {
wp_enqueue_style(
'aksrt-route-search',
$base_uri . '/assets/css/routes/search.css',
['aksrt-public', 'aksrt-post-card'],
$version
);
}
// 分类汇总页:路由专属 CSS
if (is_page_template('templates/pages/page-categories.php')) {
wp_enqueue_style(
+2 -5
View File
@@ -95,11 +95,7 @@ trait DisplayPageGroups {
$slides[] = [
'background' => $base . $image,
'link' => ['url' => 'https://www.legacy.com/', 'target' => '_blank'],
'text' => ['desc' => '', 'title' => ''],
'text_align' => 'left-bottom',
'text_parallax' => 30,
'text_size_m' => 20,
'text_size_pc' => 30,
'text' => ['desc' => '', 'title' => '', 'text_align' => 'left-bottom', 'parallax' => 40, 'text_size_m' => 20, 'text_size_pc' => 30],
];
}
return $slides;
@@ -128,6 +124,7 @@ trait DisplayPageGroups {
/** @return array<string,mixed> */
private static function header_slider_card_defaults(): array {
return [
'show_widget_bg' => false,
'icon_radius4' => false,
'cards' => [
['icon' => 'fa fas fa-gem', 'customize_icon' => '', 'icon_class' => 'c-yellow', 'link' => [], 'title' => '图标卡片', 'desc' => '这是一个图标卡片示例'],
@@ -0,0 +1,126 @@
<?php
/** Render-level harness for the header multifunction component. */
namespace AKSRT\Core {
final class Color {
public static function sanitize(string $value): string { return $value; }
}
}
namespace AKSRT\Settings {
final class Settings {
public static array $headerSlider = [];
public static function get_header_slider_settings(): array { return self::$headerSlider; }
}
}
namespace {
define('ABSPATH', __DIR__);
$GLOBALS['aksrt_mobile'] = false;
$GLOBALS['aksrt_lazy'] = true;
final class WP_Query {
public function get(string $key) { return 0; }
}
$GLOBALS['wp_query'] = new WP_Query();
function is_admin(): bool { return false; }
function wp_is_mobile(): bool { return !empty($GLOBALS['aksrt_mobile']); }
function is_author(): bool { return false; }
function is_front_page(): bool { return true; }
function is_category(): bool { return false; }
function is_tag(): bool { return false; }
function is_singular($type = ''): bool { return false; }
function is_search(): bool { return false; }
function is_page(): bool { return false; }
function is_home(): bool { return false; }
function get_query_var(string $key) { return ''; }
function sanitize_key($value): string { return preg_replace('/[^a-z0-9_-]/', '', strtolower((string) $value)); }
function sanitize_html_class($value): string { return preg_replace('/[^a-zA-Z0-9_-]/', '', (string) $value); }
function wp_parse_args($args, array $defaults = []): array { return array_merge($defaults, is_array($args) ? $args : []); }
function esc_url($value): string { return htmlspecialchars((string) $value, ENT_QUOTES); }
function esc_url_raw($value): string { return (string) $value; }
function esc_attr($value): string { return htmlspecialchars((string) $value, ENT_QUOTES); }
function esc_html($value): string { return htmlspecialchars((string) $value, ENT_QUOTES); }
function wp_strip_all_tags($value): string { return strip_tags((string) $value); }
function __($value, $domain = ''): string { return (string) $value; }
function get_bloginfo($show = ''): string { return 'AKSRT'; }
function home_url($path = ''): string { return 'https://example.test/' . ltrim((string) $path, '/'); }
function wp_kses($value, $allowed = []): string { return (string) $value; }
function aksrt_is_lazy(string $key): bool { return !empty($GLOBALS['aksrt_lazy']); }
function aksrt_get_lazy_thumb(string $size = ''): string { return 'https://example.test/placeholder.svg'; }
function aksrt_get_lazy_attr(string $key, string $src, string $class = '', string $lazy_src = ''): string {
if (aksrt_is_lazy($key)) {
return ' class="lazyload ' . esc_attr($class) . '" src="' . esc_url($lazy_src) . '" data-src="' . esc_url($src) . '"';
}
return ' class="' . esc_attr($class) . '" src="' . esc_url($src) . '"';
}
function aksrt_get_search_box(array $args = []): string { return '<div class="search-input">search-box</div>'; }
function aksrt_icon_cover_card(array $card): string {
return '<div class="icon-cover-card flex ac ' . esc_attr((string) ($card['class'] ?? '')) . '">' . esc_html((string) ($card['title'] ?? '')) . '</div>';
}
require_once dirname(__DIR__, 2) . '/inc/helpers/homepage/header-components.php';
$slides = [
['background' => 'https://example.test/slide.jpg', 'link' => ['url' => 'https://example.test/one', 'target' => '_blank', 'text' => 'One'], 'text' => ['title' => 'Title', 'desc' => 'Description'], 'image_layer' => [['image' => 'https://example.test/layer.png', 'free_size' => true, 'align' => 'right', 'parallax' => 40, 'parallax_opacity' => 80, 'parallax_scale' => 110]]],
['background_video' => 'https://example.test/background.mp4', 'background' => 'https://example.test/poster.jpg'],
['video' => 'https://example.test/content.mp4', 'background' => 'https://example.test/content-poster.jpg'],
['background' => 'https://example.test/pc-only.jpg', 'hide' => 'm'],
['background' => 'https://example.test/mobile-only.jpg', 'hide' => 'pc'],
];
$settings = [
'slides' => $slides,
'show_on_pages' => ['home'],
'show_type' => '',
'nav_color' => '#ffffff',
'slider_config' => ['loop' => true, 'autoplay' => true, 'interval' => 6, 'pagination' => true],
'search_show' => ['pc_s', 'm_s'],
'search_config' => ['before_html' => '<div>Search intro</div>'],
'card_show' => ['pc_s', 'm_s'],
'card_config' => ['show_widget_bg' => false, 'cards' => [['icon' => 'fa fas fa-star', 'title' => 'Card one']]],
'filter_blur' => ['pc_s', 'm_s'],
];
\AKSRT\Settings\Settings::$headerSlider = $settings;
ob_start();
aksrt_header_slide();
$desktop = (string) ob_get_clean();
$GLOBALS['aksrt_mobile'] = true;
ob_start();
aksrt_header_slide();
$mobile = (string) ob_get_clean();
$settings['card_config']['show_widget_bg'] = true;
\AKSRT\Settings\Settings::$headerSlider = $settings;
ob_start();
aksrt_header_slide();
$module_background = (string) ob_get_clean();
$GLOBALS['aksrt_mobile'] = false;
$GLOBALS['aksrt_lazy'] = false;
$lazy_disabled = aksrt_get_header_slider_markup([
'slides' => [['background' => 'https://example.test/eager.jpg']],
'class' => 'slide-index slide-header',
]);
$single_slide = aksrt_get_header_slider_markup([
'slides' => [['background' => 'https://example.test/single.jpg']],
'class' => 'slide-index slide-header',
'pagination' => true,
'button' => true,
]);
require_once dirname(__DIR__, 2) . '/src/Admin/PageConfigMetaBox.php';
$sanitize_cards = new \ReflectionMethod('AKSRT\\Admin\\PageConfigMetaBox', 'sanitize_card_options');
$page_config_save = $sanitize_cards->invoke(null, ['show_widget_bg' => true, 'cards' => []]);
echo json_encode([
'desktop' => $desktop,
'mobile' => $mobile,
'module_background' => $module_background,
'lazy_disabled' => $lazy_disabled,
'single_slide' => $single_slide,
'page_config_save' => $page_config_save,
], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}
@@ -0,0 +1,62 @@
'use strict';
const assert = require('node:assert/strict');
const { spawnSync } = require('node:child_process');
const fs = require('node:fs');
const path = require('node:path');
const test = require('node:test');
const root = path.resolve(__dirname, '..', '..');
test('header multifunction renders reference slide, search, and card contracts on desktop and mobile', () => {
const rendered = spawnSync(
process.env.PHP_BINARY || 'php',
[path.join(__dirname, 'header-multifunction-render-harness.php')],
{ cwd: root, encoding: 'utf8' },
);
assert.equal(rendered.status, 0, rendered.stderr || rendered.stdout);
const { desktop, mobile, module_background: moduleBackground } = JSON.parse(rendered.stdout);
assert.match(desktop, /data-src="https:\/\/example\.test\/slide\.jpg"/);
assert.match(desktop, /data-swiper-parallax="40%" data-swiper-parallax-opacity="0\.8" data-swiper-parallax-scale="1\.1"/);
assert.match(desktop, /data-src="https:\/\/example\.test\/pc-only\.jpg"/);
assert.doesNotMatch(desktop, /mobile-only\.jpg/);
assert.match(desktop, /class="swiper-slide slide-background-video"/);
assert.match(desktop, /data-src="https:\/\/example\.test\/background\.mp4"/);
assert.match(desktop, /class="new-dplayer" video-url="https:\/\/example\.test\/content\.mp4" video-type="auto"/);
assert.match(desktop, /class="absolute dplayer-poster"/);
assert.doesNotMatch(desktop, /<video controls/);
assert.match(desktop, /header-slider-search-more text-center before/);
assert.match(desktop, /<div class="search-input">search-box<\/div>/);
assert.match(desktop, /<div class="icon-cover-card flex ac aksrt-panel">Card one<\/div>/);
assert.doesNotMatch(mobile, /background\.mp4/);
assert.match(mobile, /data-src="https:\/\/example\.test\/mobile-only\.jpg"/);
assert.doesNotMatch(mobile, /pc-only\.jpg/);
assert.match(mobile, /data-src="https:\/\/example\.test\/poster\.jpg"/);
assert.match(mobile, /class="new-dplayer" video-url="https:\/\/example\.test\/content\.mp4"/);
assert.match(mobile, /header-slider-search-more text-center before/);
assert.match(mobile, /<div class="icon-cover-card flex ac aksrt-panel">Card one<\/div>/);
assert.match(moduleBackground, /<div class="aksrt-panel padding-10"><div class="flex jse/);
assert.match(moduleBackground, /<div class="icon-cover-card flex ac padding-10">Card one<\/div>/);
assert.equal(JSON.parse(rendered.stdout).page_config_save.show_widget_bg, true);
const { lazy_disabled: eager, single_slide: single } = JSON.parse(rendered.stdout);
assert.match(eager, /<img class="radius8" src="https:\/\/example\.test\/eager\.jpg"/);
assert.doesNotMatch(eager, /data-src=|lazyload/);
assert.match(single, /swiper-container-initialized/);
assert.doesNotMatch(single, /swiper-pagination|swiper-button-prev/);
});
test('header card background setting is editable, saved, and defaults off', () => {
const schema = fs.readFileSync(path.join(root, 'src/Admin/Schema/SchemaPageDisplay.php'), 'utf8');
const settings = fs.readFileSync(path.join(root, 'src/Settings/DisplayPageGroups.php'), 'utf8');
const metaBox = fs.readFileSync(path.join(root, 'src/Admin/PageConfigMetaBox.php'), 'utf8');
assert.match(schema, /field\('show_widget_bg', '模块背景', 'switcher', false/);
assert.match(schema, /'show_widget_bg'\s*=>\s*false/);
assert.match(settings, /'show_widget_bg'\s*=>\s*false/);
assert.match(metaBox, /'show_widget_bg'\s*=>\s*!empty\(\$value\['show_widget_bg'\]\)/);
assert.match(metaBox, /'show_widget_bg'\s*=>\s*false/);
});
@@ -0,0 +1,45 @@
'use strict';
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const test = require('node:test');
const vm = require('node:vm');
const root = path.resolve(__dirname, '../..');
const runtime = fs.readFileSync(path.join(root, 'assets/js/runtime/main.js'), 'utf8');
test('video poster clicks play the same DPlayer instance and reveal its controls', () => {
const slide = {};
let played = 0;
let revealed = false;
let handler;
const start = runtime.indexOf("_win.bd.on('click', '.swiper-slide.slide-dplayer");
const end = runtime.indexOf('//视频列表图封面', start);
assert.ok(start > -1 && end > start);
vm.runInNewContext(runtime.slice(start, end), {
_win: { bd: { on(event, selector, callback) {
assert.equal(event, 'click');
assert.equal(selector, '.swiper-slide.slide-dplayer:not(.slide-dplayer-played) > *');
handler = callback;
} } },
jQuery(target) {
assert.equal(target, slide);
return {
find(selector) {
assert.equal(selector, '.new-dplayer');
return { data(key) {
assert.equal(key, 'dplayer');
return { play() { played++; } };
} };
},
parent() { return { addClass(name) {
assert.equal(name, 'slide-dplayer-played');
revealed = true;
} }; },
};
},
});
handler.call(slide);
assert.equal(played, 1);
assert.equal(revealed, true);
});
@@ -12,6 +12,7 @@ test('icon card renderers keep vertical and horizontal legacy DOM contracts sepa
const helper = read('inc/helpers/aksrt-icon-cards.php');
const widgets = read('src/WidgetSystem/Renderers/GeneralRenderer.php');
const header = read('inc/helpers/homepage/header-components.php');
const mediaBrand = read('inc/helpers/template-tags/media-brand.php');
assert.match(helper, /<div class="icon-card /);
assert.match(helper, /<div class="icon-cover-card flex ac /);
@@ -23,20 +24,26 @@ test('icon card renderers keep vertical and horizontal legacy DOM contracts sepa
// combo_info legitimately renders icon_image cards; icon cards must not leak media-card fields.
assert.doesNotMatch(widgets, /\$card\['description'\]/);
assert.match(header, /empty\(\$card\['custom_icon'\]\)/);
assert.doesNotMatch(mediaBrand, /function aksrt_render_icon_cover_card/);
});
test('homepage horizontal cards render fully from legacy CSS with no dedicated stylesheet', () => {
const baseCss = read('assets/css/frontend/base.css');
const legacyUtilities = read('assets/css/frontend/legacy-utilities.css');
const mainCss = read('assets/css/main.css');
const widgetCss = read('assets/widgets/frontend.css');
const scripts = read('src/Core/ScriptsPart1b.php');
assert.equal(fs.existsSync(path.join(root, 'assets/css/frontend/header-cards.css')), false);
assert.doesNotMatch(baseCss, /\.icon-cover-card\.aksrt-icon-cover-card/);
assert.doesNotMatch(baseCss, /\.header-components-card/);
assert.match(
baseCss,
/\.header-slider-card\s+\.icon-cover-card\s*\{[^}]*font-size:\s*12px/s,
);
assert.doesNotMatch(baseCss, /\.header-slider-card\s+\.icon-cover-card\s*\{[^}]*font-size:/s);
assert.doesNotMatch(legacyUtilities, /\.px12-sm\s*\{[^}]*font-size:\s*12px/);
const mobileTextSize = mainCss.lastIndexOf('.px12-sm,');
const mobileBreakpoint = mainCss.lastIndexOf('@media', mobileTextSize);
assert.ok(mobileBreakpoint > 0, 'the compact card text utility must remain inside a responsive media rule');
assert.match(mainCss.slice(mobileBreakpoint, mobileTextSize + 120), /max-width:\s*640px/);
assert.match(mainCss.slice(mobileTextSize, mobileTextSize + 120), /font-size:\s*12px/);
assert.doesNotMatch(scripts, /header-cards/);
assert.doesNotMatch(widgetCss, /aksrt-widget-icon-cards \.icon-cover-card/);
});
@@ -447,6 +447,7 @@ test('save contract rejects invalid input and round-trips canonical nested value
assert.equal(data.unknown_section, true)
assert.equal(data.invalid_enum_rejected, true)
assert.equal(data.nested_multiselect_valid, true)
assert.equal(data.header_card_bg, true)
assert.equal(data.footer_valid, true)
assert.equal(data.vip_switches_valid, true)
assert.deepEqual(data.vip_switches_clean, {
@@ -495,5 +496,6 @@ test('save contract rejects invalid input and round-trips canonical nested value
message_excludes_home: false,
home_excludes_public_home: false,
home_excludes_user_center: false,
paged_archive_hidden: false,
})
})
@@ -176,6 +176,7 @@ namespace {
'link' => ['url' => 'https://example.test/slide', 'target' => '_blank', 'text' => '<b>Go</b>', 'unknown' => 'drop-me'],
'text' => ['title' => '<strong>Safe</strong><script>bad()</script>', 'desc' => '<em>Copy</em>', 'unknown' => 'drop-me'],
]],
'header_slider_card_option' => ['show_widget_bg' => true, 'cards' => []],
];
$header_clean = $provider->sanitize_payload('page_display', $header_payload, 'header-components');
@@ -219,9 +220,10 @@ namespace {
* @param list<string> $show_on
* @param array<string,mixed> $page_config
*/
function aksrt_visibility_case(string $query, array $show_on, array $page_config = []): bool {
function aksrt_visibility_case(string $query, array $show_on, array $page_config = [], int $paged = 0): bool {
$GLOBALS['aksrt_visibility_query'] = $query;
$GLOBALS['aksrt_visibility_page_config'] = $page_config;
$GLOBALS['wp_query'] = new WP_Query(['paged' => $paged]);
\AKSRT\Settings\Settings::$headerSlider = [
'show_on_pages' => $show_on,
'show_type' => '',
@@ -249,6 +251,7 @@ namespace {
'message_excludes_home' => aksrt_visibility_case('message', ['home']),
'home_excludes_public_home' => aksrt_visibility_case('user_home', ['home']),
'home_excludes_user_center' => aksrt_visibility_case('user_center', ['home']),
'paged_archive_hidden' => aksrt_visibility_case('home', ['home'], [], 2),
];
echo json_encode([
@@ -260,6 +263,7 @@ namespace {
'invalid_enum_rejected' => !$invalid_validation['valid'],
'nested_multiselect_valid' => $category_validation['valid'],
'nested' => $header_clean,
'header_card_bg' => $header_clean['header_slider_card_option']['show_widget_bg'] ?? null,
'footer_valid' => $footer_validation['valid'],
'footer_clean' => $footer_clean,
'footer_readback' => $footer_readback,
@@ -0,0 +1,45 @@
const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const { spawnSync } = require('node:child_process');
const root = path.resolve(__dirname, '..', '..');
const read = (file) => fs.readFileSync(path.join(root, file), 'utf8');
test('search route keeps the reference Zibll results and empty-state structure', () => {
const template = read('search.php');
const styles = read('assets/css/main.css');
for (const token of ['search-input', 'search-page-ajaxpager', 'search-tab-header', 'search-filter-item', 'post_ajax_loader']) {
assert.match(template + styles, new RegExp(token.replace(/[.*+?^${}()|[\\]\\]/g, '\\$&')));
}
assert.match(template, /aksrt_get_ajax_null\(__\('请输入搜索关键词'/);
assert.match(template, /'null-search\.svg'/);
assert.match(template, /user_query instanceof WP_User_Query/);
assert.equal(fs.existsSync(path.join(root, 'assets/css/routes/search.css')), false);
assert.match(template, /'skip_wrapper' => true/);
assert.match(template, /null-user\.svg/);
assert.match(template, /null-post\.svg/);
assert.match(template, /route-title=/);
for (const image of ['null-search.svg', 'null-user.svg', 'null-post.svg']) {
assert.match(read(`assets/img/${image}`), /<svg\b/);
}
assert.equal(fs.existsSync(path.join(root, 'assets/img/null-search.svg')), true);
assert.equal(fs.existsSync(path.join(root, 'assets/img/null-user.svg')), true);
});
test('search rendering preserves form state, result markup, paging and escaped keywords', () => {
const result = spawnSync(process.env.PHP_BINARY || 'php', [path.join(__dirname, 'search-render-harness.php')], {
cwd: root,
encoding: 'utf8',
});
assert.equal(result.status, 0, result.stderr || result.stdout);
assert.match(result.stdout, /Search render harness passed/);
});
test('search route renders reference fluid widget sidebars in order', () => {
const template = read('search.php');
assert.match(template, /dynamic_sidebar\('all_top_fluid'\)[\s\S]*dynamic_sidebar\('search_top_fluid'\)/);
assert.match(template, /dynamic_sidebar\('search_bottom_fluid'\)[\s\S]*dynamic_sidebar\('all_bottom_fluid'\)/);
});
@@ -0,0 +1,200 @@
<?php
declare(strict_types=1);
define('ABSPATH', dirname(__DIR__, 2) . DIRECTORY_SEPARATOR);
define('COOKIEPATH', '/');
define('COOKIE_DOMAIN', '');
define('MONTH_IN_SECONDS', 2592000);
function __($text): string { return (string) $text; }
function esc_html($value): string { return htmlspecialchars((string) $value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); }
function esc_attr($value): string { return esc_html($value); }
function esc_url($value): string { return esc_attr($value); }
function esc_url_raw($value): string { return (string) $value; }
function esc_html__($text): string { return esc_html($text); }
function esc_attr__($text): string { return esc_attr($text); }
function wp_strip_all_tags($value): string { return strip_tags((string) $value); }
function wp_parse_args($args, $defaults = []): array { return array_merge($defaults, is_array($args) ? $args : []); }
function sanitize_html_class($class, $fallback = ''): string {
$value = preg_replace('/[^A-Za-z0-9_-]/', '', (string) $class) ?? '';
return $value !== '' ? $value : (string) $fallback;
}
function sanitize_key($value): string { return preg_replace('/[^a-z0-9_-]/', '', strtolower((string) $value)) ?? ''; }
function wp_unslash($value) { return $value; }
function absint($value): int { return abs((int) $value); }
function is_search(): bool { return true; }
function get_search_query(bool $escaped = true): string { return $escaped ? esc_attr($GLOBALS['search_text']) : $GLOBALS['search_text']; }
function get_query_var($key) { return 1; }
function home_url($path = '/'): string { return 'https://example.test' . $path; }
function add_query_arg($key, $value = null, $url = ''): string {
if (is_array($key)) {
$args = $key;
$url = (string) $value;
} else {
$args = [(string) $key => $value];
$url = (string) $url;
}
return rtrim($url, '/') . '/?' . http_build_query($args);
}
function get_bloginfo($key): string { return $key === 'name' ? 'AKSRT' : ''; }
function number_format_i18n($number): string { return number_format((float) $number); }
function wp_kses_post($html): string { return strip_tags((string) $html, '<a><b><span><i><div><p><ul><li>'); }
function is_wp_error($value): bool { return false; }
function is_active_sidebar($id): bool { return false; }
function dynamic_sidebar($id): void {}
function get_header(): void {}
function get_sidebar(): void {}
function get_footer(): void {}
function aksrt_save_history_search(string $value): void {}
function aksrt_update_search_keywords(string $value): void {}
function aksrt_search_history_enabled(): bool { return false; }
function aksrt_get_search_hot_keywords(): array { return []; }
function aksrt_get_search_type_options(): array { return ['post' => '文章', 'user' => '用户']; }
function aksrt_get_search_form_type(): string { return (string) ($_REQUEST['type'] ?? 'post'); }
function aksrt_get_search_form_state(): array {
return ['type' => aksrt_get_search_form_type(), 'types' => aksrt_get_search_type_options(), 'category_id' => 0, 'category_enabled' => false, 'categories' => []];
}
class WP_Term {
public function __construct(public int $term_id, public string $name, public string $taxonomy = 'category') {}
}
function aksrt_get_search_categories(?array $ids = null): array {
return array_map(static fn($id) => new WP_Term((int) $id, (int) $id === 7 ? 'Tech' : 'News'), $ids ?? []);
}
function get_term($id) { return new WP_Term((int) $id, 'Tech'); }
function get_term_link($term): string { return 'https://example.test/category/' . $term->term_id; }
function get_taxonomy($taxonomy) { return (object) ['labels' => (object) ['singular_name' => '分类']]; }
class WP_Query {
public int $found_posts = 0;
public array $posts = [];
public function have_posts(): bool { return (bool) $this->posts; }
public function the_post(): void {}
}
class WP_User_Query {
public function __construct(private array $args) { $GLOBALS['last_user_query_args'] = $args; }
public function get_results(): array { return $GLOBALS['users']; }
public function get_total(): int { return $GLOBALS['user_total']; }
}
function get_userdata($id) { return $GLOBALS['user_data'][(int) $id] ?? false; }
function aksrt_get_user_home_url($id): string { return 'https://example.test/user/' . (int) $id; }
function get_author_posts_url($id): string { return aksrt_get_user_home_url($id); }
function aksrt_get_avatar_url($id, $args = []): string { return 'https://example.test/avatar/' . (int) $id . '.png'; }
function aksrt_get_lazy_attr($mode, $url, $class = '', $placeholder = ''): string {
return ' class="' . esc_attr($class) . '" src="' . esc_attr($url) . '"';
}
function aksrt_get_lazy_thumb($size): string { return ''; }
function aksrt_get_user_name($args): string {
$user = get_userdata((int) $args['id']);
$name = function_exists('aksrt_renderer_highlight_text')
? aksrt_renderer_highlight_text((string) $user->display_name, (string) ($args['highlight_query'] ?? ''))
: esc_html($user->display_name);
return '<name class="flex ac flex1"><a class="display-name" href="' . esc_url(aksrt_get_user_home_url($user->ID)) . '">' . $name . '</a></name>';
}
function aksrt_get_user_follow($class, $id): string { return '<a class="follow flex0" data-follow="' . (int) $id . '">Follow</a>'; }
function aksrt_get_user_description($id): string { return (string) (get_userdata($id)->description ?? ''); }
function get_user_meta($id, $key, $single = true): string { return ''; }
function aksrt_get_ajax_null(?string $text = null, $margin = 60, string $img = 'null.svg', int $width = 280): string {
return '<div class="ajax-item aksrt-ajax-null" data-img="' . esc_attr($img) . '" data-width="' . $width . '">' . esc_html((string) $text) . '</div>';
}
function aksrt_get_null($text = null, $margin = 60, string $img = 'null.svg', string $class = '', int $width = 280): string { return ''; }
function aksrt_get_search_tab_nav_filter(string $type): string { return ''; }
function aksrt_archive_get_render_config(array $args): array { return $args + ['mode' => 'list']; }
function aksrt_render_post_list(array $args, WP_Query $query): void {
$title = $query->posts[0]->post_title ?? '';
echo '<div class="posts-item list ajax-item">' . aksrt_renderer_highlight_text((string) $title, (string) ($args['highlight_query'] ?? '')) . '</div>';
}
function aksrt_render_pagination($query, array $args): void {}
function aksrt_render_placeholder($kind, $count): string { return ''; }
require ABSPATH . 'inc/helpers/posts-renderer/config.php';
require ABSPATH . 'inc/helpers/aksrt-graphic-card.php';
require ABSPATH . 'inc/helpers/aksrt-ajax-list.php';
require ABSPATH . 'inc/helpers/search/aksrt-search-box.php';
function render_search_case(string $query, string $type, array $users = [], int $user_total = 0, array $posts = []): string {
$GLOBALS['search_text'] = $query;
$GLOBALS['users'] = $users;
$GLOBALS['user_total'] = $user_total;
$GLOBALS['last_user_query_args'] = [];
$GLOBALS['user_data'] = [];
foreach ($users as $user) {
$GLOBALS['user_data'][$user->ID] = $user;
}
$_REQUEST = ['type' => $type];
$_GET = $_REQUEST;
$GLOBALS['wp_query'] = new WP_Query();
$GLOBALS['wp_query']->found_posts = count($posts);
$GLOBALS['wp_query']->posts = $posts;
ob_start();
include ABSPATH . 'search.php';
return (string) ob_get_clean();
}
$empty = render_search_case('', 'post');
if (!str_contains($empty, 'null-search.svg') || !str_contains($empty, 'data-width="300"') || str_contains($empty, 'search-page-ajaxpager')) {
throw new RuntimeException('Empty search markup does not match the reference state.');
}
$query = 'A&B "Z"';
$post_html = render_search_case($query, 'post', [], 0, [(object) ['post_title' => $query]]);
if (!str_contains($post_html, 'posts-item list ajax-item') || !str_contains($post_html, 'A&amp;B') || !str_contains($post_html, '&quot;Z&quot;')) {
throw new RuntimeException('Post result markup or escaping failed.');
}
$user = (object) ['ID' => 5, 'display_name' => $query, 'description' => 'About ' . $query];
$user_html = render_search_case($query, 'user', [$user], 25);
if (!str_contains($user_html, 'author-minicard') || !str_contains($user_html, 'follow flex0') || !str_contains($user_html, 'user_paged=2') || !str_contains($user_html, 'type=user') || !str_contains($user_html, 's=A%26B') || !str_contains($user_html, 'orderby=name')) {
throw new RuntimeException('User card or AJAX pagination markup failed.');
}
if (($GLOBALS['last_user_query_args']['orderby'] ?? '') !== 'display_name') {
throw new RuntimeException('User name ordering is not mapped to WP_User_Query.');
}
$highlight = aksrt_renderer_highlight_text('<b>A&B</b> "Z" <script>x</script>', $query);
$plain = html_entity_decode(strip_tags($highlight), ENT_QUOTES | ENT_HTML5, 'UTF-8');
if ($plain !== 'A&B "Z" x' || !str_contains($highlight, '<b class="focus-color">')) {
throw new RuntimeException('Keyword highlighting does not preserve safe text.');
}
$form_with_category = aksrt_get_search_box([
'class' => 'main-search page-search-box',
's' => '',
'show_keywords' => false,
'show_history' => false,
'show_posts' => false,
'show_input_cat' => true,
'more_cats' => [7],
'show_type' => true,
'in_type' => 'post',
], false);
$form_without_category = aksrt_get_search_box([
'class' => 'main-search page-search-box',
's' => '',
'show_keywords' => false,
'show_history' => false,
'show_posts' => false,
'show_input_cat' => true,
'more_cats' => [],
'show_type' => true,
'in_type' => 'post',
], false);
if (!str_contains((string) $form_with_category, 'main-search page-search-box') || !str_contains((string) $form_with_category, 'Tech') || !str_contains((string) $form_with_category, 'search-type-but-average')) {
throw new RuntimeException('WP_Term category selector or multi-class search wrapper failed.');
}
if (!str_contains((string) $form_without_category, 'name="type"') || !str_contains((string) $form_without_category, 'dropdown-menu')) {
throw new RuntimeException('Search type dropdown is missing when no category picker is available.');
}
if (!str_contains((string) $form_with_category, 'class="line-form-input" tabindex="1" value=""')) {
throw new RuntimeException('The header form must preserve its own empty query on a search results page.');
}
foreach (['post' => 'null-post.svg', 'user' => 'null-user.svg'] as $type => $image) {
$no_results = render_search_case('No matches', $type);
if (!str_contains($no_results, 'class="ajax-item aksrt-ajax-null"') || !str_contains($no_results, $image)) {
throw new RuntimeException('Empty results must remain an AJAX replaceable illustrated item.');
}
}
echo "Search render harness passed: empty, post, user, escaping, WP_Term category and no-category type dropdown.\n";
@@ -0,0 +1,100 @@
'use strict';
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const test = require('node:test');
const vm = require('node:vm');
const root = path.resolve(__dirname, '../..');
const read = (file) => fs.readFileSync(path.join(root, file), 'utf8');
const runtime = read('assets/js/runtime/main.js');
function handlerBetween(start, end, context) {
let handler;
vm.runInNewContext(runtime.slice(runtime.indexOf(start), runtime.indexOf(end)), {
_win: { bd: { on(event, selector, callback) { handler = callback; } } },
...context,
});
assert.equal(typeof handler, 'function');
return handler;
}
test('search type changes reset only the active form placeholder', () => {
const field = { length: 1, attr: () => '开启精彩搜索', text(value) { this.value = value; } };
const control = {};
const handler = handlerBetween('//搜索功能-恢复默认占位符', '//搜索功能->删除多余的input', {
jQuery(target) {
assert.equal(target, control, 'must not select all search boxes');
return { closest(selector) {
assert.equal(selector, 'form');
return { find(selector) { assert.equal(selector, '.scale-placeholder'); return field; } };
} };
},
});
handler.call(control);
assert.equal(field.value, '开启精彩搜索');
});
test('clearing history expires the saved cookie at its original WordPress path and domain', () => {
const control = {};
const history = {};
const cookies = [];
let removed = false;
let confirmed = true;
const jQuery = (target) => {
if (target === control) return { attr(name) {
return { 'data-cookie-path': '/blog/', 'data-cookie-domain': '.example.test' }[name];
} };
if (target === '.history-search') return { slideUp(duration, complete) {
assert.equal(duration, 300);
complete.call(history);
} };
assert.equal(target, history);
return { remove() { removed = true; } };
};
jQuery.cookie = (name, value, options) => cookies.push({ name, value, ...options });
const handler = handlerBetween('//清空搜索关键词', '//用户签到', {
jQuery, confirm: () => confirmed, aksrt__: (key) => key,
});
handler.call(control);
assert.deepEqual(cookies, [{ name: 'history_search', value: null, path: '/blog/', domain: '.example.test' }]);
assert.equal(removed, true);
confirmed = false;
handler.call(control);
assert.equal(cookies.length, 1, 'cancelling must preserve history');
});
test('removed search markup has no orphaned JavaScript owner', () => {
assert.doesNotMatch(read('assets/js/core/article.js'), /initSearchClear|search-clear-btn|search-page-input|search-category-filter|aksrt_search_type|aksrt_category/);
assert.doesNotMatch(runtime, /eval\('\/' \+ val|search-tab \.item-heading/);
assert.doesNotMatch(runtime, /css\/dplayer\.min\.css/);
});
test('search submissions replace results with encoded filters and navigate normally when cleared', () => {
const handlers = {};
const form = {};
let data = { s: '主题 & "搜索"', type: 'post', trem: '7' };
let linkMarkup = '';
let clicks = 0;
const link = { click() { clicks++; return this; }, remove() {} };
const pager = { length: 1, append(node) { assert.equal(node, link); } };
const jQuery = (target) => {
if (target === '.search-page-ajaxpager') return pager;
if (target === form) return { serializeObject: () => data, attr: () => 'https://example.test/blog/' };
linkMarkup = target;
return link;
};
vm.runInNewContext(runtime.slice(runtime.indexOf('//搜索页面关键词ajax'), runtime.indexOf('function nav_folding()')), {
_win: { bd: { on(event, selector, handler) { handlers[event] = handler; } } },
jQuery, URL, URLSearchParams,
});
assert.equal(handlers.submit.call(form), false);
const url = new URL(linkMarkup.match(/href="([^"]+)"/)[1]);
assert.equal(url.searchParams.get('s'), data.s);
assert.equal(url.searchParams.get('type'), 'post');
assert.equal(url.searchParams.get('trem'), '7');
assert.equal(clicks, 1);
data = { s: ' ', type: 'post' };
assert.equal(handlers.submit.call(form), undefined);
assert.equal(clicks, 1, 'the empty page has no AJAX pager and must use normal form navigation');
});