Skip to content

Commit 67c7e39

Browse files
feature: 新增内容搜索功能,快捷键:Ctrl + F
1 parent a6d2685 commit 67c7e39

File tree

7 files changed

+156
-17
lines changed

7 files changed

+156
-17
lines changed

packages/gui/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"request-progress": "^3.0.0",
3535
"sass": "^1.81.0",
3636
"sass-loader": "^16.0.3",
37+
"search-bar-vue2": "^1.0.0",
3738
"vue": "^2.7.16",
3839
"vue-json-editor-fix-cn": "^1.4.3",
3940
"vue-router": "^3.6.5"

packages/gui/src/background.js

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -298,28 +298,38 @@ function createWindow (startHideWindow, autoQuitIfError = true) {
298298
})
299299

300300
const shortcut = (event, input) => {
301-
// 按 F12,打开/关闭 开发者工具
302-
if (input.key === 'F12') {
303-
// 阻止默认的按键事件行为
301+
if (input.key === 'F12' && input.type === 'keyUp' && !input.control && !input.shift && !input.alt && !input.meta) {
302+
// 按 F12,打开/关闭 开发者工具
304303
event.preventDefault()
305-
// 切换开发者工具显示状态
306304
switchDevTools()
307-
// eslint-disable-next-line style/brace-style
308-
}
309-
// 按 F5,刷新页面
310-
else if (input.key === 'F5') {
311-
// 阻止默认的按键事件行为
305+
} else if (input.key === 'F5' && input.type === 'keyUp' && !input.control && !input.shift && !input.alt && !input.meta) {
306+
// 按 F5,刷新页面
312307
event.preventDefault()
313-
// 刷新页面
314308
win.webContents.reload()
309+
} else {
310+
// 全文检索框(SearchBar)相关快捷键
311+
if ((input.key === 'F' || input.key === 'f') && input.type === 'keyDown' && input.control && !input.shift && !input.alt && !input.meta) {
312+
// 按 Ctrl + F,显示或隐藏全文检索框(SearchBar)
313+
event.preventDefault()
314+
win.webContents.send('search-bar', { key: 'show-hide' })
315+
} else if (input.key === 'Escape' && input.type === 'keyUp' && !input.control && !input.shift && !input.alt && !input.meta) {
316+
// 按 ESC,隐藏全文检索框(SearchBar)
317+
event.preventDefault()
318+
win.webContents.send('search-bar', { key: 'hide' })
319+
} else if (input.key === 'F3' && input.type === 'keyDown' && !input.control && !input.shift && !input.alt && !input.meta) {
320+
// 按 F3,全文检索框(SearchBar)定位到下一个
321+
event.preventDefault()
322+
win.webContents.send('search-bar', { key: 'next' })
323+
} else if (input.key === 'F3' && input.type === 'keyDown' && !input.control && input.shift && !input.alt && !input.meta) {
324+
// 按 Shift + F3,全文检索框(SearchBar)定位到上一个
325+
event.preventDefault()
326+
win.webContents.send('search-bar', { key: 'previous' })
327+
}
315328
}
316329
}
317330

318331
// 监听键盘事件
319332
win.webContents.on('before-input-event', (event, input) => {
320-
if (input.type !== 'keyUp' || input.control || input.alt || input.shift || input.meta) {
321-
return
322-
}
323333
win.webContents.executeJavaScript('config')
324334
.then((value) => {
325335
console.info('window.config:', value, ', key:', input.key)

packages/gui/src/main.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import antd from 'ant-design-vue'
22
import Vue from 'vue'
33
import VueRouter from 'vue-router'
4+
import SearchBar from 'search-bar-vue2'
45
import { ipcRenderer } from 'electron'
56
import view from './view'
67
import App from './view/App.vue'
@@ -25,6 +26,7 @@ try {
2526
Vue.config.productionTip = false
2627
Vue.use(antd)
2728
Vue.use(VueRouter)
29+
Vue.use(SearchBar)
2830
Vue.component(DsContainer)
2931
// 3. 创建 router 实例,然后传 `routes` 配置
3032
// 你还可以传别的配置参数, 不过先这么简单着吧。

packages/gui/src/view/App.vue

Lines changed: 102 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<script>
2+
import { ipcRenderer } from 'electron'
23
import createMenus from '@/view/router/menu'
34
import zhCN from 'ant-design-vue/lib/locale-provider/zh_CN'
45
import { colorTheme } from './composables/theme'
@@ -11,6 +12,9 @@ export default {
1112
info: {},
1213
menus: undefined,
1314
config: undefined,
15+
hideSearchBar: true,
16+
searchBarIsFocused: false,
17+
searchBarInputKeyupTimeout: null,
1418
}
1519
},
1620
computed: {
@@ -35,13 +39,95 @@ export default {
3539
this.$api.info.get().then((ret) => {
3640
this.info = ret
3741
})
42+
43+
ipcRenderer.on('search-bar', (_, message) => {
44+
if (window.config.disableSearchBar) {
45+
this.hideSearchBar = true
46+
return
47+
}
48+
49+
// 如果不是显示/隐藏操作,并且还未显示检索框,先按显示操作处理
50+
if (!message.key.includes('hide') && this.hideSearchBar) {
51+
message = { key: 'show-hide' }
52+
}
53+
54+
try {
55+
if (message.key === 'show-hide') { // 显示/隐藏
56+
const hide = message.hideSearchBar != null ? message.hideSearchBar : !this.hideSearchBar
57+
58+
// 如果为隐藏操作,但SearchBar未隐藏且未获取焦点,则获取焦点
59+
if (hide && !this.hideSearchBar && !this.searchBarIsFocused) {
60+
this.doSearchBarInputFocus()
61+
return
62+
}
63+
64+
this.hideSearchBar = hide
65+
66+
// 显示后,获取输入框焦点
67+
if (!this.hideSearchBar) {
68+
this.doSearchBarInputFocus()
69+
} else {
70+
this.searchBarIsFocused = false
71+
}
72+
} else if (message.key === 'hide') { // 隐藏
73+
this.hideSearchBar = true
74+
this.searchBarIsFocused = false
75+
} else if (message.key === 'next') { // 下一项
76+
this.$refs.searchBar.next()
77+
} else if (message.key === 'previous') { // 上一项
78+
this.$refs.searchBar.previous()
79+
}
80+
} catch (e) {
81+
console.error('操作SearchBar出现异常:', e)
82+
}
83+
84+
const input = this.getSearchBarInput()
85+
if (input) {
86+
input.addEventListener('focus', this.onSearchBarInputFocus)
87+
input.addEventListener('blur', this.onSearchBarInputBlur)
88+
input.addEventListener('keydown', this.onSearchBarInputKeydown)
89+
input.addEventListener('keyup', this.onSearchBarInputKeyup)
90+
}
91+
})
3892
},
3993
methods: {
94+
getSearchBarInput () {
95+
return this.$refs.searchBar.$el.querySelector('input[type=text]')
96+
},
97+
onSearchBarInputFocus () {
98+
this.searchBarIsFocused = true
99+
},
100+
onSearchBarInputBlur () {
101+
this.searchBarIsFocused = false
102+
},
103+
onSearchBarInputKeydown () {
104+
clearTimeout(this.searchBarInputKeyupTimeout)
105+
},
106+
onSearchBarInputKeyup (e) {
107+
if (!this.$refs.searchBar || e.key === 'Enter' || e.key === 'F3') {
108+
return
109+
}
110+
clearTimeout(this.searchBarInputKeyupTimeout)
111+
this.searchBarInputKeyupTimeout = setTimeout(() => {
112+
// 连续调用以下两个方法,为了获取检索结果中的第一项
113+
this.$refs.searchBar.next()
114+
this.$refs.searchBar.previous()
115+
}, 150)
116+
},
117+
doSearchBarInputFocus () {
118+
setTimeout(() => {
119+
const input = this.getSearchBarInput()
120+
if (input) {
121+
input.focus()
122+
}
123+
}, 100)
124+
},
40125
titleClick (item) {
41126
console.log('title click:', item)
42127
},
43128
menuClick (item) {
44129
console.log('menu click:', item)
130+
window.config.disableSearchBar = false
45131
this.$router.replace(item.path)
46132
},
47133
},
@@ -51,6 +137,13 @@ export default {
51137
<template>
52138
<a-config-provider :locale="locale">
53139
<div class="ds_layout" :class="themeClass">
140+
<SearchBar ref="searchBar"
141+
:root="'#document'"
142+
:highlightClass="'search-bar-highlight'"
143+
:selectedClass="'selected-highlight'"
144+
:hiden.sync="hideSearchBar"
145+
style="inset:auto auto 53px 210px; background-color:#ddd"
146+
/>
54147
<a-layout>
55148
<a-layout-sider :theme="theme">
56149
<div class="logo" />
@@ -78,7 +171,7 @@ export default {
78171
<a-layout>
79172
<!-- <a-layout-header>Header</a-layout-header> -->
80173
<a-layout-content>
81-
<router-view />
174+
<router-view id="document" />
82175
</a-layout-content>
83176
<a-layout-footer>
84177
<div class="footer">
@@ -139,4 +232,12 @@ body {
139232
border: 0;
140233
}
141234
}
235+
.search-bar-highlight {
236+
background-color: #ef0fff;
237+
color: #fdfdfd;
238+
239+
&.selected-highlight {
240+
background-color: #17a450;
241+
}
242+
}
142243
</style>

packages/gui/src/view/pages/setting.vue

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,15 +169,19 @@ export default {
169169
shortcut += 'Meta + '
170170
}
171171
172-
// 如果以上按钮都没有按下,并且当前键不是F1~F4、F6~F11时,则直接返回(注:F5已经是刷新页面快捷键、F12已经是打开DevTools的快捷键了)
173-
if (shortcut === '' && !key.match(/^F([1-46-9]|1[01])$/g)) {
172+
// 如果以上按钮都没有按下,并且当前键不是F1、F2、F4、F6~F11时,则直接返回(注:F5已经是刷新页面快捷键、F12已经是打开DevTools的快捷键了)
173+
if (shortcut === '' && !key.match(/^F([1246-9]|1[01])$/g)) {
174174
this.config.app.showHideShortcut = ''
175175
return
176176
}
177177
178178
// 拼接键值
179179
shortcut += key
180180
181+
if (shortcut === 'Ctrl + F' || shortcut === 'Shift + F3') {
182+
shortcut = '' // 如果是其他已被占用快捷键,则设置为 '无'
183+
}
184+
181185
this.config.app.showHideShortcut = shortcut
182186
},
183187
async applyBefore () {
@@ -430,7 +434,7 @@ export default {
430434
<a-form-item label="打开窗口快捷键" :label-col="labelCol" :wrapper-col="wrapperCol">
431435
<a-input v-model="config.app.showHideShortcut" @change="shortcutChange" @keydown="shortcutKeyDown" @keyup="shortcutKeyUp" />
432436
<div class="form-help">
433-
部分快捷键已被占用:F5=刷新页面,F12=开发者工具(DevTools)
437+
部分快捷键已被占用:<code>F5</code>、<code>F12</code>、<code>Ctrl+F</code>、<code>F3</code>、<code>Shift+F3</code>
434438
</div>
435439
</a-form-item>
436440
<a-form-item label="启动时窗口状态" :label-col="labelCol" :wrapper-col="wrapperCol">

packages/gui/src/view/style/theme/dark.scss

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,4 +239,13 @@ $dark-input: #777; //输入框:背景色
239239
border-color: #8b2929;
240240
}
241241
}
242+
243+
.search-bar {
244+
div {
245+
color: #000;
246+
}
247+
span {
248+
color: #000;
249+
}
250+
}
242251
}

pnpm-lock.yaml

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)