头两天用电脑摸鱼,突然领导从角落里走过来了,结果我紧急打开文档,但是文档程序启动需要时间。
领导撇了一眼我的屏幕,啥也没说就走了。
我发现除非我之前就将文档或者网页打开,调好到预定位置,否则如果有别人过来我很难反应过来。

即便是我反应过来了,电脑打开程序也是需要时间的。
所以我紧急开发了一款防摸鱼被发现神器 ------ 秒切(miao-qie)
需求
可以预先将 文档 / 网页 进行截图,上传到程序中,预设好展示截图的快捷键。
当触发快捷键 的时候,瞬间打开截图,并全屏窗口,看起来好像在浏览某个页面一样。
使用截图 规避快捷键打开程序需要的冷启动时间。
技术选型
需求看起来比较简单,实现起来还是存在一点门槛的。
首先考虑的是在浏览器中开发,但如果是浏览器插件的话,只能在浏览器中触发。
所以考虑开发一款PC端的程序,这样无论当前在干什么都能及时调出来。

前端使用 Vite + Vue3 + Ts 的老三样。
框架使用 Tauri 2.0 版本,打出来的包比较小,存储直接放在 localStore 里面。
实现代码
输入框捕获快捷键方法
js
const handleInputFocus = (row: Setting) => {
focusedRow.value = row
}
const handleInputBlur = () => {
focusedRow.value = null
}
const handleKeyDown = (event: KeyboardEvent) => {
if (!focusedRow.value) return
const modifiers: string[] = []
if (event.ctrlKey || event.metaKey) {
modifiers.push('Ctrl')
}
if (event.shiftKey) {
modifiers.push('Shift')
}
if (event.altKey) {
modifiers.push('Alt')
}
let key = event.key
if (key === ' ') {
key = 'Space'
} else if (key.length === 1 && key.match(/^[a-zA-Z]$/)) {
key = key.toUpperCase()
} else if (key.startsWith('Arrow')) {
key = key.replace('Arrow', '')
} else if (key === 'Backspace' || key === 'Delete') {
return
}
if (modifiers.length > 0 || (!['Control', 'Shift', 'Alt', 'Meta', 'Tab', 'Enter', 'Escape'].includes(key))) {
const shortcut = [...modifiers, key].join(' + ')
focusedRow.value.shortcut = shortcut
event.preventDefault()
}
}
if (typeof window !== 'undefined') {
window.addEventListener('keydown', handleKeyDown)
}
上传的图片直接转为Base64进行存储,这里基本不考虑分辨率的问题。
js
const handleImageBeforeUpload = (file: File, row: Setting) => {
// 图片转base64编码
const reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = (e) => {
if (e.target?.result) {
row.image = e.target.result as string
}
}
return true
}
快捷键触发创建一个全屏窗口 ,这里要注意,Tauri创建新窗口以后,webView渲染的 html页面 需要放在 public 下。
js
const createFullScreenWindow = async (imageBase64: string) => {
const appWindow = new Window('uniqueLabel', {
title: '图片',
fullscreen: true
});
appWindow.once('tauri://created', async function () {
console.log('Window窗口创建成功')
const webview = new Webview(appWindow, 'theUniqueLabel', {
url: '/image.html',
x: 0,
y: 0,
width: 1920,
height: 1080
});
webview.once('tauri://webview-created', async function () {
console.log('webview 创建成功')
});
webview.once('tauri://error', function (e) {
console.error('创建 webview 失败:', e)
});
await webview.listen("page-loaded", () => {
// 页面加载完成
webview.emit("image-base64", imageBase64);
});
// unlisten();
});
}
快捷键注册方法,批量注册快捷键。
这里还存在一点儿小问题,快捷键冲突的时候还没有想好怎么解决。
js
const registerShortcut = async () => {
// 注销所有快捷键
await unregisterAll()
// 批量注册快捷键
await Promise.allSettled(dataSrouce.value.map(async (item) => {
let shortcutArr = item.shortcut.trim().replace(/\s+/g, '').split('+')
// 判断出现Ctrl的话转为CommandOrControl
if (shortcutArr.includes('Ctrl')) {
shortcutArr = shortcutArr.map(item => item.replace('Ctrl', 'CommandOrControl'))
}
// 重组快捷键
let shortcut = shortcutArr.join('+')
console.log(shortcut)
await register(shortcut, () => {
console.log(`快捷键触发 ${shortcut} ✅`)
// 这里写你要执行的逻辑
createFullScreenWindow(item.image)
})
}))
}
总结
其实实现起来感觉非常简单,但是真正从零开始实现你才能踩到那些坑点。
Tauri 2.0 本身权限划分的非常细,所以权限记得给够。
快捷键的绑定操作、窗口创建关闭、托盘菜单等等Tauri都提供了相应的插件,但是开发的时候仍然觉得比较麻烦。
最最关键的,现在用AI开发 Tauri 2.0 的程序很多时候他仍然在使用 1.x 的代码,但是代码不兼容。