feat(search): 按参考稿重做搜索框并支持后台配置

- 顶部悬浮引擎标签 + 下拉选项,使用 stash-ui 新增的 EngineIcon
- 站内搜索保持现有本地过滤与回车打开首个匹配项
- 外部引擎使用配置的 {query} 模板新标签页搜索
- settings 新增 search.default / search.engines,后台新增『搜索框』配置默认项、名称、地址与启停
- 默认默认搜索项为站内搜索,地址校验必须含 {query}
This commit is contained in:
2026-11-04 18:11:22 +08:00
parent 5ae2088826
commit aa6f341505
6 changed files with 447 additions and 127 deletions
+94 -47
View File
@@ -1437,96 +1437,143 @@ html.theme-transition .site-background {
}
}
/* ---------- 搜索框:搜索引擎切换(效果五) ---------- */
.engine-switch {
/* ---------- 搜索框:顶部引擎标签 + 下拉选项 ---------- */
.search-shell {
position: relative;
display: inline-flex;
align-items: center;
width: min(100%, 480px);
}
.engine-trigger {
.engine-badge {
position: absolute;
top: -12px;
left: 16px;
z-index: 2;
display: inline-flex;
align-items: center;
justify-content: center;
width: 26px;
height: 26px;
padding: 0;
border: 0;
border-radius: var(--su-radius-xs);
background: transparent;
color: var(--su-text-muted);
font-size: var(--su-font-size-lg);
gap: 5px;
padding: 2px 8px;
border: 1px solid var(--su-border);
border-radius: 6px;
background-color: var(--su-bg-card);
box-shadow: var(--su-shadow-card);
color: var(--su-text-main);
font: inherit;
font-size: 11px;
line-height: 1.4;
cursor: pointer;
transition:
color var(--su-duration-fast) var(--su-ease-in-out),
background-color var(--su-duration-fast) var(--su-ease-in-out);
background-color var(--su-duration-fast) var(--su-ease-in-out),
border-color var(--su-duration-fast) var(--su-ease-in-out);
}
.engine-trigger:hover,
.engine-trigger[aria-expanded='true'] {
.engine-badge:hover,
.engine-badge[aria-expanded='true'] {
border-color: var(--su-border-strong);
background-color: var(--su-bg-subtle);
color: var(--su-text-main);
}
.engine-trigger svg {
.engine-badge svg {
display: block;
flex-shrink: 0;
}
.engine-menu {
.engine-dropdown {
position: absolute;
top: 50%;
left: calc(100% + 6px);
top: calc(100% + 8px);
left: 10px;
z-index: var(--su-z-float);
display: flex;
flex-direction: row;
flex-direction: column;
gap: 2px;
min-width: 170px;
padding: var(--su-space-1);
border: 1px solid var(--su-border);
border-radius: var(--su-radius-sm);
background-color: var(--su-bg-card);
box-shadow: var(--su-shadow-pop);
transform: translateY(-50%);
animation: engine-bar-in 140ms var(--su-ease-out);
animation: engine-menu-in 160ms var(--su-ease-out);
}
@keyframes engine-bar-in {
@keyframes engine-menu-in {
from {
opacity: 0;
transform: translate(-6px, -50%);
transform: translateY(-6px);
}
to {
opacity: 1;
transform: translate(0, -50%);
transform: translateY(0);
}
}
.engine-option {
display: inline-flex;
align-items: center;
gap: 4px;
padding: var(--su-space-1) var(--su-space-2);
border: 0;
border-radius: var(--su-radius-xs);
background: transparent;
color: var(--su-text-sub);
font: inherit;
font-size: var(--su-font-size-xs);
white-space: nowrap;
cursor: pointer;
.engine-divider {
height: 1px;
margin: 4px 8px;
background-color: var(--su-border);
}
.engine-option-icon {
display: inline-flex;
font-size: var(--su-font-size-lg);
.engine-option {
display: flex;
align-items: center;
gap: 10px;
width: 100%;
padding: 8px 12px;
border: 0;
border-radius: 6px;
background: transparent;
color: var(--su-text-main);
font: inherit;
font-size: 13px;
text-align: left;
white-space: nowrap;
cursor: pointer;
transition: background-color var(--su-duration-fast) var(--su-ease-in-out);
}
.engine-option:hover {
background-color: var(--su-bg-subtle);
color: var(--su-text-main);
}
.engine-option.is-active {
background-color: var(--su-color-primary-soft);
color: var(--su-color-primary);
font-weight: 600;
}
/* 后台:搜索框引擎配置 */
.search-engine-list {
display: flex;
flex-direction: column;
gap: var(--su-space-3);
}
.search-engine-row {
padding: var(--su-space-4);
border: 1px solid var(--su-border);
border-radius: var(--su-radius-md);
}
.search-engine-row.is-disabled {
opacity: 0.55;
}
.search-engine-head {
display: flex;
align-items: center;
gap: var(--su-space-2);
margin-bottom: var(--su-space-3);
}
.search-engine-head > :last-child {
margin-left: auto;
}
.search-engine-fields {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
gap: var(--su-space-3);
}
@media (width <= 900px) {
.search-engine-fields {
grid-template-columns: minmax(0, 1fr);
}
}