Skip to content

Commit 5a57f2c

Browse files
authored
refactor: reorganize top menu bar structure (#1157)
close #1009
1 parent cd78fe9 commit 5a57f2c

File tree

12 files changed

+773
-246
lines changed

12 files changed

+773
-246
lines changed

apps/web/src/components/editor/editor-header/EditDropdown.vue

Lines changed: 177 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
<script setup lang="ts">
2-
import { ClipboardPasteIcon, Contact2Icon, CopyIcon, Redo2Icon, TableIcon, Undo2Icon, UploadCloudIcon } from 'lucide-vue-next'
2+
import type { EditorView } from '@codemirror/view'
3+
import { altSign, ctrlSign, shiftSign } from '@md/shared/configs'
4+
import { redoAction, undoAction } from '@md/shared/editor'
5+
import {
6+
ClipboardPaste,
7+
Copy,
8+
Redo2,
9+
Replace,
10+
Search,
11+
Undo2,
12+
WandSparkles,
13+
} from 'lucide-vue-next'
314
import { useEditorStore } from '@/stores/editor'
15+
import { usePostStore } from '@/stores/post'
416
import { useUIStore } from '@/stores/ui'
517
import { copyPlain } from '@/utils/clipboard'
618
@@ -13,9 +25,18 @@ const props = withDefaults(defineProps<{
1325
const { asSub } = toRefs(props)
1426
1527
const editorStore = useEditorStore()
28+
const postStore = usePostStore()
1629
const uiStore = useUIStore()
1730
18-
const { toggleShowInsertFormDialog, toggleShowUploadImgDialog, toggleShowInsertMpCardDialog } = uiStore
31+
const { editor } = storeToRefs(editorStore)
32+
33+
// Format content function
34+
async function formatContent() {
35+
const doc = await editorStore.formatContent()
36+
if (doc && postStore.currentPost) {
37+
postStore.updatePostContent(postStore.currentPostId, doc)
38+
}
39+
}
1940
2041
// Clipboard operations
2142
async function copyToClipboard() {
@@ -33,13 +54,56 @@ async function pasteFromClipboard() {
3354
}
3455
}
3556
36-
// Undo/Redo (handled by keyboard shortcuts)
57+
// Undo/Redo
3758
function undo() {
38-
console.log(`Undo should be handled by keyboard shortcuts`)
59+
if (!editor.value)
60+
return
61+
62+
try {
63+
const editorView = toRaw(editor.value) as EditorView
64+
undoAction(editorView)
65+
editorView.focus()
66+
}
67+
catch (error) {
68+
console.error('Undo failed:', error)
69+
}
3970
}
4071
4172
function redo() {
42-
console.log(`Redo should be handled by keyboard shortcuts`)
73+
if (!editor.value)
74+
return
75+
76+
try {
77+
const editorView = toRaw(editor.value) as EditorView
78+
redoAction(editorView)
79+
editorView.focus()
80+
}
81+
catch (error) {
82+
console.error('Redo failed:', error)
83+
}
84+
}
85+
86+
// Search/Replace - 使用项目已有的 SearchTab 组件
87+
function openSearch() {
88+
// 触发打开搜索面板
89+
if (editor.value) {
90+
const selection = editor.value.state.selection.main
91+
const selected = editor.value.state.doc.sliceString(selection.from, selection.to).trim()
92+
93+
// 使用 UI store 来触发搜索面板的打开
94+
uiStore.openSearchTab(selected)
95+
}
96+
}
97+
98+
function openReplace() {
99+
// 打开搜索面板并展开替换功能
100+
if (editor.value) {
101+
const selection = editor.value.state.selection.main
102+
const selected = editor.value.state.doc.sliceString(selection.from, selection.to).trim()
103+
104+
// 使用 UI store 来触发搜索面板的打开,并显示替换选项
105+
uiStore.openSearchTab(selected, true)
106+
}
43107
}
44108
</script>
45109

@@ -49,51 +113,76 @@ function redo() {
49113
<MenubarSubTrigger>
50114
编辑
51115
</MenubarSubTrigger>
52-
<MenubarSubContent>
116+
<MenubarSubContent class="w-60">
53117
<!-- 历史操作 -->
54118
<MenubarItem @click="undo()">
55-
<Undo2Icon class="mr-2 h-4 w-4" />
119+
<Undo2 class="mr-2 h-4 w-4" />
56120
撤销
121+
<MenubarShortcut>
122+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">{{ ctrlSign }}</kbd>
123+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">Z</kbd>
124+
</MenubarShortcut>
57125
</MenubarItem>
58126
<MenubarItem @click="redo()">
59-
<Redo2Icon class="mr-2 h-4 w-4" />
127+
<Redo2 class="mr-2 h-4 w-4" />
60128
重做
129+
<MenubarShortcut>
130+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">{{ ctrlSign }}</kbd>
131+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">Y</kbd>
132+
</MenubarShortcut>
61133
</MenubarItem>
62134

63135
<MenubarSeparator />
64136

65-
<!-- 插入操作子菜单 -->
66-
<MenubarSub>
67-
<MenubarSubTrigger>
68-
<TableIcon class="mr-2 h-4 w-4" />
69-
插入
70-
</MenubarSubTrigger>
71-
<MenubarSubContent>
72-
<MenubarItem @click="toggleShowUploadImgDialog()">
73-
<UploadCloudIcon class="mr-2 h-4 w-4" />
74-
插入图片
75-
</MenubarItem>
76-
<MenubarItem @click="toggleShowInsertFormDialog()">
77-
<TableIcon class="mr-2 h-4 w-4" />
78-
插入表格
79-
</MenubarItem>
80-
<MenubarItem @click="toggleShowInsertMpCardDialog()">
81-
<Contact2Icon class="mr-2 h-4 w-4" />
82-
插入公众号名片
83-
</MenubarItem>
84-
</MenubarSubContent>
85-
</MenubarSub>
86-
87-
<MenubarSeparator />
88-
89137
<!-- 剪贴板操作 -->
90138
<MenubarItem @click="copyToClipboard()">
91-
<CopyIcon class="mr-2 h-4 w-4" />
139+
<Copy class="mr-2 h-4 w-4" />
92140
复制
141+
<MenubarShortcut>
142+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">{{ ctrlSign }}</kbd>
143+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">C</kbd>
144+
</MenubarShortcut>
93145
</MenubarItem>
94146
<MenubarItem @click="pasteFromClipboard()">
95-
<ClipboardPasteIcon class="mr-2 h-4 w-4" />
147+
<ClipboardPaste class="mr-2 h-4 w-4" />
96148
粘贴
149+
<MenubarShortcut>
150+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">{{ ctrlSign }}</kbd>
151+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">V</kbd>
152+
</MenubarShortcut>
153+
</MenubarItem>
154+
155+
<MenubarSeparator />
156+
157+
<!-- 格式化文档 -->
158+
<MenubarItem @click="formatContent()">
159+
<WandSparkles class="mr-2 h-4 w-4" />
160+
格式化文档
161+
<MenubarShortcut>
162+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">{{ altSign }}</kbd>
163+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">{{ shiftSign }}</kbd>
164+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">F</kbd>
165+
</MenubarShortcut>
166+
</MenubarItem>
167+
168+
<MenubarSeparator />
169+
170+
<!-- 查找替换 -->
171+
<MenubarItem @click="openSearch()">
172+
<Search class="mr-2 h-4 w-4" />
173+
查找
174+
<MenubarShortcut>
175+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">{{ ctrlSign }}</kbd>
176+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">F</kbd>
177+
</MenubarShortcut>
178+
</MenubarItem>
179+
<MenubarItem @click="openReplace()">
180+
<Replace class="mr-2 h-4 w-4" />
181+
替换
182+
<MenubarShortcut>
183+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">{{ ctrlSign }}</kbd>
184+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">H</kbd>
185+
</MenubarShortcut>
97186
</MenubarItem>
98187
</MenubarSubContent>
99188
</MenubarSub>
@@ -103,51 +192,76 @@ function redo() {
103192
<MenubarTrigger>
104193
编辑
105194
</MenubarTrigger>
106-
<MenubarContent align="start">
195+
<MenubarContent class="w-60" align="start">
107196
<!-- 历史操作 -->
108197
<MenubarItem @click="undo()">
109-
<Undo2Icon class="mr-2 h-4 w-4" />
198+
<Undo2 class="mr-2 h-4 w-4" />
110199
撤销
200+
<MenubarShortcut>
201+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">{{ ctrlSign }}</kbd>
202+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">Z</kbd>
203+
</MenubarShortcut>
111204
</MenubarItem>
112205
<MenubarItem @click="redo()">
113-
<Redo2Icon class="mr-2 h-4 w-4" />
206+
<Redo2 class="mr-2 h-4 w-4" />
114207
重做
208+
<MenubarShortcut>
209+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">{{ ctrlSign }}</kbd>
210+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">Y</kbd>
211+
</MenubarShortcut>
115212
</MenubarItem>
116213

117214
<MenubarSeparator />
118215

119-
<!-- 插入操作子菜单 -->
120-
<MenubarSub>
121-
<MenubarSubTrigger>
122-
<TableIcon class="mr-2 h-4 w-4" />
123-
插入
124-
</MenubarSubTrigger>
125-
<MenubarSubContent>
126-
<MenubarItem @click="toggleShowUploadImgDialog()">
127-
<UploadCloudIcon class="mr-2 h-4 w-4" />
128-
插入图片
129-
</MenubarItem>
130-
<MenubarItem @click="toggleShowInsertFormDialog()">
131-
<TableIcon class="mr-2 h-4 w-4" />
132-
插入表格
133-
</MenubarItem>
134-
<MenubarItem @click="toggleShowInsertMpCardDialog()">
135-
<Contact2Icon class="mr-2 h-4 w-4" />
136-
插入公众号名片
137-
</MenubarItem>
138-
</MenubarSubContent>
139-
</MenubarSub>
140-
141-
<MenubarSeparator />
142-
143216
<!-- 剪贴板操作 -->
144217
<MenubarItem @click="copyToClipboard()">
145-
<CopyIcon class="mr-2 h-4 w-4" />
218+
<Copy class="mr-2 h-4 w-4" />
146219
复制
220+
<MenubarShortcut>
221+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">{{ ctrlSign }}</kbd>
222+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">C</kbd>
223+
</MenubarShortcut>
147224
</MenubarItem>
148225
<MenubarItem @click="pasteFromClipboard()">
149-
<ClipboardPasteIcon class="mr-2 h-4 w-4" />
226+
<ClipboardPaste class="mr-2 h-4 w-4" />
150227
粘贴
228+
<MenubarShortcut>
229+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">{{ ctrlSign }}</kbd>
230+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">V</kbd>
231+
</MenubarShortcut>
232+
</MenubarItem>
233+
234+
<MenubarSeparator />
235+
236+
<!-- 格式化文档 -->
237+
<MenubarItem @click="formatContent()">
238+
<WandSparkles class="mr-2 h-4 w-4" />
239+
格式化文档
240+
<MenubarShortcut>
241+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">{{ altSign }}</kbd>
242+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">{{ shiftSign }}</kbd>
243+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">F</kbd>
244+
</MenubarShortcut>
245+
</MenubarItem>
246+
247+
<MenubarSeparator />
248+
249+
<!-- 查找替换 -->
250+
<MenubarItem @click="openSearch()">
251+
<Search class="mr-2 h-4 w-4" />
252+
查找
253+
<MenubarShortcut>
254+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">{{ ctrlSign }}</kbd>
255+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">F</kbd>
256+
</MenubarShortcut>
257+
</MenubarItem>
258+
<MenubarItem @click="openReplace()">
259+
<Replace class="mr-2 h-4 w-4" />
260+
替换
261+
<MenubarShortcut>
262+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">{{ ctrlSign }}</kbd>
263+
<kbd class="mx-1 bg-gray-2 dark:bg-stone-9">H</kbd>
264+
</MenubarShortcut>
151265
</MenubarItem>
152266
</MenubarContent>
153267
</MenubarMenu>

apps/web/src/components/editor/editor-header/FileDropdown.vue

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup lang="ts">
2-
import { Download, FileCode, FileCog, FileText, Package, Upload } from 'lucide-vue-next'
2+
import { Download, FileCode, FileCog, FileText, FolderKanban, Package, Upload } from 'lucide-vue-next'
33
import { useEditorStore } from '@/stores/editor'
44
import { useExportStore } from '@/stores/export'
55
import { useUIStore } from '@/stores/ui'
@@ -18,7 +18,7 @@ const editorStore = useEditorStore()
1818
const exportStore = useExportStore()
1919
const uiStore = useUIStore()
2020
21-
const { isDark, isEditOnLeft, isOpenPostSlider } = storeToRefs(uiStore)
21+
const { isOpenPostSlider } = storeToRefs(uiStore)
2222
const { toggleShowTemplateDialog } = uiStore
2323
2424
const importMarkdownContent = useImportMarkdownContent()
@@ -112,24 +112,19 @@ function exportEditorContent2PDF() {
112112
模板管理
113113
</MenubarItem>
114114

115+
<!-- 内容管理 -->
116+
<MenubarItem @click="isOpenPostSlider = !isOpenPostSlider">
117+
<FolderKanban class="mr-2 size-4" />
118+
内容管理
119+
</MenubarItem>
120+
121+
<MenubarSeparator />
122+
115123
<!-- 项目配置 -->
116124
<MenubarItem @click="openEditorStateDialog()">
117125
<FileCog class="mr-2 size-4" />
118126
项目配置
119127
</MenubarItem>
120-
121-
<MenubarSeparator />
122-
123-
<!-- 视图设置 -->
124-
<MenubarCheckboxItem v-model:checked="isDark">
125-
深色模式
126-
</MenubarCheckboxItem>
127-
<MenubarCheckboxItem v-model:checked="isEditOnLeft">
128-
左侧编辑
129-
</MenubarCheckboxItem>
130-
<MenubarCheckboxItem v-model:checked="isOpenPostSlider">
131-
内容管理
132-
</MenubarCheckboxItem>
133128
</MenubarSubContent>
134129
</MenubarSub>
135130

@@ -191,24 +186,19 @@ function exportEditorContent2PDF() {
191186
模板管理
192187
</MenubarItem>
193188

189+
<!-- 内容管理 -->
190+
<MenubarItem @click="isOpenPostSlider = !isOpenPostSlider">
191+
<FolderKanban class="mr-2 size-4" />
192+
内容管理
193+
</MenubarItem>
194+
195+
<MenubarSeparator />
196+
194197
<!-- 项目配置 -->
195198
<MenubarItem @click="openEditorStateDialog()">
196199
<FileCog class="mr-2 size-4" />
197200
项目配置
198201
</MenubarItem>
199-
200-
<MenubarSeparator />
201-
202-
<!-- 视图设置 -->
203-
<MenubarCheckboxItem v-model:checked="isDark">
204-
深色模式
205-
</MenubarCheckboxItem>
206-
<MenubarCheckboxItem v-model:checked="isEditOnLeft">
207-
左侧编辑
208-
</MenubarCheckboxItem>
209-
<MenubarCheckboxItem v-model:checked="isOpenPostSlider">
210-
内容管理
211-
</MenubarCheckboxItem>
212202
</MenubarContent>
213203
</MenubarMenu>
214204
</template>

0 commit comments

Comments
 (0)