简介
由于版本更新等问题,如果加载出的富文本为空白,很有可能是引用的问题,可以搜索此类问题在main.js里修改引用就可以了,程序的代码上是完全没有问题的。(2022-05-04更新)
查了好多资料忙了一天一夜,最后在群里靠别人解决了实时监测文本内容,百度太多坑了,资料不完整,说明不详细,没有完整代码,查得那叫一个辛苦,一个问题弄半天才明白,这篇文章我是从一个小白看文章的角度来写的,希望能给使用Tinymce这个富文本的小伙们一些帮助,但是希望看完自行去思考一些问题,不是过来复制粘贴就完了,看完对你有用,有赞点赞,没事评论评论,好歹以后遇到问题还能有个动力继续分享。
正文
下面这些是我使用的各种东西版本
@vue/cli 4.5.15
jdk 1.8
tinymce配置是将文件拷贝到本地使用的,我没有它的api,不知道的请自行百度安装
下面是我的项目结构目录,其实只用到了public/tinymce/langs/zh_CN.js(这个是tinymce富文本的中文包,需要请自己去下),src\components\tinymce\index_1.vue(这是构建tinymce的类),src\App.vue(这是调用进行在页面显示的类),src\main.js(全局配置些乱七八糟的东西),vue.config.js(也是配置的),介绍就到这里了。
如果遇到没有vue.config.js,自己安装cube-ui插件,不懂自己百度
首先,上传图片到自己服务器,需要用到的插件是axios,以及需要跨域,不懂什么是跨域自行百度,
安装好axios插件后,首先解决跨域问题
main.js里加上
import TinymceEditor from './components/tinymce';
import Axios from 'axios'
Vue.prototype.$axios = Axios //axios上传
Axios.defaults.baseURL = '/api' //跨域,将url转成/api
这是我vue.config.js的全部配置
const webpack = require('webpack')
module.exports = {
configureWebpack: {
plugins: [
//添加jquery的依赖
new webpack.ProvidePlugin({
$:"jquery",
jQuery:"jquery",
"windows.jQuery":"jquery"
})
]
},
devServer: {
//解决跨越问题配置
proxy: {
'/api': {
// 此处的写法,目的是为了 将 /api 替换成替换成我的服务器地址,地址自己写自己的,本机的也可以
target: 'http://***.***.***.***:8080/',
// 允许跨域
changeOrigin: true,
ws: true,
pathRewrite: {
'^/api': ''
}
}
},
},
css: {
loaderOptions: {
stylus: {
'resolve url': true,
'import': []
}
}
},
pluginOptions: {
'cube-ui': {
postCompile: true,
theme: false
}
}
}
不一定要全部复制,看你自己需要
跨域问题解决后进入index_1.vue里,这里全是关于tinymce富文本的 *** 作了
该有的注释都有了,代码也全部贴出来了,v-model这个可以百度看看他的意思
<template>
<div>
<!-- 当下面配置好直接使用<textarea>标签就能应用tinymce这个富文本了-->
<textarea :id= "tinymceId" v-model="tinymceHtml"></textarea>
</div>
</template>
<script>
import tinymce from 'tinymce'
import Editor from '@tinymce/tinymce-vue'
import 'tinymce/themes/silver'
import 'tinymce/plugins/image'// 插入上传图片插件
import 'tinymce/plugins/media'// 插入视频插件
import 'tinymce/plugins/table'// 插入表格插件
import 'tinymce/plugins/link' //超链接插件
import 'tinymce/plugins/code' //代码块插件
import 'tinymce/plugins/lists'// 列表插件
import 'tinymce/plugins/contextmenu' //右键菜单插件
import 'tinymce/plugins/wordcount' // 字数统计插件
import 'tinymce/plugins/colorpicker' //选择颜色插件
import 'tinymce/plugins/textcolor' //文本颜色插件
import 'tinymce/plugins/fullscreen' //全屏
import 'tinymce/plugins/help'
import 'tinymce/plugins/charmap'
import 'tinymce/plugins/paste'
import 'tinymce/plugins/hr'
import 'tinymce/plugins/searchreplace'
import 'tinymce/plugins/insertdatetime'
import 'tinymce/plugins/toc'
import 'tinymce/plugins/codesample'
export default {
name: 'tinymce',
components: {Editor},
//props:['value'], //下面methods里我配置了value,用来解决一些问题,不明白就不用管
data () {
let ide = Date.now()
return {
tinymceId: ide,
tinymceHtml:'',
DefaultInit: {
//这些路径自己放哪就找哪
language_url: '/tinymce/langs/zh_CN.js', //导入语言文件
language: "zh_CN",//语言设置
skin_url: '/tinymce/skins/ui/oxide',//主题样式
content_css: `/tinymce/skins/content/default/content.css`,
font_formats: "微软雅黑='微软雅黑';宋体='宋体';黑体='黑体';仿宋='仿宋';楷体='楷体';隶书='隶书';幼圆='幼圆';Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings",
plugin_preview_width: 375, // 预览宽度
plugin_preview_height: 100,
lineheight_val: "1 1.1 1.2 1.3 1.35 1.4 1.5 1.55 1.6 1.75 1.8 1.9 1.95 2 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 3 3.1 3.2 3.3 3.4 4 5",
fontsize_formats: "8pt 10pt 11pt 12pt 13pt 14pt 15pt 16pt 17pt 18pt 24pt 36pt",
height: 500, //高度
// menubar: false,// 隐藏最上方menu菜单
toolbar: true,//false禁用工具栏(隐藏工具栏)
browser_spellcheck: true, // 拼写检查
branding: false, // 去水印
statusbar: false, // 隐藏编辑器底部的状态栏
elementpath: false, //禁用下角的当前标签路径
paste_data_images: true, // 允许粘贴图像
powerpaste_word_import: 'merge', //从word粘贴过来的插件,也不知道有没有用,毕竟是本地的
//设置tinymce各种插件的显示
toolbar: 'fontselect | bold italic underline strikethrough | link unlink image | undo redo | fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist | outdent indent blockquote | code | removeformat',
// tinymce 富文本编译器的扩展插件
plugins:'link lists image code table wordcount media fullscreen preview paste contextmenu textcolor',
}
}
},
mounted () {
this.init()
},
methods: {
getTinymecHtml(){
return this.tinymceHtml
},
init () {
const self = this
window.tinymce.init({
// 默认配置
...this.DefaultInit,
// 'value': (editor) => {
// // 在插入位置插入内容, 光标会被移至右侧
// editor.setContent('');
// editor.insertContent(this.value);
// },
//监听富文本内容
setup: function(editor) {
editor.on('input change undo redo execCommand KeyUp', function(e) {
self.$emit('input', editor.getContent()); //将富文本内容发送到父类App.vue里,这个input一会App.cue是要在控件里@input来使用的
console.log(editor.getContent())
// if(this.flag){
// editor.setContent(editor.getContent);
// }
// this.flag=true
})
},
// 图片上传
images_upload_handler: function (blobInfo, success, failure){
//有图片上传请用这个FormData,当然这个也能添加字符之类的,只需要formData.append(name,object)就可以了,如果有更好的请自己搞去
let formData = new FormData()
console.log(blobInfo.filename())
formData.append('img',blobInfo.blob()) //记住这个 name:'img',一会服务器端代码里需要
let configs = { // 上传文件 请求头要设置成下面这样
headers:{'Content-Type':'multipart/form-data'} //给我写死,别作死,能复制就复制
};
self.$axios.post('/fileUpload/uploadImage/',formData,configs) //因为在vue.config.js和main.js里配置了,所以这里面的路径应该是 我的服务器地址/fileUpload/uploadImage/,其实/fileUpload/uploadImage/这个路径是和服务器里的地址对应,可以随意修改
.then(response =>{ //从服务器返回数据的回调
console.log(response.data['path'])
if(response.data['status']==1){ //这个status是服务器代码里写的名称
success(response.data['path'])
console.log("成功了")
}else{
console.log("失败了")
failure('上传失败!')
}
})
},
// 挂载的DOM对象
selector: `#${this.tinymceId}`,
})
}
}
}
</script>
接下来要在App.vue里调用
<template>
<div id="app">
<div id="nav">
<!-- 标签名就是script里impor里自己起的名字,@input就是index里起的那个名字-->
<TinymceEditor @input="datasss"/>
<!-- 我这里用来实时显示文本内容的-->
<p id="aaa" v-html="this.texts"></p>
</div>
</div>
</template>
<style>
</style>
<script>
import TinymceEditor from "./components/tinymce/index_1.vue" //导入的路径
export default {
components: {TinymceEditor}, //别少这句
data(){
return {
texts:""
}
},
return:{
},
methods:{
//这里实现@input的方法
datasss(e){
this.texts=e
}
}
}
</script>
到这里,已经可以显示出我们的tinymce富文本了,然后是上传图片的 *** 作
当选择好自己的图片时,会跳到这个界面
点击保存就可以往服务器发送图片了,但是其实也可以直接拖照片进文本框里,但是不可以选择宽高,还得自己调,可以自己写拖入d出窗口设置宽高的代码,由于现在服务器代码还没写呢,当然传不了,哈哈哈,接下来是服务器的代码,先上成功效果图
服务器端用的是springboot,老样子,先上目录结构
需要的几个类src\main\java\com\example\demo\config\CrosConfig.java(//解决跨域问题),src\main\java\com\example\demo\controller\ImageController.java(接收从客户端发送来的图片并处理),src\main\java\com\example\demo\DemoApplication.java(启动类,配置一些内容),
src\main\java\com\example\demo\FileUploadConfig.java(解决上传图片找不到图片问题),
src\main\resources\application.properties(配置文件)
这是application.properties的配置,自己修改
spring.application.name=image_service
server.port=8080
server.tomcat.uri-encoding=utf-8
#单次上传单个上传文件大小
pring.servlet.multipart.max-file-size = 100MB
#单次上传总文件大小
spring.servlet.multipart.max-request-size=1000MB
#数据库相关配置
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/homework
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.max-idle=10
spring.datasource.max-wait=10000
spring.datasource.min-idle=5
spring.datasource.initial-size=5
#session生命周期
server.servlet.session.timeout=30m
FileUploadConfig.java(解决上传图片找不到图片问题)
package com.example.demo;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class FileUploadConfig implements WebMvcConfigurer {
//解决上传图片找不到图片问题
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//获取文件的真实路径
String path = System.getProperty("user.dir")+"\src\main\resources\image\";
registry.addResourceHandler("/image/**").addResourceLocations("file:"+path);
}
}
CrosConfig.java(//解决跨域问题)
package com.example.demo.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
//解决跨域问题
@Configuration
public class CrosConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
.allowCredentials(true)
.maxAge(3600)
.allowedHeaders("*");
}
}
ImageController.java(接收从客户端发送来的图片并处理)
package com.example.demo.controller;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.alibaba.fastjson.JSON;
@RestController
@Configuration
@RequestMapping("/fileUpload") //客户端里的/fileUpload/uploadImage/就是这么来的
public class ImageController {
private static final String imagePath = System.getProperty("user.dir")+"/src/main/resources/image/"; //图片保存路径,就是本项目下的image文件夹
@RequestMapping(value = "/uploadImage",method = RequestMethod.POST) //客户端里的/fileUpload/uploadImage/就是这么来的
public void uploadImage(@RequestParam("img") MultipartFile file,HttpServletRequest request, //这里的img对应客户端的名称
HttpServletResponse response) {
Map result = new HashMap();
try {
String fileName = file.getOriginalFilename(); //文件名
String path = imagePath + fileName;
System.out.println(fileName);
System.out.println(path);
File storeImage = new File(path);
if (!storeImage.exists()) {
storeImage.mkdirs(); //如果没有文件夹就创建文件夹
}
file.transferTo(storeImage); //保存文件到指定的文件夹
String url = "http://***.***.***.***:8080/image/"+fileName; //*这里填自己的服务器地址,返回文件夹下的图片路径
System.out.println(url);
result.put("status", "1");
result.put("msg", "上传成功");
result.put("fileName", fileName);
result.put("path", url);
} catch (Exception e) {
result.put("status", "0");
result.put("msg", "上传失败");
}
String json = JSON.toJSONString(result);
PrintWriter writer = null;
try {
response.setHeader("Content-type", "application/json;charset=UTF-8");
writer = response.getWriter();
writer.write(json); //将指定的文本json发送回客户端
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != writer) {
writer.close();
}
}
}
}
DemoApplication.java(启动类,配置一些内容)
package com.example.demo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.unit.DataSize;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.servlet.MultipartConfigElement;
@SpringBootApplication
@Configuration
@MapperScan(basePackages = "com.example.demo.mapper")
public class DemoApplication extends SpringBootServletInitializer{
/*public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
System.out.println(" ===项目启动成功===");
}*/
public static void main(String[] args) {
new SpringApplicationBuilder(DemoApplication.class).run(args);
System.out.println(" ===项目启动成功===");
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
// TODO Auto-generated method stub
return builder.sources(DemoApplication.class);
}
@Bean
public MultipartConfigElement multipartConfigElement() {
//配置单个和总文件单次上传大小
MultipartConfigFactory factory = new MultipartConfigFactory();
// 单个数据大小
factory.setMaxFileSize(DataSize.parse("100000KB")); // KB,MB
/// 总上传数据大小
factory.setMaxRequestSize(DataSize.parse("1000000KB"));
return factory.createMultipartConfig();
}
}
写累了,实在是写不动了,但是这里只是解决了图片上传的问题,还有文本实时获取其实已经在index_1.vue代码里了
//监听富文本内容
setup: function(editor) {
editor.on('input change undo redo execCommand KeyUp', function(e) {
self.$emit('input', editor.getContent()); //将富文本内容发送到父类App.vue里,这个input一会App.cue是要在控件里@input来使用的
console.log(editor.getContent())
// if(this.flag){
// editor.setContent(editor.getContent);
// }
// this.flag=true
})
},
就是那么一段,够简单吧,但是百度上资料少得苦逼,我吃了不少亏,这篇文章就到这了,真怕突然断电,白写那么多。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)