yifengyide/src/library/customEditor.vue
2025-03-07 16:47:46 +08:00

207 lines
7.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="editor">
<!-- 这两个都是获取值的必要条件 v-model:content contentType="html" -->
<quill-editor
ref="editorRef"
v-model:content="content"
:options="options"
contentType="html"
></quill-editor>
</div>
</template>
<script setup lang="ts">
// 引入富文本编辑器与样式
import { Quill, QuillEditor } from '@vueup/vue-quill'
import '@vueup/vue-quill/dist/vue-quill.snow.css'
// 引入缩放图片的插件
import BlotFormatter from 'quill-blot-formatter'
Quill.register('modules/blotFormatter', BlotFormatter)
const content = ref('')
const editorRef = ref(null)
// 富文本配置
const options = ref({
theme: 'snow', // 使用snow主题
modules: {
// 富文本头部栏的功能配置
toolbar: {
container: [
['bold', 'italic', 'underline', 'strike'], // 加粗 斜体 下划线 删除线
[{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
[{ align: [] }], // 对齐方式
[{ size: ['small', false, 'large', 'huge'] }], // 字体大小
[{ font: [] }], // 字体种类
[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
[{ direction: 'ltl' }], // 文本方向
[{ direction: 'rtl' }], // 文本方向
[{ indent: '-1' }, { indent: '+1' }], // 缩进
[{ list: 'ordered' }, { list: 'bullet' }], // 有序、无序列表
[{ script: 'sub' }, { script: 'super' }], // 上标/下标
['blockquote', 'code-block'], // 引用 代码块
['clean'], // 清除文本格式
['link', 'image', 'video'], // 链接、图片、视频
],
handlers: {
image: imageHandler, // 点击图片触发事件
},
},
// 图片缩放
blotFormatter: {
// 可以在这里设置缩放样式
// overlay: {
// style: {
// border: '2px solid red',
// }
// },
toolbar: {
mainClassName: 'blot-formatter__toolbar'
}
}
}
})
// 如果方法报错把imageHandler 方法放到options的上面
// 处理富文本图片上传
const imageHandler = () => {
// 创建一个文件输入元素
const input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', 'image/*');
// 模拟点击,打开文件选择对话框
input.click();
// 当用户选择文件后触发的事件
input.onchange = async () => {
// 获取用户选择的文件
const file = input.files ? input.files[0] : null;
if (file) {
// 创建一个 FormData 对象,用于文件上传
const formData = new FormData();
formData.append('file', file);
try {
/**
* @todo 可以选中图片然后把file文件给后端后端给存到文件服务器然后返回一个线上地址
* 这里的abc替换成你的请求接口方法,也可以使用 axios 发送 POST 请求
* */
// todo
// 使用 axios 发送 POST 请求,将文件上传到服务器,这里的abc替换成你的请求接口方法
// 可以选中图片然后把file文件给后端后端给存到文件服务器然后返回一个线上地址
const res = await abc(formData);
// 确保获取到 Quill 编辑器实例
const quill = toRaw(editorRef.value).getQuill()
if (quill) {
// 获取当前光标位置
const range = quill.getSelection(true);
// 在当前光标位置插入上传的图片
quill.insertEmbed(range.index, 'image', res.data);
}
} catch (error) {
alert('图片上传失败')
}
}
};
}
// toolbar标题,划过富文本头部提示信息
const titleConfig = [
{ Choice: '.ql-insertMetric', title: '跳转配置' },
{ Choice: '.ql-bold', title: '加粗' },
{ Choice: '.ql-italic', title: '斜体' },
{ Choice: '.ql-underline', title: '下划线' },
{ Choice: '.ql-header', title: '段落格式' },
{ Choice: '.ql-strike', title: '删除线' },
{ Choice: '.ql-blockquote', title: '块引用' },
{ Choice: '.ql-code', title: '插入代码' },
{ Choice: '.ql-code-block', title: '插入代码段' },
{ Choice: '.ql-font', title: '字体' },
{ Choice: '.ql-size', title: '字体大小' },
{ Choice: '.ql-list[value="ordered"]', title: '编号列表' },
{ Choice: '.ql-list[value="bullet"]', title: '项目列表' },
{ Choice: '.ql-direction', title: '文本方向' },
{ Choice: '.ql-header[value="1"]', title: 'h1' },
{ Choice: '.ql-header[value="2"]', title: 'h2' },
{ Choice: '.ql-align', title: '对齐方式' },
{ Choice: '.ql-color', title: '字体颜色' },
{ Choice: '.ql-background', title: '背景颜色' },
{ Choice: '.ql-image', title: '图像' },
{ Choice: '.ql-video', title: '视频' },
{ Choice: '.ql-link', title: '添加链接' },
{ Choice: '.ql-formula', title: '插入公式' },
{ Choice: '.ql-clean', title: '清除字体格式' },
{ Choice: '.ql-script[value="sub"]', title: '下标' },
{ Choice: '.ql-script[value="super"]', title: '上标' },
{ Choice: '.ql-indent[value="-1"]', title: '向左缩进' },
{ Choice: '.ql-indent[value="+1"]', title: '向右缩进' },
{ Choice: '.ql-header .ql-picker-label', title: '标题大小' },
{ Choice: '.ql-header .ql-picker-item[data-value="1"]', title: '标题一' },
{ Choice: '.ql-header .ql-picker-item[data-value="2"]', title: '标题二' },
{ Choice: '.ql-header .ql-picker-item[data-value="3"]', title: '标题三' },
{ Choice: '.ql-header .ql-picker-item[data-value="4"]', title: '标题四' },
{ Choice: '.ql-header .ql-picker-item[data-value="5"]', title: '标题五' },
{ Choice: '.ql-header .ql-picker-item[data-value="6"]', title: '标题六' },
{ Choice: '.ql-header .ql-picker-item:last-child', title: '标准' },
{ Choice: '.ql-size .ql-picker-item[data-value="small"]', title: '小号' },
{ Choice: '.ql-size .ql-picker-item[data-value="large"]', title: '大号' },
{ Choice: '.ql-size .ql-picker-item[data-value="huge"]', title: '超大号' },
{ Choice: '.ql-size .ql-picker-item:nth-child(2)', title: '标准' },
{ Choice: '.ql-align .ql-picker-item:first-child', title: '居左对齐' },
{ Choice: '.ql-align .ql-picker-item[data-value="center"]', title: '居中对齐' },
{ Choice: '.ql-align .ql-picker-item[data-value="right"]', title: '居右对齐' },
{ Choice: '.ql-align .ql-picker-item[data-value="justify"]', title: '两端对齐' }
]
// 给富文本框工具栏加上鼠标悬浮中文提示
const initTitle = () => {
for (let item of titleConfig) {
// .editor 是富文本编辑器的类名
let tip = document.querySelector('.editor ' + item.Choice);
if (tip) {
tip.setAttribute('title', item.title);
}
}
}
// 自定义粘贴事件
const customPaste=(e)=>{
// 获取当前最新时间 改名啥的可以用
let newTime = new Date().getTime()
const clipboardData = e.clipboardData // 粘贴信息
const types = clipboardData.types // 当前文件类型
if (types.includes('Files')) {
e.preventDefault();
e.clipboardData.files.forEach(file=>{
// 在这里可以拿到粘贴后的图片与文件信息
// 在这里做操作
})
}
}
onMounted(()=>{
nextTick(()=>{
// 给富文本框工具栏加上鼠标悬浮中文提示
initTitle()
})
// 给富文本增加粘贴事件
editorRef.value.getQuill().root.addEventListener('customPaste', customPaste, false)
})
</script>
<style scoped lang="scss">
.editor{
width: 100%;
:deep(.ql-editor) {
min-height: 200px;
}
}
</style>