feat(search): 效果五快捷栏加入本地搜索
- 引擎选项新增「本地」并作为默认;本地模式回车打开第一个匹配条目/分组 - 快捷栏改为贴在搜索框右侧内部展开,贴合效果五 - 外部引擎仍在新标签页搜索,输入时本地过滤逻辑保持
This commit is contained in:
+15
-2
@@ -1478,8 +1478,8 @@ html.theme-transition .site-background {
|
||||
|
||||
.engine-menu {
|
||||
position: absolute;
|
||||
top: calc(100% + 12px);
|
||||
right: 0;
|
||||
top: 50%;
|
||||
right: calc(100% + 6px);
|
||||
z-index: var(--su-z-float);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@@ -1489,6 +1489,19 @@ html.theme-transition .site-background {
|
||||
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);
|
||||
}
|
||||
|
||||
@keyframes engine-bar-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translate(6px, -50%);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translate(0, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
.engine-option {
|
||||
|
||||
@@ -63,6 +63,7 @@ type Route =
|
||||
| { kind: 'api' }
|
||||
|
||||
const SEARCH_ENGINES = [
|
||||
{ key: 'local', name: '本地', search: '' },
|
||||
{ key: 'google', name: 'Google', search: 'https://www.google.com/search?q=' },
|
||||
{ key: 'bing', name: 'Bing', search: 'https://www.bing.com/search?q=' },
|
||||
{ key: 'baidu', name: '百度', search: 'https://www.baidu.com/s?wd=' },
|
||||
@@ -202,6 +203,24 @@ function matches(entry: Record<string, unknown>, keyword: string): boolean {
|
||||
return text.includes(keyword)
|
||||
}
|
||||
|
||||
/** 本地搜索回车时打开第一个匹配项;没有条目命中但分组名命中时打开分组 */
|
||||
function findLocalTarget(
|
||||
groups: GroupNode[],
|
||||
keyword: string,
|
||||
): { group: GroupNode; entry?: Record<string, unknown> } | undefined {
|
||||
for (const group of groups) {
|
||||
if (group.enabled === false) continue
|
||||
if (group.title.toLowerCase().includes(keyword)) return { group }
|
||||
const entry = (group.entries as unknown as Record<string, unknown>[]).find((item) =>
|
||||
matches(item, keyword),
|
||||
)
|
||||
if (entry !== undefined) return { group, entry }
|
||||
const child = findLocalTarget(group.children, keyword)
|
||||
if (child !== undefined) return child
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
export default function AppNext() {
|
||||
const { status, projects, error, live, refreshing, refresh } = useProjects()
|
||||
const { route, navigate } = useRoute()
|
||||
@@ -388,6 +407,20 @@ export default function AppNext() {
|
||||
}
|
||||
if (event.key !== 'Enter' || keyword.trim() === '') return
|
||||
event.preventDefault()
|
||||
setEngineOpen(false)
|
||||
|
||||
if (searchEngine.key === 'local') {
|
||||
const target = findLocalTarget(manage.groups, keywordLower)
|
||||
if (target !== undefined) {
|
||||
navigate(
|
||||
target.entry === undefined
|
||||
? `/g/${encodeURIComponent(target.group.key)}`
|
||||
: `/g/${encodeURIComponent(target.group.key)}/i/${encodeURIComponent(String(target.entry.id))}`,
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
window.open(
|
||||
`${searchEngine.search}${encodeURIComponent(keyword.trim())}`,
|
||||
'_blank',
|
||||
@@ -396,7 +429,7 @@ export default function AppNext() {
|
||||
}
|
||||
input.addEventListener('keydown', handleKeyDown)
|
||||
return () => input.removeEventListener('keydown', handleKeyDown)
|
||||
}, [keyword, searchEngine])
|
||||
}, [keyword, keywordLower, manage.groups, navigate, searchEngine])
|
||||
|
||||
const chooseEngine = (next: SearchEngine) => {
|
||||
setSearchEngine(next)
|
||||
@@ -797,8 +830,16 @@ export default function AppNext() {
|
||||
value={keyword}
|
||||
onChange={setKeyword}
|
||||
inputRef={searchRef}
|
||||
placeholder="搜索本地项目…"
|
||||
label="搜索本地项目,回车使用当前搜索引擎"
|
||||
placeholder={
|
||||
searchEngine.key === 'local'
|
||||
? '搜索本地项目…'
|
||||
: `用 ${searchEngine.name} 搜索,回车打开…`
|
||||
}
|
||||
label={
|
||||
searchEngine.key === 'local'
|
||||
? '搜索本地项目,回车打开第一个匹配项'
|
||||
: `用 ${searchEngine.name} 搜索,回车打开新标签页`
|
||||
}
|
||||
variant="card"
|
||||
hotkey="k"
|
||||
suffix={
|
||||
@@ -809,7 +850,11 @@ export default function AppNext() {
|
||||
aria-haspopup="menu"
|
||||
aria-expanded={engineOpen}
|
||||
aria-label={`搜索引擎:${searchEngine.name},点击切换`}
|
||||
title={`当前:${searchEngine.name};回车用该引擎搜索`}
|
||||
title={
|
||||
searchEngine.key === 'local'
|
||||
? '当前:本地搜索;回车打开第一个匹配项'
|
||||
: `当前:${searchEngine.name};回车用该引擎搜索`
|
||||
}
|
||||
onClick={() => setEngineOpen((open) => !open)}
|
||||
>
|
||||
{searchEngine.name}
|
||||
|
||||
Reference in New Issue
Block a user