|
@@ -1,107 +1,149 @@
|
|
<template>
|
|
<template>
|
|
- <tiny-editor v-model="content" :init="init" :key="componentKey" id="textarea"></tiny-editor>
|
|
|
|
-</template>
|
|
|
|
-
|
|
|
|
-<script>
|
|
|
|
-import editor from '@tinymce/tinymce-vue';
|
|
|
|
-import url from '@/utils/baseUrl';
|
|
|
|
-
|
|
|
|
-export default {
|
|
|
|
- name: 'myEditor',
|
|
|
|
- props: {
|
|
|
|
- value: {
|
|
|
|
- type: String,
|
|
|
|
- default: ''
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
- data() {
|
|
|
|
- return {
|
|
|
|
- componentKey: 0, // 用于强制重新渲染
|
|
|
|
- content: '',
|
|
|
|
- init: {
|
|
|
|
- selector: '#textarea',
|
|
|
|
- height: 550,
|
|
|
|
- language_url: 'js/tinymce/langs/zh_CN.js',
|
|
|
|
- language: 'zh_CN',
|
|
|
|
- plugins: 'image axupimgs code lists advlist table anchor autosave charmap fullscreen hr insertdatetime link preview print searchreplace wordcount indent2em',
|
|
|
|
- toolbar: [
|
|
|
|
- "undo redo | styleselect | fontselect | fontsizeselect | bold italic underline strikethrough subscript superscript charmap | indent2em | alignleft aligncenter alignright alignjustify | lineheight | outdent indent",
|
|
|
|
- "forecolor backcolor | link | removeformat | image axupimgs | table | searchreplace cut copy paste | hr blockquote anchor | bullist numlist | insertdatetime | restoredraft | code | fullscreen preview print wordcount"
|
|
|
|
- ],
|
|
|
|
- font_formats: '微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;宋体=simsun,serif',
|
|
|
|
- fontsize_formats: '12px 14px 16px 18px 20px 22px 24px 28px 32px 36px 42px 48px',
|
|
|
|
- branding: false,
|
|
|
|
- images_upload_handler: function (blobInfo, success, failure) {
|
|
|
|
- var xhr, formData;
|
|
|
|
- xhr = new XMLHttpRequest();
|
|
|
|
- xhr.withCredentials = false;
|
|
|
|
- //创建连接
|
|
|
|
- xhr.open('POST', url.baseUrl + '/public/uploadFile');
|
|
|
|
- xhr.onload = function () {
|
|
|
|
- var json;
|
|
|
|
- if (xhr.status < 200 || xhr.status >= 300) {
|
|
|
|
- failure('HTTP Error: ' + xhr.status);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- json = JSON.parse(xhr.responseText);
|
|
|
|
- console.log(json)
|
|
|
|
- if (json.code != 200) {
|
|
|
|
- failure('图片上传失败! ' + json.message);
|
|
|
|
- return;
|
|
|
|
|
|
+ <tiny-editor v-model="content" :init="init" :key="componentKey" id="textarea"></tiny-editor>
|
|
|
|
+ </template>
|
|
|
|
+
|
|
|
|
+ <script>
|
|
|
|
+ import editor from '@tinymce/tinymce-vue';
|
|
|
|
+ import url from '@/utils/baseUrl';
|
|
|
|
+
|
|
|
|
+ export default {
|
|
|
|
+ name: 'myEditor',
|
|
|
|
+ props: {
|
|
|
|
+ value: {
|
|
|
|
+ type: String,
|
|
|
|
+ default: ''
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ data() {
|
|
|
|
+ return {
|
|
|
|
+ componentKey: 0,
|
|
|
|
+ content: '',
|
|
|
|
+ init: {
|
|
|
|
+ selector: '#textarea',
|
|
|
|
+ height: 550,
|
|
|
|
+ language_url: 'js/tinymce/langs/zh_CN.js',
|
|
|
|
+ language: 'zh_CN',
|
|
|
|
+ plugins: 'paste image axupimgs code lists advlist table anchor autosave charmap fullscreen hr insertdatetime link preview print searchreplace wordcount indent2em',
|
|
|
|
+ toolbar: [
|
|
|
|
+ "undo redo | styleselect | fontselect | fontsizeselect | bold italic underline strikethrough subscript superscript charmap | indent2em | alignleft aligncenter alignright alignjustify | lineheight | outdent indent",
|
|
|
|
+ "forecolor backcolor | link | removeformat | image axupimgs | table | searchreplace cut copy paste | hr blockquote anchor | bullist numlist | insertdatetime | restoredraft | code | fullscreen preview print wordcount"
|
|
|
|
+ ],
|
|
|
|
+ font_formats: '微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;宋体=simsun,serif',
|
|
|
|
+ fontsize_formats: '12px 14px 16px 18px 20px 22px 24px 28px 32px 36px 42px 48px',
|
|
|
|
+ branding: false,
|
|
|
|
+ paste_data_images: true,
|
|
|
|
+ paste_postprocess: (editor, args) => {
|
|
|
|
+ const images = args.node.querySelectorAll('img[src^="data:image/"]');
|
|
|
|
+ if (images.length > 0) {
|
|
|
|
+ Array.from(images).forEach((img) => {
|
|
|
|
+ const blob = this.dataURLtoBlob(img.src);
|
|
|
|
+ this.uploadImageFromBlob(blob,
|
|
|
|
+ (imageUrl) => {
|
|
|
|
+ editor.dom.setAttrib(img, 'src', imageUrl);
|
|
|
|
+ editor.dom.setAttrib(img, 'alt', '粘贴的图片');
|
|
|
|
+ },
|
|
|
|
+ (error) => {
|
|
|
|
+ console.error('图片上传失败:', error);
|
|
|
|
+ editor.dom.remove(img);
|
|
|
|
+ }
|
|
|
|
+ );
|
|
|
|
+ });
|
|
}
|
|
}
|
|
- success(json.data.imgUrl);
|
|
|
|
- // Listen for the NodeChange event to set the alt attribute
|
|
|
|
- const editor = tinymce.activeEditor;
|
|
|
|
- editor.on('NodeChange', function (e) {
|
|
|
|
- const imgElm = e.element;
|
|
|
|
- if (imgElm.nodeName === 'IMG' && imgElm.src === json.data.imgUrl) {
|
|
|
|
- console.log("Setting alt attribute to:", json.data.oldName || '全国政务信息一体化应用平台'); // Debugging: Check the alt value
|
|
|
|
- editor.dom.setAttrib(imgElm, 'alt', json.data.oldName || '全国政务信息一体化应用平台'); // Use oldName or a default value
|
|
|
|
- editor.off('NodeChange'); // Remove the event listener after setting the alt
|
|
|
|
|
|
+ },
|
|
|
|
+ images_upload_handler: (blobInfo, success, failure) => {
|
|
|
|
+ const xhr = new XMLHttpRequest();
|
|
|
|
+ xhr.withCredentials = false;
|
|
|
|
+ xhr.open('POST', url.baseUrl + '/public/uploadFile');
|
|
|
|
+ xhr.onload = () => {
|
|
|
|
+ if (xhr.status < 200 || xhr.status >= 300) {
|
|
|
|
+ failure('HTTP Error: ' + xhr.status);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ const json = JSON.parse(xhr.responseText);
|
|
|
|
+ if (json.code != 200) {
|
|
|
|
+ failure('图片上传失败! ' + json.message);
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
|
|
+ success(json.data.imgUrl);
|
|
|
|
+
|
|
|
|
+ const editor = tinymce.activeEditor;
|
|
|
|
+ const nodeChangeHandler = (e) => {
|
|
|
|
+ const imgElm = e.element;
|
|
|
|
+ if (imgElm.nodeName === 'IMG' && imgElm.src === json.data.imgUrl) {
|
|
|
|
+ editor.dom.setAttrib(imgElm, 'alt', json.data.oldName || '全国政务信息一体化应用平台');
|
|
|
|
+ editor.off('NodeChange', nodeChangeHandler);
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ editor.on('NodeChange', nodeChangeHandler);
|
|
|
|
+ };
|
|
|
|
+ const formData = new FormData();
|
|
|
|
+ formData.append('file', blobInfo.blob());
|
|
|
|
+ xhr.send(formData);
|
|
|
|
+ },
|
|
|
|
+ setup: (editor) => {
|
|
|
|
+ this.editorInstance = editor;
|
|
|
|
+ editor.setContent(this.value);
|
|
|
|
+ editor.on('change', () => {
|
|
|
|
+ this.$emit('input', editor.getContent());
|
|
});
|
|
});
|
|
- };
|
|
|
|
-
|
|
|
|
- formData = new FormData();
|
|
|
|
- formData.append('file', blobInfo.blob());
|
|
|
|
- xhr.send(formData);
|
|
|
|
- },
|
|
|
|
- setup: (editor) => { // 这里改用箭头函数
|
|
|
|
- // 存储编辑器引用
|
|
|
|
- this.editorInstance = editor;
|
|
|
|
- // 初始设置内容
|
|
|
|
- editor.setContent(this.value);
|
|
|
|
- editor.on('change', () => {
|
|
|
|
- this.$emit('input', editor.getContent()); // 发送内容变化事件
|
|
|
|
- });
|
|
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+ };
|
|
|
|
+ },
|
|
|
|
+ methods: {
|
|
|
|
+ dataURLtoBlob(dataURL) {
|
|
|
|
+ const arr = dataURL.split(',');
|
|
|
|
+ const mime = arr[0].match(/:(.*?);/)[1];
|
|
|
|
+ const bstr = atob(arr[1]);
|
|
|
|
+ let n = bstr.length;
|
|
|
|
+ const u8arr = new Uint8Array(n);
|
|
|
|
+ while(n--) {
|
|
|
|
+ u8arr[n] = bstr.charCodeAt(n);
|
|
|
|
+ }
|
|
|
|
+ return new Blob([u8arr], {type: mime});
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ uploadImageFromBlob(blob, success, failure) {
|
|
|
|
+ const xhr = new XMLHttpRequest();
|
|
|
|
+ xhr.withCredentials = false;
|
|
|
|
+ xhr.open('POST', url.baseUrl + '/public/uploadFile');
|
|
|
|
+
|
|
|
|
+ xhr.onload = () => {
|
|
|
|
+ if (xhr.status < 200 || xhr.status >= 300) {
|
|
|
|
+ failure('HTTP Error: ' + xhr.status);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const json = JSON.parse(xhr.responseText);
|
|
|
|
+ if (json.code != 200) {
|
|
|
|
+ failure('图片上传失败! ' + json.message);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ success(json.data.imgUrl);
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ const formData = new FormData();
|
|
|
|
+ formData.append('file', blob);
|
|
|
|
+ xhr.send(formData);
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ reinitEditor() {
|
|
|
|
+ this.componentKey += 1;
|
|
}
|
|
}
|
|
- };
|
|
|
|
- },
|
|
|
|
- watch: {
|
|
|
|
- value(newVal) {
|
|
|
|
- // 当父组件传入新内容时更新编辑器
|
|
|
|
- if (this.editorInstance && newVal !== this.editorInstance.getContent()) {
|
|
|
|
- this.content = newVal;
|
|
|
|
- //以防万一可以使用下面这个方法 强制更新视图
|
|
|
|
- //this.reinitEditor();
|
|
|
|
|
|
+ },
|
|
|
|
+ watch: {
|
|
|
|
+ value(newVal) {
|
|
|
|
+ if (this.editorInstance && newVal !== this.editorInstance.getContent()) {
|
|
|
|
+ this.content = newVal;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- }
|
|
|
|
- },
|
|
|
|
- components: {
|
|
|
|
- 'tiny-editor': editor,
|
|
|
|
- },
|
|
|
|
- created() {
|
|
|
|
-
|
|
|
|
- },
|
|
|
|
- mounted() {
|
|
|
|
- this.reinitEditor();
|
|
|
|
- },
|
|
|
|
- methods: {
|
|
|
|
- // 强制重新初始化编辑器(必要时使用)
|
|
|
|
- reinitEditor() {
|
|
|
|
- this.componentKey += 1;
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
-}
|
|
|
|
-</script>
|
|
|
|
|
|
+ },
|
|
|
|
+ components: {
|
|
|
|
+ 'tiny-editor': editor,
|
|
|
|
+ },
|
|
|
|
+ mounted() {
|
|
|
|
+ this.reinitEditor();
|
|
|
|
+ },
|
|
|
|
+ }
|
|
|
|
+ </script>
|