feat(editor): 为编辑器添加工具栏组件

- 新增 EditorToolbar 组件,提供标题、文本样式、引用、代码、链接和列表等常用格式操作按钮
- 在 LivePreviewEditor 中集成工具栏,并调整编辑器样式以适配工具栏布局
This commit is contained in:
cfq 2026-01-26 18:38:44 +08:00
parent d5d594fb7f
commit 3d31989d4b
2 changed files with 88 additions and 1 deletions

View File

@ -0,0 +1,85 @@
<template>
<div class="editor-toolbar">
<a-space :size="4">
<!-- 标题 -->
<a-dropdown :trigger="['click']">
<a-button type="text" size="small" title="标题">
<template #icon><span style="font-weight: bold; font-size: 14px;">H</span></template>
</a-button>
<template #overlay>
<a-menu @click="({ key }) => triggerAction('heading', key)">
<a-menu-item :key="1"><span style="font-size: 1.6em; font-weight: bold;">H1 标题</span></a-menu-item>
<a-menu-item :key="2"><span style="font-size: 1.4em; font-weight: bold;">H2 标题</span></a-menu-item>
<a-menu-item :key="3"><span style="font-size: 1.2em; font-weight: bold;">H3 标题</span></a-menu-item>
<a-menu-item :key="4"><span style="font-size: 1.1em; font-weight: bold;">H4 标题</span></a-menu-item>
<a-menu-item :key="5"><span style="font-size: 1em; font-weight: bold;">H5 标题</span></a-menu-item>
<a-menu-item :key="6"><span style="font-size: 0.9em; font-weight: bold; color: var(--text-color-secondary);">H6 标题</span></a-menu-item>
</a-menu>
</template>
</a-dropdown>
<a-divider type="vertical" style="height: 1.2em; background-color: var(--border-color);" />
<!-- 文本样式 -->
<a-button type="text" size="small" @click="triggerAction('bold')" title="加粗 (Ctrl+B)">
<template #icon><BoldOutlined /></template>
</a-button>
<a-button type="text" size="small" @click="triggerAction('italic')" title="斜体 (Ctrl+I)">
<template #icon><ItalicOutlined /></template>
</a-button>
<a-button type="text" size="small" @click="triggerAction('strike')" title="删除线">
<template #icon><StrikethroughOutlined /></template>
</a-button>
<a-divider type="vertical" style="height: 1.2em; background-color: var(--border-color);" />
<!-- 引用与代码 -->
<a-button type="text" size="small" @click="triggerAction('quote')" title="引用">
<template #icon><MessageOutlined /></template>
</a-button>
<a-button type="text" size="small" @click="triggerAction('inlineCode')" title="行内代码">
<template #icon><CodeOutlined /></template>
</a-button>
<a-button type="text" size="small" @click="triggerAction('link')" title="链接">
<template #icon><LinkOutlined /></template>
</a-button>
<a-divider type="vertical" style="height: 1.2em; background-color: var(--border-color);" />
<!-- 列表 -->
<a-button type="text" size="small" @click="triggerAction('unorderedList')" title="无序列表">
<template #icon><UnorderedListOutlined /></template>
</a-button>
<a-button type="text" size="small" @click="triggerAction('orderedList')" title="有序列表">
<template #icon><OrderedListOutlined /></template>
</a-button>
</a-space>
</div>
</template>
<script setup>
import {
BoldOutlined,
ItalicOutlined,
StrikethroughOutlined,
CodeOutlined,
MessageOutlined,
UnorderedListOutlined,
OrderedListOutlined,
LinkOutlined
} from '@ant-design/icons-vue';
import { useEditor } from '../composables/useEditor';
const { triggerAction } = useEditor();
</script>
<style scoped>
.editor-toolbar {
padding: 8px 16px;
border-bottom: 1px solid var(--border-color);
background-color: var(--card-background);
display: flex;
align-items: center;
flex-shrink: 0;
}
</style>

View File

@ -1,9 +1,10 @@
<template> <template>
<div class="live-editor"> <div class="live-editor">
<EditorToolbar />
<codemirror <codemirror
v-model="code" v-model="code"
placeholder="请输入 Markdown 内容..." placeholder="请输入 Markdown 内容..."
:style="{ height: '100%', fontSize: 'var(--editor-font-size)' }" :style="{ height: 'auto', flex: 1, fontSize: 'var(--editor-font-size)' }"
:autofocus="true" :autofocus="true"
:indent-with-tab="true" :indent-with-tab="true"
:tab-size="2" :tab-size="2"
@ -25,6 +26,7 @@ import { attachImagePaste } from '../codemirror/imagePaste'
import { useEditor } from '../composables/useEditor' import { useEditor } from '../composables/useEditor'
import { useMarkdownActions } from '../composables/useMarkdownActions' import { useMarkdownActions } from '../composables/useMarkdownActions'
import { useTabs } from '../composables/useTabs' import { useTabs } from '../composables/useTabs'
import EditorToolbar from './EditorToolbar.vue'
const props = defineProps({ const props = defineProps({
modelValue: String, modelValue: String,