TinymceEditor.vue 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. <template>
  2. <div class="tinymce-editor">
  3. <Editor
  4. :id="tinymceId"
  5. :init="init"
  6. :disabled="disabled"
  7. v-model="myValue"
  8. @onClick="onClick"
  9. ></Editor>
  10. </div>
  11. </template>
  12. <script>
  13. // import axios from "axios";
  14. import tinymce from "tinymce/tinymce"; //tinymce默认hidden,不引入不显示
  15. import Editor from "@tinymce/tinymce-vue"; //编辑器引入
  16. import "tinymce/themes/silver/theme"; //编辑器主题
  17. // 引入编辑器插件(基本免费插件都在这儿了)
  18. import "tinymce/plugins/advlist"; //高级列表
  19. import "tinymce/plugins/autolink"; //自动链接
  20. import "tinymce/plugins/link"; //超链接
  21. import "tinymce/plugins/image"; //插入编辑图片
  22. import "tinymce/plugins/lists"; //列表插件
  23. import "tinymce/plugins/charmap"; //特殊字符
  24. import "tinymce/plugins/media"; //插入编辑媒体
  25. import "tinymce/plugins/wordcount"; // 字数统计
  26. // import Cookies from "js-cookie";
  27. // const OSS = require("ali-oss");
  28. const fonts = [
  29. "宋体=宋体",
  30. "微软雅黑=微软雅黑",
  31. "新宋体=新宋体",
  32. "黑体=黑体",
  33. "楷体=楷体",
  34. "隶书=隶书",
  35. "Courier New=courier new,courier",
  36. "AkrutiKndPadmini=Akpdmi-n",
  37. "Andale Mono=andale mono,times",
  38. "Arial=arial,helvetica,sans-serif",
  39. "Arial Black=arial black,avant garde",
  40. "Book Antiqua=book antiqua,palatino",
  41. "Comic Sans MS=comic sans ms,sans-serif",
  42. "Courier New=courier new,courier",
  43. "Georgia=georgia,palatino",
  44. "Helvetica=helvetica",
  45. "Impact=impact,chicago",
  46. "Symbol=symbol",
  47. "Tahoma=tahoma,arial,helvetica,sans-serif",
  48. "Terminal=terminal,monaco",
  49. "Times New Roman=times new roman,times",
  50. "Trebuchet MS=trebuchet ms,geneva",
  51. "Verdana=verdana,geneva",
  52. "Webdings=webdings",
  53. "Wingdings=wingdings,zapf dingbats"
  54. ];
  55. export default {
  56. name: "TinymceEditor",
  57. components: {
  58. Editor
  59. },
  60. props: {
  61. //内容
  62. value: {
  63. type: String,
  64. default: ""
  65. },
  66. //是否禁用
  67. disabled: {
  68. type: Boolean,
  69. default: false
  70. },
  71. //插件
  72. plugins: {
  73. type: [String, Array],
  74. default: "advlist image lists wordcount " // media link autolink charmap
  75. },
  76. //工具栏
  77. toolbar: {
  78. type: [String, Array],
  79. default:
  80. "undo redo | formatselect | colorpicker | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | image" // | lists image media table link
  81. }
  82. },
  83. data() {
  84. return {
  85. //初始化配置
  86. tinymceId: "tinymce",
  87. myValue: this.value,
  88. init: {
  89. selector: "#tinymce",
  90. language_url: "/tinymce/langs/zh_CN.js", //汉化路径是自定义的,一般放在public或static里面
  91. language: "zh_CN",
  92. skin_url: "/tinymce/skins/ui/oxide", //皮肤
  93. icons_url: "/tinymce/icons/default/icons.min.js", //图标
  94. plugins: this.plugins, //插件
  95. //工具栏
  96. toolbar: this.toolbar,
  97. toolbar_location: "/",
  98. fontsize_formats:
  99. "12px 14px 16px 18px 20px 22px 24px 28px 32px 36px 48px 56px 72px", //字体大小
  100. font_formats: fonts.join(";"),
  101. content_style: "img {max-width:100%;}", // 图片最大的宽度,避免超出屏幕
  102. image_description: false,
  103. image_dimensions: false,
  104. height: 500, //高度
  105. placeholder: "在这里输入文字",
  106. branding: false, //隐藏右下角技术支持
  107. link_context_toolbar: true,
  108. media_dimensions: false,
  109. media_alt_source: false,
  110. //图片上传
  111. images_upload_handler: function(blobInfo, success, failure) {
  112. //文件上传的formData传递,忘记为什么要用这个了
  113. const isAccord =
  114. blobInfo.blob().type === "image/jpeg" ||
  115. blobInfo.blob().type === "image/png" ||
  116. blobInfo.blob().type === "image/GIF" ||
  117. blobInfo.blob().type === "image/jpg" ||
  118. blobInfo.blob().type === "image/BMP";
  119. if (blobInfo.blob().size / 1024 / 1024 > 2) {
  120. failure("上传失败,图片大小请控制在 2M 以内");
  121. } else if (blobInfo.blob().type == isAccord) {
  122. failure("图片格式错误");
  123. } else {
  124. let formData = new FormData();
  125. // 服务端接收文件的参数名,文件数据,文件名
  126. formData.append("image-file", blobInfo.blob(), blobInfo.filename());
  127. window.$_http.post("/image/upload", formData).then(res => {
  128. console.log("--upload--" + JSON.stringify(res));
  129. success(res.data.url);
  130. });
  131. }
  132. },
  133. // file_picker_callback: function(callback, value, meta) {
  134. // //文件分类
  135. // var filetype =
  136. // ".pdf, .txt, .zip, .rar, .7z, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .mp3, .mp4";
  137. // //后端接收上传文件的地址
  138. // //为不同插件指定文件类型及后端地址
  139. // let bucket = "jtxt-file-public";
  140. // let ossPath = "file/";
  141. // switch (meta.filetype) {
  142. // case "image":
  143. // filetype = ".jpg, .jpeg, .png, .gif";
  144. // ossPath = "image/";
  145. // break;
  146. // case "media":
  147. // bucket = "jtxt-video-public";
  148. // filetype = ".mp3, .mp4";
  149. // ossPath = "media/";
  150. // break;
  151. // case "file":
  152. // bucket = "jtxt-file-public";
  153. // filetype =
  154. // ".pdf, .txt, .zip, .rar, .7z, .doc, .docx, .xls, .xlsx, .ppt, .pptx";
  155. // ossPath = "file/";
  156. // break;
  157. // default:
  158. // }
  159. // //模拟出一个input用于添加本地文件
  160. // var input = document.createElement("input");
  161. // input.setAttribute("type", "file");
  162. // input.setAttribute("accept", filetype);
  163. // input.onchange = function(res) {
  164. // console.log("change----" + JSON.stringify(res));
  165. // let file = res.target.files[0];
  166. // window.$_http.get("/assume-oss-writer").then(res => {
  167. // console.log("--oss-writer--" + JSON.stringify(res));
  168. // const client = new OSS({
  169. // // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
  170. // region: "oss-cn-beijing",
  171. // // 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
  172. // accessKeyId: res.data.accessKeyId,
  173. // accessKeySecret: res.data.accessKeySecret,
  174. // // 从STS服务获取的安全令牌(SecurityToken)。
  175. // stsToken: res.data.securityToken,
  176. // // 填写Bucket名称。
  177. // bucket: bucket
  178. // });
  179. // // 上传oss
  180. // try {
  181. // client.put(ossPath + file.name, file).then(res => {
  182. // console.log(res);
  183. // callback(res.url);
  184. // });
  185. // } catch (e) {
  186. // console.error(e);
  187. // }
  188. // // 回调
  189. // });
  190. // };
  191. // input.click();
  192. // },
  193. menu: {
  194. file: { title: "File", items: "newdocument" },
  195. edit: {
  196. title: "Edit",
  197. items: "undo redo | cut copy pastetext | selectall"
  198. },
  199. insert: { title: "Insert", items: "link image media | template hr" },
  200. view: { title: "View", items: "visualaid" },
  201. format: {
  202. title: "Format",
  203. items:
  204. "bold italic underline strikethrough superscript subscript | removeformat"
  205. },
  206. table: {
  207. title: "Table",
  208. items: "inserttable tableprops deletetable | cell row column"
  209. },
  210. tools: { title: "Tools", items: "spellchecker code" }
  211. }
  212. }
  213. };
  214. },
  215. watch: {
  216. //监听内容变化
  217. value(newValue) {
  218. this.myValue = newValue == null ? "" : newValue;
  219. },
  220. myValue(newValue) {
  221. if (this.triggerChange) {
  222. this.$emit("change", newValue);
  223. } else {
  224. this.$emit("input", newValue);
  225. }
  226. }
  227. },
  228. mounted() {
  229. tinymce.init({});
  230. },
  231. methods: {
  232. onClick(e) {
  233. this.$emit("onClick", e, tinymce);
  234. },
  235. //清空内容
  236. clear() {
  237. this.myValue = "";
  238. }
  239. }
  240. };
  241. </script>
  242. <style lang="less" scoped>
  243. @import "~@/styles/common/variable.less";
  244. </style>