vue3使用富文本编译器以及上传图片

无敌的宇宙
无敌的宇宙
擅长邻域:Java,HTML,JavaScript,MySQL,支付,退款,图片上传

分类: vue 专栏: vue 标签: vue3使用富文本编译器

2026-01-04 19:51:06 98浏览

vue3使用富文本编译器

大学宿舍管理系系统vue项目

安装

#!/bin/bash
# 安装Quill核心库
npm install quill -S
# 安装Vue3适配组件
npm install @vueup/vue-quill@alpha -S
# 安装主题样式
npm install --save-dev @vueup/vue-quill/dist/vue-quill.snow.css
# 清理缓存
npm cache clean --force
# 重新安装依赖
rm -rf node_modules
npm install
 <template>
    <el-card class="box-card">
        <template #header>
            <div class="card-header">
                <span>公告管理</span>
                <el-button  @click="addHandle( )" type="danger" style="float:right">添加</el-button>
            </div>
        </template>
        <div >
            <el-input v-model="query.title" placeholder="公告标题" class="inpsel"></el-input>
            <el-button @click="getPage" type="primary" >搜索</el-button>
            <el-button @click="resetHandel" type="primary">重置</el-button>
        </div>

        <el-table  :data="tabledata.list"     >

            <el-table-column prop="id" label="ID" width="100" align="center"></el-table-column>
            <el-table-column prop="title" label="名称"   align="center"  > <template #default="scope">

                <span  @click="editHandle(scope.row.$index,scope.row)" style="color: blue;">{{scope.row.title}}</span>
            </template>  </el-table-column>



            <el-table-column label="创建时间" prop="cts"  align="center" ></el-table-column>
            <el-table-column label="发布人" prop="realname"  align="center" ></el-table-column>

            <el-table-column label="操作" width="200" align="center" fixed="right">
                <template #default="scope">
                    <el-button @click="editHandle(scope.row.$index,scope.row)" type="primary" >编辑</el-button>
                    <el-button @click="delHandle(scope.row.$index,scope.row)" type="warning"  >删除</el-button>




                </template>
            </el-table-column>
        </el-table>
        <div class="pagination">
            <el-pagination
                    @size-change="handleSizeChange"
                    @current-change="handlePageChange"
                    :current-page="query.pageNo"
                    :page-sizes="[10,20,50,100, 200, 300, 400,500]"
                    :page-size="query.pageSize"
                    layout="total, sizes, prev, pager, next, jumper"
                    :total="tabledata.total">
            </el-pagination>

        </div>

    </el-card>


    <!-- 添加或者编辑弹出框 -->
    <el-dialog title="添加或编辑"   v-model="editVisible" :close-on-click-modal ="false"    >

        <el-form
                label-width="90px"
                :model="dataForm"
                :rules="dataFormRule"
                ref="dataFormRef"
        >

            <el-form-item label="公告标题" prop="title">
                <el-input v-model="dataForm.title"  ></el-input>
            </el-form-item>
            <el-form-item label="公告内容"  >
                <QuillEditor
                        ref="quillEditor"
                        v-model:content="editcont"
                        :options="editorOptions"
                        @ready="onEditorReady"
                        @change="onEditorChange"
                        content-type="html"
                        style="height: 500px;width:100%;"
                />
            </el-form-item>
        </el-form>
        <template #footer>
                    <span class="dialog-footer">
                          <el-button @click="editVisible = false">取 消</el-button>

                        <el-button type="primary" @click="submitForm">确 定</el-button>
                    </span>
        </template>

    </el-dialog>
</template>

