vue上传本地图片(vue3 使用tinymce编辑器实现单/多图片上传,附件上传,视频上传)
导读:安装: 我用的是tinymce最新版本v6 npm install tinymce -S npm install @tinymce/tinymce-vue -S...
安装:
我用的是tinymce最新版本v6 npm install tinymce -S npm install @tinymce/tinymce-vue -S2.安装语言包:Language Packages | Trusted Rich Text Editor | TinyMCE
3.在项目public文件夹下--新建tinymce文件夹,安装包解压在该文件夹下
封装组件TEditor.vue
<template> <editor v-model="myValue" :init="init"></editor> </template> <script setup lang="ts"> import { uploadImg } from "../api/module/new_news"; //JS部分 //在js中引入所需的主题和组件 import tinymce from "tinymce/tinymce"; import "tinymce/skins/content/default/content.css"; import Editor from "@tinymce/tinymce-vue"; import "tinymce/themes/silver"; import "tinymce/themes/silver/theme"; import "tinymce/icons/default"; //引入编辑器图标icon ,不引入则不显示对应图标 import "tinymce/models/dom"; // 这里是个坑 一定要引入 //在TinyMce.vue中接着引入相关插件 import "tinymce/icons/default/icons"; import "tinymce/plugins/image"; // 插入上传图片插件 import "tinymce/plugins/media"; // 插入视频插件 import "tinymce/plugins/table"; // 插入表格插件 import "tinymce/plugins/lists"; // 列表插件 import "tinymce/plugins/wordcount"; // 字数统计插件 import "tinymce/plugins/code"; // 源码 import "tinymce/plugins/fullscreen"; //全屏 import "tinymce/plugins/preview"; //预览 // import tinymce/plugins/paste; //粘贴插件 import "tinymce/plugins/pagebreak"; //插入分页符 import "tinymce/plugins/codesample"; import "tinymce/plugins/searchreplace"; import "tinymce/plugins/link"; import "tinymce/plugins/autosave"; import "tinymce/plugins/autolink"; import "tinymce/plugins/anchor"; import "/public/tinymce/plugins/axupimgs/plugin.js"; // / // import "tinymce/plugins/fullpage";autolink anchor //接下来定义编辑器所需要的插件数据 import { reactive, ref } from "vue"; import { onMounted, defineEmits, watch } from "vue"; // import axios from "axios"; import request from "@/utils/axios"; // import { updateImg } from "@/api/order/order"; const emits = defineEmits(["getContent"]); //这里我选择将数据定义在props里面 ,方便在不同的页面也可以配置出不同的编辑器 ,当然也可以直接在组件中直接定义 const props = defineProps({ value: { type: String, default: () => { return ""; }, }, baseUrl: { type: String, default: "", }, disabled: { type: Boolean, default: false, }, plugins: { type: [String, Array], // default: "lists image media table wordcount fullscreen", default: " wordcount table searchreplace preview pagebreak fullscreen codesample autosave autolink anchor autolink image media lists link code image axupimgs", }, toolbar: { type: [String, Array], default: " fontsize fontfamily bold italic lineheight underline alignleft aligncenter alignright alignjustify anchor | undo redo | formatselect | forecolor backcolor | bullist numlist outdent indent | lists link image axupimgs media table | removeformat | fullscreen|preview code codesample|searchreplace ", }, //必填 objId:{ type: Object, default: {}, } }); // watch(()=>props.objId,(id,old)=>{ // console.log(id,xinid) // id=newId // }) console.log(props.objId.newId,++++++++++++++) //用于接收外部传递进来的富文本 const myValue = ref(props.value); //定义一个对象 init初始化 const init = reactive({ selector: "textarea", language_url: "/cms/tinymce/langs/zh_CN.js", // 语言包的路径 ,具体路径看自己的项目 ,文档后面附上中文js文件 language: "zh_CN", //语言 //自动聚焦 auto_focus: true, skin_url: "tinymce/skins/ui/oxide", // skin路径 ,具体路径看自己的项目 height: 800, //编辑器高度 width: "100%", branding: false, //是否禁用“Powered by TinyMCE ” menubar: false, //顶部菜单栏显示 image_dimensions: false, //去除宽高属性 plugins: props.plugins, //这里的数据是在props里面就定义好了的 toolbar: props.toolbar, //这里的数据是在props里面就定义好了的 images_upload_url: "/news/picUpload", // paste_convert_word_fake_lists: true, // 插入word文档需要该属性 font_size_formats: "12px 14px 16px 18px 24px 36px 48px 56px 72px", font_family_formats: "微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif", line_height_formats: "1 1.2 1.4 1.6 2", paste_webkit_styles: "all", paste_merge_formats: true, nonbreaking_force_tab: false, paste_auto_cleanup_on_paste: false, file_picker_types: "file image media", content_css: "tinymce/skins/content/default/content.css", //以css文件方式自定义可编辑区域的css样式 ,css文件需自己创建并引入 // 文件上传 file_picker_callback: (callback, value, meta) => { //,,m4v,avi,wmv,rmvb,mov,mpg,mpeg,webm let filetype = ".pdf, .txt, .zip, .rar, .7z, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .mp3, .mp4,.mkv, .avi,.wmv, .rmvb,.mov,.mpg,.mpeg,.webm, .jpg, .jpeg, .png, .gif"; //限制文件的上传类型 let inputElem = document.createElement("input"); //创建文件选择 inputElem.setAttribute("type", "file"); inputElem.setAttribute("accept", filetype); inputElem.click(); inputElem.onchange = () => { let upurl = ""; let file = inputElem.files[0]; //获取文件信息 const ph = import.meta.env.VITE_APP_IMAGE_URL; let params = new FormData(); if (file.type.slice(0, 5) == "video") { //判断文件类型 upurl = "/news/videoUpload"; params.append("file", file); params.append("id", props.objId.newId); } else if (file.type.slice(0, 5) == "image") { upurl = "/news/picUpload"; params.append("file", file); params.append("id", props.objId.newId); } else { upurl = "/news/attachUpload"; params.append("file", file); params.append("siteId", props.objId.siteId); params.append("newsId", props.objId.newId); params.append("attachDesc", ""); } if (file.type.slice(0, 5) == "image" && file.size / 1024 / 1024 > 2) { alert("上传失败 ,图片大小请控制在2M以内"); } else if ( file.type.slice(0, 5) == "video" && file.size / 1024 / 1024 > 500 ) { alert("上传失败 ,视频大小请控制在 500M 以内"); } else if (file.size / 1024 / 1024 > 10) { alert("上传失败 ,文件大小请控制在 10M 以内"); } else { let config = { headers: { "Content-Type": "multipart/form-data", }, }; request .post(upurl, params, config) .then((res) => { if (res.code == 200) { if (res.data.url) { callback(ph + res.data.url, { text: res.data.alt, title: res.data.name, }); } else { console.log(res); //上传成功 ,在回调函数里填入文件路径 callback(ph + res.data); } } else { alert("上传失败"); } }) .catch(() => { alert("上传出错 ,服务器开小差了呢"); }); } }; }, }); //监听外部传递进来的的数据变化 watch( () => props.value, () => { myValue.value = props.value; emits("getContent", myValue.value); } ); //监听富文本中的数据变化 watch( () => myValue.value, () => { emits("getContent", myValue.value); } ); //在onMounted中初始化编辑器 onMounted(() => { tinymce.init({}); }); </script>上传图片
上传附件
上传视频
最终效果如下图
批量上传图片实现
需要安装插件ax多图片批量上传插件 | TinyMCE中文文档中文手册
注意:安装完以后放到最开始新建的tinymce文件夹下
但是在文件里引入的时候会有问题
这里借鉴了在vuecli3.0+中使用tinymce及实现多图上传,文件上传 ,公式编辑等功能 - huihuihero - 博客园
为什么引入的是plugin.js是因为axupimgs中没有index.js文件,我试了一下写一个index.js 引入的时候还是会报错,具体的原因我也不大明白,(就是菜)..
不报错的引入方式,但是会有下面的提示要使用/tinymce/plugins/axupimgs/plugin.js这种方式,但是按照这个来就会报错
引入完以后最重要的就是去plugin.js文件修改一下路径哦!!!不然就会出现空白的情况
就是你们项目的地址
插件安装好修改完以后其他的就很好实现了,直接看代码吧
多个图片上传主要是基于单个图片上传的,所以方法都是一样的,这里最重要的就是单张图片和多个图片回调传的参数不一样.
最后看一下效果吧!
我也是第一次用这个编辑器,写的不好的地方,大佬们多指正
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!