147 lines
3.7 KiB
Vue
147 lines
3.7 KiB
Vue
<!-- src/components/RichTextEditor.vue -->
|
|
<template>
|
|
<div class="editor-wrapper">
|
|
<!-- 工具栏 -->
|
|
<div v-if="editor" class="toolbar">
|
|
<button @click="editor.chain().focus().toggleBold().run()"
|
|
:class="{ 'is-active': editor.isActive('bold') }">
|
|
<strong>B</strong>
|
|
</button>
|
|
<button @click="editor.chain().focus().toggleItalic().run()"
|
|
:class="{ 'is-active': editor.isActive('italic') }">
|
|
<em>I</em>
|
|
</button>
|
|
<button @click="editor.chain().focus().toggleHeading({ level: 2 }).run()"
|
|
:class="{ 'is-active': editor.isActive('heading') }">
|
|
H2
|
|
</button>
|
|
</div>
|
|
<el-scrollbar height="600px">
|
|
<!-- 编辑器主体 -->
|
|
<editor-content :editor="editor" class="editor-content" />
|
|
</el-scrollbar>
|
|
|
|
|
|
<!-- 操作按钮 -->
|
|
<div class="actions">
|
|
<button @click="loadContent" class="btn-load">加载文件</button>
|
|
<button @click="saveContent" class="btn-save">保存文件</button>
|
|
</div>
|
|
|
|
<!-- 状态提示 -->
|
|
<div v-if="statusMessage" class="status">
|
|
{{ statusMessage }}
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { EditorContent, useEditor } from '@tiptap/vue-3'
|
|
import StarterKit from '@tiptap/starter-kit'
|
|
import axios from 'axios'
|
|
import { ref } from 'vue'
|
|
|
|
const statusMessage = ref('')
|
|
|
|
// 初始化编辑器
|
|
const editor = useEditor({
|
|
content: '',
|
|
extensions: [
|
|
StarterKit.configure({
|
|
heading: {
|
|
levels: [2, 3],
|
|
},
|
|
}),
|
|
],
|
|
})
|
|
|
|
// 加载文件内容
|
|
const loadContent = async () => {
|
|
try {
|
|
// const response = await axios.get('/api/files', {
|
|
// params: { filePath: 'demo.txt' }
|
|
// })
|
|
const data = "<p>124535</p><p>4554</p><p>4545ljgljk</p><p><strong>lk'k;'k;'l;k'</strong></p><h2><strong><em>;l'kl;'kl;'</em></strong></h2><h2><strong><em>;'kl;';kl'kl;'l;k'k;l'k';lk';';k'l;'k;'kl;</em></strong></h2>"
|
|
editor.value.commands.setContent(data)
|
|
// statusMessage.value = '内容加载成功'
|
|
// setTimeout(() => statusMessage.value = '', 2000)
|
|
} catch (error) {
|
|
statusMessage.value = `加载失败: ${error.response?.data || error.message}`
|
|
}
|
|
}
|
|
|
|
// 保存文件内容
|
|
const saveContent = async () => {
|
|
try {
|
|
const content = editor.value.getHTML()
|
|
await axios.post('/api/files', {
|
|
filePath: 'demo.txt',
|
|
content: content
|
|
})
|
|
statusMessage.value = '保存成功'
|
|
setTimeout(() => statusMessage.value = '', 2000)
|
|
} catch (error) {
|
|
statusMessage.value = `保存失败: ${error.response?.data || error.message}`
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.editor-wrapper {
|
|
max-width: 100%;
|
|
margin: 20px auto;
|
|
border: 1px solid #ddd;
|
|
border-radius: 8px;
|
|
padding: 20px;
|
|
}
|
|
|
|
.toolbar {
|
|
margin-bottom: 10px;
|
|
padding: 8px;
|
|
background: #f5f5f5;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.toolbar button {
|
|
margin-right: 8px;
|
|
padding: 6px 12px;
|
|
border: 1px solid #ccc;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
background: white;
|
|
}
|
|
|
|
.toolbar button.is-active {
|
|
background: #007bff;
|
|
color: white;
|
|
border-color: #007bff;
|
|
}
|
|
|
|
.editor-content {
|
|
min-height: 600px;
|
|
padding: 15px;
|
|
border: 1px solid #eee;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.actions {
|
|
margin-top: 20px;
|
|
text-align: right;
|
|
}
|
|
|
|
.btn-save {
|
|
background: #28a745;
|
|
color: white;
|
|
}
|
|
|
|
.btn-load {
|
|
background: #17a2b8;
|
|
color: white;
|
|
}
|
|
|
|
.status {
|
|
margin-top: 10px;
|
|
color: #666;
|
|
font-size: 0.9em;
|
|
}
|
|
</style> |