diff --git a/frontend/src/components/FileTabs.vue b/frontend/src/components/FileTabs.vue index b23089a1..2de25ae8 100644 --- a/frontend/src/components/FileTabs.vue +++ b/frontend/src/components/FileTabs.vue @@ -8,6 +8,7 @@ import Tabs from './Tabs.vue' import File from '../useful/file' import { defineComponent, onBeforeMount, onBeforeUnmount, ref, toRefs, watch } from 'vue' import { Components } from '../types' +import { isAction } from '../useful/shortcut' const blankUri = File.toUri(null) @@ -72,14 +73,14 @@ export default defineComponent({ } // 快捷键切换最近文档 - if (e.altKey && e.ctrlKey) { - if (e.key === 'ArrowLeft') { - const prev = findTab(-1) - prev && switchTab(prev) - } else if (e.key === 'ArrowRight') { - const next = findTab(1) - next && switchTab(next) - } + if (isAction(e, 'file-tabs-switch-left')) { + const prev = findTab(-1) + prev && switchTab(prev) + } + + if (isAction(e, 'file-tabs-switch-right')) { + const next = findTab(1) + next && switchTab(next) } } diff --git a/frontend/src/components/Filter.vue b/frontend/src/components/Filter.vue index efccceac..7def0b7f 100644 --- a/frontend/src/components/Filter.vue +++ b/frontend/src/components/Filter.vue @@ -8,6 +8,7 @@ import { useStore } from 'vuex' import { computed, defineComponent, onMounted, onUnmounted, ref, toRef } from 'vue' import { encodeMarkdownLink } from '../useful/utils' +import { getCurrentAction } from '../useful/shortcut' import { useBus } from '../useful/bus' import XMask from './Mask.vue' import QuickOpen from './QuickOpen.vue' @@ -24,26 +25,29 @@ export default defineComponent({ const withMarked = ref(true) function keydownHandler (e: KeyboardEvent) { - if (e.key === 'i' && e.ctrlKey && e.altKey) { - callback.value = (f: any) => { - const file = currentFile.value - if (file) { - const relativePath = f.path.replace(file.path.substr(0, file.path.lastIndexOf('/')), '.') - bus.emit('editor-insert-value', `[${f.name.replace(/\.[^.]+$/, '')}](${encodeMarkdownLink(relativePath)})`) + switch (getCurrentAction(e)) { + case 'insert-document': + callback.value = (f: any) => { + const file = currentFile.value + if (file) { + const relativePath = f.path.replace(file.path.substr(0, file.path.lastIndexOf('/')), '.') + bus.emit('editor-insert-value', `[${f.name.replace(/\.[^.]+$/, '')}](${encodeMarkdownLink(relativePath)})`) + } + callback.value = null } - callback.value = null - } - withMarked.value = false - e.preventDefault() - e.stopPropagation() - } else if (e.key === 'p' && e.ctrlKey) { - callback.value = (f: any) => { - store.commit('setCurrentFile', f) - callback.value = null - } - withMarked.value = true - e.preventDefault() - e.stopPropagation() + withMarked.value = false + e.preventDefault() + e.stopPropagation() + break + case 'show-quick-open': + callback.value = (f: any) => { + store.commit('setCurrentFile', f) + callback.value = null + } + withMarked.value = true + e.preventDefault() + e.stopPropagation() + break } } diff --git a/frontend/src/components/MonacoEditor.vue b/frontend/src/components/MonacoEditor.vue index 8aa00338..ae3d492d 100644 --- a/frontend/src/components/MonacoEditor.vue +++ b/frontend/src/components/MonacoEditor.vue @@ -12,7 +12,7 @@ import env from '../useful/env' const models: {[key: string]: monaco.editor.ITextModel} = {} -const keys: {[key: string]: boolean} = {} +let keys: {[key: string]: boolean} = {} export default defineComponent({ name: 'monaco-editor', @@ -80,17 +80,17 @@ export default defineComponent({ const KM = getMonaco().KeyMod const KC = getMonaco().KeyCode - getEditor().addCommand(KM.CtrlCmd | KM.Alt | KC.KEY_F, addAttachment) + getEditor().addCommand(KM.Shift | KM.Alt | KC.KEY_F, addAttachment) - getEditor().addCommand(KM.CtrlCmd | KM.Alt | KC.KEY_D, () => { + getEditor().addCommand(KM.Shift | KM.Alt | KC.KEY_D, () => { insert(dayjs().format('YYYY-MM-DD')) }) - getEditor().addCommand(KM.CtrlCmd | KM.Alt | KC.KEY_T, () => { + getEditor().addCommand(KM.Shift | KM.Alt | KC.KEY_T, () => { insert(dayjs().format('HH:mm:ss')) }) - getEditor().addCommand(KM.CtrlCmd | KM.Alt | KC.KEY_R, () => { + getEditor().addCommand(KM.Shift | KM.Alt | KC.KEY_R, () => { emit('xterm-run', getEditor().getModel()!!.getValueInRange(getEditor().getSelection()!!)) }) @@ -156,7 +156,7 @@ export default defineComponent({ function paste (e: ClipboardEvent) { if (getEditor().hasTextFocus()) { const items = e.clipboardData!!.items - if (keys.m || keys.M) { // 粘贴 HTML 转为 markdown + if (keys.d || keys.D) { // 粘贴 HTML 转为 markdown for (let i = 0; i < items.length; i++) { if (items[i].type.match(/^text\/html$/i)) { items[i].getAsString(str => { @@ -172,7 +172,7 @@ export default defineComponent({ for (let i = 0; i < items.length; i++) { const fileType = items[i].type if (fileType.match(/^image\/(png|jpg|jpeg|gif)$/i)) { - const asBase64 = keys.b || keys.B // Ctrl + v 粘贴的同时 按下了 B 键,就粘贴 base64 图像 + const asBase64 = keys.b || keys.B // 粘贴的同时 按下了 B 键,就粘贴 base64 图像 emit('paste-img', items[i].getAsFile(), asBase64) } } @@ -243,7 +243,7 @@ export default defineComponent({ if (e.type === 'keydown') { keys[e.key] = true } else { - keys[e.key] = false + keys = {} } } diff --git a/frontend/src/components/Preview.vue b/frontend/src/components/Preview.vue index 2e401335..fc019311 100644 --- a/frontend/src/components/Preview.vue +++ b/frontend/src/components/Preview.vue @@ -71,6 +71,8 @@ import 'highlight.js/styles/atom-one-dark.css' import 'katex/dist/katex.min.css' import { useBus } from '../useful/bus' import { useToast } from '../useful/toast' +import { hasCtrlCmd, isAction } from '../useful/shortcut' + HighlightLineNumber.addStyles() const markdown = Markdown({ @@ -311,7 +313,7 @@ export default defineComponent({ async function keydownHandler (e: KeyboardEvent) { // 转换所有外链图片到本地 - if (e.key === 'l' && e.ctrlKey && e.altKey) { + if (isAction(e, 'transform-img-link')) { e.preventDefault() e.stopPropagation() const result = [] @@ -420,14 +422,19 @@ export default defineComponent({ } // 复制标题链接 - if (['H1', 'H2', 'H3', 'H4', 'H5', 'H6'].indexOf(target.tagName) > -1 && target.id && e.ctrlKey) { + if (['H1', 'H2', 'H3', 'H4', 'H5', 'H6'].indexOf(target.tagName) > -1 && target.id && hasCtrlCmd(e)) { bus.emit('copy-text', encodeMarkdownLink(filePath.value) + '#' + encodeMarkdownLink(decodeURIComponent(target.id))) return preventEvent() } + // 复制内容 + if (target.classList.contains('copy-inner-text')) { + bus.emit('copy-text', target.innerText) + } + if (target.tagName === 'IMG') { const img = target as HTMLImageElement - if (e.ctrlKey && e.shiftKey) { // 转换外链图片到本地 + if (isAction(e, 'transform-img-link-by-click')) { // 转换外链图片到本地 const data = await transformImgOutLink(img) if (data) { bus.emit('tree-refresh') @@ -450,7 +457,7 @@ export default defineComponent({ return } - if (target.tagName === 'TD' && target.classList.contains('yank-td') && e.ctrlKey) { + if (target.tagName === 'TD' && target.classList.contains('yank-td') && hasCtrlCmd(e)) { const start = parseInt(target.dataset.sourceLine || '0') const end = parseInt(target.dataset.sourceLineEnd || '0') const td = target as HTMLTableDataCellElement diff --git a/frontend/src/components/StatusBar.vue b/frontend/src/components/StatusBar.vue index 2b5b651c..49325b31 100644 --- a/frontend/src/components/StatusBar.vue +++ b/frontend/src/components/StatusBar.vue @@ -9,11 +9,11 @@ 字符数:{{documentInfo.textLength}} 已选中:{{documentInfo.selectedLength}} -