feature: 新增内容搜索功能,快捷键:`Ctrl + F`
parent
a6d2685e38
commit
67c7e39000
|
@ -34,6 +34,7 @@
|
|||
"request-progress": "^3.0.0",
|
||||
"sass": "^1.81.0",
|
||||
"sass-loader": "^16.0.3",
|
||||
"search-bar-vue2": "^1.0.0",
|
||||
"vue": "^2.7.16",
|
||||
"vue-json-editor-fix-cn": "^1.4.3",
|
||||
"vue-router": "^3.6.5"
|
||||
|
|
|
@ -298,28 +298,38 @@ function createWindow (startHideWindow, autoQuitIfError = true) {
|
|||
})
|
||||
|
||||
const shortcut = (event, input) => {
|
||||
// 按 F12,打开/关闭 开发者工具
|
||||
if (input.key === 'F12') {
|
||||
// 阻止默认的按键事件行为
|
||||
if (input.key === 'F12' && input.type === 'keyUp' && !input.control && !input.shift && !input.alt && !input.meta) {
|
||||
// 按 F12,打开/关闭 开发者工具
|
||||
event.preventDefault()
|
||||
// 切换开发者工具显示状态
|
||||
switchDevTools()
|
||||
// eslint-disable-next-line style/brace-style
|
||||
}
|
||||
// 按 F5,刷新页面
|
||||
else if (input.key === 'F5') {
|
||||
// 阻止默认的按键事件行为
|
||||
} else if (input.key === 'F5' && input.type === 'keyUp' && !input.control && !input.shift && !input.alt && !input.meta) {
|
||||
// 按 F5,刷新页面
|
||||
event.preventDefault()
|
||||
// 刷新页面
|
||||
win.webContents.reload()
|
||||
} else {
|
||||
// 全文检索框(SearchBar)相关快捷键
|
||||
if ((input.key === 'F' || input.key === 'f') && input.type === 'keyDown' && input.control && !input.shift && !input.alt && !input.meta) {
|
||||
// 按 Ctrl + F,显示或隐藏全文检索框(SearchBar)
|
||||
event.preventDefault()
|
||||
win.webContents.send('search-bar', { key: 'show-hide' })
|
||||
} else if (input.key === 'Escape' && input.type === 'keyUp' && !input.control && !input.shift && !input.alt && !input.meta) {
|
||||
// 按 ESC,隐藏全文检索框(SearchBar)
|
||||
event.preventDefault()
|
||||
win.webContents.send('search-bar', { key: 'hide' })
|
||||
} else if (input.key === 'F3' && input.type === 'keyDown' && !input.control && !input.shift && !input.alt && !input.meta) {
|
||||
// 按 F3,全文检索框(SearchBar)定位到下一个
|
||||
event.preventDefault()
|
||||
win.webContents.send('search-bar', { key: 'next' })
|
||||
} else if (input.key === 'F3' && input.type === 'keyDown' && !input.control && input.shift && !input.alt && !input.meta) {
|
||||
// 按 Shift + F3,全文检索框(SearchBar)定位到上一个
|
||||
event.preventDefault()
|
||||
win.webContents.send('search-bar', { key: 'previous' })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 监听键盘事件
|
||||
win.webContents.on('before-input-event', (event, input) => {
|
||||
if (input.type !== 'keyUp' || input.control || input.alt || input.shift || input.meta) {
|
||||
return
|
||||
}
|
||||
win.webContents.executeJavaScript('config')
|
||||
.then((value) => {
|
||||
console.info('window.config:', value, ', key:', input.key)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import antd from 'ant-design-vue'
|
||||
import Vue from 'vue'
|
||||
import VueRouter from 'vue-router'
|
||||
import SearchBar from 'search-bar-vue2'
|
||||
import { ipcRenderer } from 'electron'
|
||||
import view from './view'
|
||||
import App from './view/App.vue'
|
||||
|
@ -25,6 +26,7 @@ try {
|
|||
Vue.config.productionTip = false
|
||||
Vue.use(antd)
|
||||
Vue.use(VueRouter)
|
||||
Vue.use(SearchBar)
|
||||
Vue.component(DsContainer)
|
||||
// 3. 创建 router 实例,然后传 `routes` 配置
|
||||
// 你还可以传别的配置参数, 不过先这么简单着吧。
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<script>
|
||||
import { ipcRenderer } from 'electron'
|
||||
import createMenus from '@/view/router/menu'
|
||||
import zhCN from 'ant-design-vue/lib/locale-provider/zh_CN'
|
||||
import { colorTheme } from './composables/theme'
|
||||
|
@ -11,6 +12,9 @@ export default {
|
|||
info: {},
|
||||
menus: undefined,
|
||||
config: undefined,
|
||||
hideSearchBar: true,
|
||||
searchBarIsFocused: false,
|
||||
searchBarInputKeyupTimeout: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -35,13 +39,95 @@ export default {
|
|||
this.$api.info.get().then((ret) => {
|
||||
this.info = ret
|
||||
})
|
||||
|
||||
ipcRenderer.on('search-bar', (_, message) => {
|
||||
if (window.config.disableSearchBar) {
|
||||
this.hideSearchBar = true
|
||||
return
|
||||
}
|
||||
|
||||
// 如果不是显示/隐藏操作,并且还未显示检索框,先按显示操作处理
|
||||
if (!message.key.includes('hide') && this.hideSearchBar) {
|
||||
message = { key: 'show-hide' }
|
||||
}
|
||||
|
||||
try {
|
||||
if (message.key === 'show-hide') { // 显示/隐藏
|
||||
const hide = message.hideSearchBar != null ? message.hideSearchBar : !this.hideSearchBar
|
||||
|
||||
// 如果为隐藏操作,但SearchBar未隐藏且未获取焦点,则获取焦点
|
||||
if (hide && !this.hideSearchBar && !this.searchBarIsFocused) {
|
||||
this.doSearchBarInputFocus()
|
||||
return
|
||||
}
|
||||
|
||||
this.hideSearchBar = hide
|
||||
|
||||
// 显示后,获取输入框焦点
|
||||
if (!this.hideSearchBar) {
|
||||
this.doSearchBarInputFocus()
|
||||
} else {
|
||||
this.searchBarIsFocused = false
|
||||
}
|
||||
} else if (message.key === 'hide') { // 隐藏
|
||||
this.hideSearchBar = true
|
||||
this.searchBarIsFocused = false
|
||||
} else if (message.key === 'next') { // 下一项
|
||||
this.$refs.searchBar.next()
|
||||
} else if (message.key === 'previous') { // 上一项
|
||||
this.$refs.searchBar.previous()
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('操作SearchBar出现异常:', e)
|
||||
}
|
||||
|
||||
const input = this.getSearchBarInput()
|
||||
if (input) {
|
||||
input.addEventListener('focus', this.onSearchBarInputFocus)
|
||||
input.addEventListener('blur', this.onSearchBarInputBlur)
|
||||
input.addEventListener('keydown', this.onSearchBarInputKeydown)
|
||||
input.addEventListener('keyup', this.onSearchBarInputKeyup)
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
getSearchBarInput () {
|
||||
return this.$refs.searchBar.$el.querySelector('input[type=text]')
|
||||
},
|
||||
onSearchBarInputFocus () {
|
||||
this.searchBarIsFocused = true
|
||||
},
|
||||
onSearchBarInputBlur () {
|
||||
this.searchBarIsFocused = false
|
||||
},
|
||||
onSearchBarInputKeydown () {
|
||||
clearTimeout(this.searchBarInputKeyupTimeout)
|
||||
},
|
||||
onSearchBarInputKeyup (e) {
|
||||
if (!this.$refs.searchBar || e.key === 'Enter' || e.key === 'F3') {
|
||||
return
|
||||
}
|
||||
clearTimeout(this.searchBarInputKeyupTimeout)
|
||||
this.searchBarInputKeyupTimeout = setTimeout(() => {
|
||||
// 连续调用以下两个方法,为了获取检索结果中的第一项
|
||||
this.$refs.searchBar.next()
|
||||
this.$refs.searchBar.previous()
|
||||
}, 150)
|
||||
},
|
||||
doSearchBarInputFocus () {
|
||||
setTimeout(() => {
|
||||
const input = this.getSearchBarInput()
|
||||
if (input) {
|
||||
input.focus()
|
||||
}
|
||||
}, 100)
|
||||
},
|
||||
titleClick (item) {
|
||||
console.log('title click:', item)
|
||||
},
|
||||
menuClick (item) {
|
||||
console.log('menu click:', item)
|
||||
window.config.disableSearchBar = false
|
||||
this.$router.replace(item.path)
|
||||
},
|
||||
},
|
||||
|
@ -51,6 +137,13 @@ export default {
|
|||
<template>
|
||||
<a-config-provider :locale="locale">
|
||||
<div class="ds_layout" :class="themeClass">
|
||||
<SearchBar ref="searchBar"
|
||||
:root="'#document'"
|
||||
:highlightClass="'search-bar-highlight'"
|
||||
:selectedClass="'selected-highlight'"
|
||||
:hiden.sync="hideSearchBar"
|
||||
style="inset:auto auto 53px 210px; background-color:#ddd"
|
||||
/>
|
||||
<a-layout>
|
||||
<a-layout-sider :theme="theme">
|
||||
<div class="logo" />
|
||||
|
@ -78,7 +171,7 @@ export default {
|
|||
<a-layout>
|
||||
<!-- <a-layout-header>Header</a-layout-header> -->
|
||||
<a-layout-content>
|
||||
<router-view />
|
||||
<router-view id="document" />
|
||||
</a-layout-content>
|
||||
<a-layout-footer>
|
||||
<div class="footer">
|
||||
|
@ -139,4 +232,12 @@ body {
|
|||
border: 0;
|
||||
}
|
||||
}
|
||||
.search-bar-highlight {
|
||||
background-color: #ef0fff;
|
||||
color: #fdfdfd;
|
||||
|
||||
&.selected-highlight {
|
||||
background-color: #17a450;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -169,8 +169,8 @@ export default {
|
|||
shortcut += 'Meta + '
|
||||
}
|
||||
|
||||
// 如果以上按钮都没有按下,并且当前键不是F1~F4、F6~F11时,则直接返回(注:F5已经是刷新页面快捷键、F12已经是打开DevTools的快捷键了)
|
||||
if (shortcut === '' && !key.match(/^F([1-46-9]|1[01])$/g)) {
|
||||
// 如果以上按钮都没有按下,并且当前键不是F1、F2、F4、F6~F11时,则直接返回(注:F5已经是刷新页面快捷键、F12已经是打开DevTools的快捷键了)
|
||||
if (shortcut === '' && !key.match(/^F([1246-9]|1[01])$/g)) {
|
||||
this.config.app.showHideShortcut = '无'
|
||||
return
|
||||
}
|
||||
|
@ -178,6 +178,10 @@ export default {
|
|||
// 拼接键值
|
||||
shortcut += key
|
||||
|
||||
if (shortcut === 'Ctrl + F' || shortcut === 'Shift + F3') {
|
||||
shortcut = '无' // 如果是其他已被占用快捷键,则设置为 '无'
|
||||
}
|
||||
|
||||
this.config.app.showHideShortcut = shortcut
|
||||
},
|
||||
async applyBefore () {
|
||||
|
@ -430,7 +434,7 @@ export default {
|
|||
<a-form-item label="打开窗口快捷键" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-input v-model="config.app.showHideShortcut" @change="shortcutChange" @keydown="shortcutKeyDown" @keyup="shortcutKeyUp" />
|
||||
<div class="form-help">
|
||||
部分快捷键已被占用:F5=刷新页面,F12=开发者工具(DevTools)
|
||||
部分快捷键已被占用:<code>F5</code>、<code>F12</code>、<code>Ctrl+F</code>、<code>F3</code>、<code>Shift+F3</code>
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item label="启动时窗口状态" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
|
|
|
@ -239,4 +239,13 @@ $dark-input: #777; //输入框:背景色
|
|||
border-color: #8b2929;
|
||||
}
|
||||
}
|
||||
|
||||
.search-bar {
|
||||
div {
|
||||
color: #000;
|
||||
}
|
||||
span {
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,6 +108,9 @@ importers:
|
|||
sass-loader:
|
||||
specifier: ^16.0.3
|
||||
version: 16.0.3(sass@1.81.0)(webpack@5.96.1)
|
||||
search-bar-vue2:
|
||||
specifier: ^1.0.0
|
||||
version: 1.0.0(vue@2.7.16)
|
||||
vue:
|
||||
specifier: ^2.7.16
|
||||
version: 2.7.16
|
||||
|
@ -6011,6 +6014,11 @@ packages:
|
|||
resolution: {integrity: sha512-3A6sD0WYP7+QrjbfNA2FN3FsOaGGFoekCVgTyypy53gPxhbkCIjtO6YWgdrfM+n/8sI8JeXZOIxsHjMTNxQ4nQ==}
|
||||
engines: {node: ^14.0.0 || >=16.0.0}
|
||||
|
||||
search-bar-vue2@1.0.0:
|
||||
resolution: {integrity: sha512-e65f34kiWo/ub6fOsXGC7SU1A2HWyTUhQUn3AhZfO/f002XcCOaRghkWM0sADE8/OaL5MWHZ1sxDjzq2T9vWIQ==}
|
||||
peerDependencies:
|
||||
vue: ^2.6.14
|
||||
|
||||
select-hose@2.0.0:
|
||||
resolution: {integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==}
|
||||
|
||||
|
@ -13910,6 +13918,10 @@ snapshots:
|
|||
refa: 0.12.1
|
||||
regexp-ast-analysis: 0.7.1
|
||||
|
||||
search-bar-vue2@1.0.0(vue@2.7.16):
|
||||
dependencies:
|
||||
vue: 2.7.16
|
||||
|
||||
select-hose@2.0.0: {}
|
||||
|
||||
selfsigned@2.4.1:
|
||||
|
|
Loading…
Reference in New Issue