<script setup>

    import {onMounted, ref,reactive} from 'vue'
    import {ElMessage} from 'element-plus'
    import axios from 'axios'
    import {useRouter} from 'vue-router'



    import { QuillEditor } from '@vueup/vue-quill';
    import '@vueup/vue-quill/dist/vue-quill.snow.css';
    import 'quill/dist/quill.core.css';
    import 'quill/dist/quill.bubble.css';
    const editorOptions = reactive({
        theme: 'snow',
        placeholder: '请输入内容...',
        modules: {
            toolbar: {
                container: [
                    ['bold', 'italic', 'underline', 'strike'],
                    [{ 'header': [1, 2, 3, 4, 5, 6, false] }],
                    [{ 'color': [] }, { 'background': [] }],
                    [{ 'font': [] }],
                    [{ 'align': [] }],
                    ['link', 'image', 'video'],
                    ['clean']
                ],
                handlers: {
                    'image': imageHandler
                }
            }
        }
    })

    // 自定义图片上传处理函数
    function imageHandler() {
        const input = document.createElement('input')
        input.setAttribute('type', 'file')
        input.setAttribute('accept', 'image/*')
        input.click()

        input.onchange = async () => {
            const file = input.files[0]
            if (!file) return

            // 创建FormData对象
            const formData = new FormData()
            formData.append('file', file)

            try {

                // 调用自定义图片上传接口
                const response = await fetch('/api/tip/updetail', {
                    method: 'POST',
                    body: formData
                })

                if (response.ok) {
                    const result = await response.json()
                    const imageUrl = result.obj // 假设返回的图片URL在url字段

                    // 获取当前光标位置
                    const editor = quillEditor.value.getQuill()
                    const range = editor.getSelection()

                    // 插入图片到编辑器
                    editor.insertEmbed(range.index, 'image', imageUrl)

                    // 移动光标到图片后
                    editor.setSelection(range.index + 1)
                } else {
                    console.error('图片上传失败:', response.statusText)
                    alert('图片上传失败,请重试')
                }
            } catch (error) {
                console.error('上传错误:', error)
                alert('上传过程中出现错误')
            }
        }
    }

    const onEditorReady = (quill) => {
        console.log('Editor ready!', quill);
    };

    const onEditorChange = ({ quill, html, text }) => {
        console.log('Content changed:', html,editcont.value);

    };


    const router = useRouter()

    const editVisible = ref( false);
    const editcont = ref( '');
    const quillEditor = ref(null)

    const dataForm = ref({
        title: '',
        context: '',
        id:'',
    })
    const dataFormRule = {
        title: [   { required: true, trigger: 'blur' ,  message: '不能为空' },  ],
    }
    const dataFormRef=ref(null)
    const query = ref({
        title: '',
        pageNo:1,
        pageSize:10,
    })
    const resetHandel = ( ) => {
        query.value.title = '';
        query.value.pageNo = 1;
        getPage();
    }
    const tabledata = ref({
        list: [],
        total:0,
    })

    const handleSizeChange = (e) => {
        query.value.pageSize=e;
        query.value.pageNo=1;
        getPage();
    }
    const handlePageChange = (e) => {
        query.value.pageNo=e;
        getPage();
    }
    const getPage = () => {
        axios({
            method: 'post',
            url: '/api/tip/page',
            params: query.value
        }).then(res => {
            if(res.status==1){
                tabledata.value.list=res.obj.list;
                tabledata.value.total=res.obj.total;
            }else{
                ElMessage.error(res.msg)
            }
        })
    }
    const delHandle = (index,row) => {
        axios({
            method: 'post',
            url: '/api/tip/del',
            params: {id:row.id}
        }).then(res => {
            if(res.status==1){
                ElMessage.success(res.msg)
               getPage();
            }else{
                ElMessage.error(res.msg)
            }
        })
    }


    const addHandle = ( ) => {
        editVisible.value=true;
        dataForm.value={};

        editcont.value='';
        quillEditor.value.getQuill().root.innerHTML = editcont.value

        dataForm.value.user_id=JSON.parse(localStorage.loginUser).id;
    }
    const editHandle= ( index,row) => {
        editVisible.value=true;
        dataForm.value.id=row.id;
        dataForm.value.title=row.title;
        dataForm.value.context=row.context;
        editcont.value=dataForm.value.context;

        quillEditor.value.getQuill().root.innerHTML = editcont.value//如果没有,则无法更新编译器内容

    }
    const submitForm = ( ) => {
        dataFormRef.value.validate((valid) => {
            if (valid) {
                dataForm.value.context=editcont.value;


                const formData = new FormData()
                if(dataForm.value.id) formData.append('id', dataForm.value.id)
                formData.append('title', dataForm.value.title)
                formData.append('context', dataForm.value.context)


                axios({
                    method: 'post',
                    url: '/api/tip/save',
                    data: formData
                }).then(res => {
                    if(res.status==1){
                        editVisible.value=false;
                        ElMessage.success(res.msg)
                         getPage();
                    }else{
                        ElMessage.error(res.msg)
                    }
                })
            }else{
                ElMessage.error("数据校验不通过")
            }
        })

    }
    const lander = ref({});
    const role = ref("");
    onMounted(() => {
        lander.value = JSON.parse(localStorage.loginUser);
        role.value = localStorage.role;
        if (role.value == 'college_manager') query.value.user_id = lander.value.id;
         getPage();
    })
</script>

<style scoped>
.inpsel{width: 320px;margin-right: 10px;}


</style>

好博客就要一起分享哦!分享海报

此处可发布评论

评论(0展开评论

暂无评论,快来写一下吧

展开评论

您可能感兴趣的博客

客服QQ 1913284695