feat(editor): 为编辑器添加工具栏组件
- 新增 EditorToolbar 组件,提供标题、文本样式、引用、代码、链接和列表等常用格式操作按钮 - 在 LivePreviewEditor 中集成工具栏,并调整编辑器样式以适配工具栏布局
This commit is contained in:
parent
d5d594fb7f
commit
3d31989d4b
|
|
@ -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>
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue