提交 | 用户 | age
|
4dde14
|
1 |
<template> |
L |
2 |
<div :class="{fullscreen:fullscreen}" class="tinymce-container" :style="{width:containerWidth}"> |
|
3 |
<textarea :id="tinymceId" class="tinymce-textarea" /> |
|
4 |
<div class="editor-custom-btn-container"> |
|
5 |
<editorImage color="#1890ff" class="editor-upload-btn" @successCBK="imageSuccessCBK" /> |
|
6 |
</div> |
|
7 |
</div> |
|
8 |
</template> |
|
9 |
|
|
10 |
<script> |
|
11 |
/** |
|
12 |
* docs: |
|
13 |
* https://panjiachen.github.io/vue-element-admin-site/feature/component/rich-editor.html#tinymce |
|
14 |
*/ |
|
15 |
import editorImage from './components/EditorImage' |
|
16 |
import plugins from './plugins' |
|
17 |
import toolbar from './toolbar' |
|
18 |
import load from './dynamicLoadScript' |
|
19 |
|
|
20 |
// why use this cdn, detail see https://github.com/PanJiaChen/tinymce-all-in-one |
|
21 |
const tinymceCDN = 'https://cdn.jsdelivr.net/npm/tinymce-all-in-one@4.9.3/tinymce.min.js' |
|
22 |
|
|
23 |
export default { |
|
24 |
name: 'Tinymce', |
|
25 |
components: { editorImage }, |
|
26 |
props: { |
|
27 |
id: { |
|
28 |
type: String, |
|
29 |
default: function() { |
|
30 |
return 'vue-tinymce-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '') |
|
31 |
} |
|
32 |
}, |
|
33 |
value: { |
|
34 |
type: String, |
|
35 |
default: '' |
|
36 |
}, |
|
37 |
toolbar: { |
|
38 |
type: Array, |
|
39 |
required: false, |
|
40 |
default() { |
|
41 |
return [] |
|
42 |
} |
|
43 |
}, |
|
44 |
menubar: { |
|
45 |
type: String, |
|
46 |
default: 'file edit insert view format table' |
|
47 |
}, |
|
48 |
height: { |
|
49 |
type: [Number, String], |
|
50 |
required: false, |
|
51 |
default: 360 |
|
52 |
}, |
|
53 |
width: { |
|
54 |
type: [Number, String], |
|
55 |
required: false, |
|
56 |
default: 'auto' |
|
57 |
} |
|
58 |
}, |
|
59 |
data() { |
|
60 |
return { |
|
61 |
hasChange: false, |
|
62 |
hasInit: false, |
|
63 |
tinymceId: this.id, |
|
64 |
fullscreen: false, |
|
65 |
languageTypeList: { |
|
66 |
'en': 'en', |
|
67 |
'zh': 'zh_CN', |
|
68 |
'es': 'es_MX', |
|
69 |
'ja': 'ja' |
|
70 |
} |
|
71 |
} |
|
72 |
}, |
|
73 |
computed: { |
|
74 |
containerWidth() { |
|
75 |
const width = this.width |
|
76 |
if (/^[\d]+(\.[\d]+)?$/.test(width)) { // matches `100`, `'100'` |
|
77 |
return `${width}px` |
|
78 |
} |
|
79 |
return width |
|
80 |
} |
|
81 |
}, |
|
82 |
watch: { |
|
83 |
value(val) { |
|
84 |
if (!this.hasChange && this.hasInit) { |
|
85 |
this.$nextTick(() => |
|
86 |
window.tinymce.get(this.tinymceId).setContent(val || '')) |
|
87 |
} |
|
88 |
} |
|
89 |
}, |
|
90 |
mounted() { |
|
91 |
this.init() |
|
92 |
}, |
|
93 |
activated() { |
|
94 |
if (window.tinymce) { |
|
95 |
this.initTinymce() |
|
96 |
} |
|
97 |
}, |
|
98 |
deactivated() { |
|
99 |
this.destroyTinymce() |
|
100 |
}, |
|
101 |
destroyed() { |
|
102 |
this.destroyTinymce() |
|
103 |
}, |
|
104 |
methods: { |
|
105 |
init() { |
|
106 |
// dynamic load tinymce from cdn |
|
107 |
load(tinymceCDN, (err) => { |
|
108 |
if (err) { |
|
109 |
this.$message.error(err.message) |
|
110 |
return |
|
111 |
} |
|
112 |
this.initTinymce() |
|
113 |
}) |
|
114 |
}, |
|
115 |
initTinymce() { |
|
116 |
const _this = this |
|
117 |
window.tinymce.init({ |
|
118 |
selector: `#${this.tinymceId}`, |
|
119 |
language: this.languageTypeList['en'], |
|
120 |
height: this.height, |
|
121 |
body_class: 'panel-body ', |
|
122 |
object_resizing: false, |
|
123 |
toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar, |
|
124 |
menubar: this.menubar, |
|
125 |
plugins: plugins, |
|
126 |
end_container_on_empty_block: true, |
|
127 |
powerpaste_word_import: 'clean', |
|
128 |
code_dialog_height: 450, |
|
129 |
code_dialog_width: 1000, |
|
130 |
advlist_bullet_styles: 'square', |
|
131 |
advlist_number_styles: 'default', |
|
132 |
imagetools_cors_hosts: ['www.tinymce.com', 'codepen.io'], |
|
133 |
default_link_target: '_blank', |
|
134 |
link_title: false, |
|
135 |
nonbreaking_force_tab: true, // inserting nonbreaking space need Nonbreaking Space Plugin |
|
136 |
init_instance_callback: editor => { |
|
137 |
if (_this.value) { |
|
138 |
editor.setContent(_this.value) |
|
139 |
} |
|
140 |
_this.hasInit = true |
|
141 |
editor.on('NodeChange Change KeyUp SetContent', () => { |
|
142 |
this.hasChange = true |
|
143 |
this.$emit('input', editor.getContent()) |
|
144 |
}) |
|
145 |
}, |
|
146 |
setup(editor) { |
|
147 |
editor.on('FullscreenStateChanged', (e) => { |
|
148 |
_this.fullscreen = e.state |
|
149 |
}) |
|
150 |
}, |
|
151 |
// it will try to keep these URLs intact |
|
152 |
// https://www.tiny.cloud/docs-3x/reference/configuration/Configuration3x@convert_urls/ |
|
153 |
// https://stackoverflow.com/questions/5196205/disable-tinymce-absolute-to-relative-url-conversions |
|
154 |
convert_urls: false |
|
155 |
// 整合七牛上传 |
|
156 |
// images_dataimg_filter(img) { |
|
157 |
// setTimeout(() => { |
|
158 |
// const $image = $(img); |
|
159 |
// $image.removeAttr('width'); |
|
160 |
// $image.removeAttr('height'); |
|
161 |
// if ($image[0].height && $image[0].width) { |
|
162 |
// $image.attr('data-wscntype', 'image'); |
|
163 |
// $image.attr('data-wscnh', $image[0].height); |
|
164 |
// $image.attr('data-wscnw', $image[0].width); |
|
165 |
// $image.addClass('wscnph'); |
|
166 |
// } |
|
167 |
// }, 0); |
|
168 |
// return img |
|
169 |
// }, |
|
170 |
// images_upload_handler(blobInfo, success, failure, progress) { |
|
171 |
// progress(0); |
|
172 |
// const token = _this.$store.getters.token; |
|
173 |
// getToken(token).then(response => { |
|
174 |
// const url = response.data.qiniu_url; |
|
175 |
// const formData = new FormData(); |
|
176 |
// formData.append('token', response.data.qiniu_token); |
|
177 |
// formData.append('key', response.data.qiniu_key); |
|
178 |
// formData.append('file', blobInfo.blob(), url); |
|
179 |
// upload(formData).then(() => { |
|
180 |
// success(url); |
|
181 |
// progress(100); |
|
182 |
// }) |
|
183 |
// }).catch(err => { |
|
184 |
// failure('出现未知问题,刷新页面,或者联系程序员') |
|
185 |
// console.log(err); |
|
186 |
// }); |
|
187 |
// }, |
|
188 |
}) |
|
189 |
}, |
|
190 |
destroyTinymce() { |
|
191 |
const tinymce = window.tinymce.get(this.tinymceId) |
|
192 |
if (this.fullscreen) { |
|
193 |
tinymce.execCommand('mceFullScreen') |
|
194 |
} |
|
195 |
|
|
196 |
if (tinymce) { |
|
197 |
tinymce.destroy() |
|
198 |
} |
|
199 |
}, |
|
200 |
setContent(value) { |
|
201 |
window.tinymce.get(this.tinymceId).setContent(value) |
|
202 |
}, |
|
203 |
getContent() { |
|
204 |
window.tinymce.get(this.tinymceId).getContent() |
|
205 |
}, |
|
206 |
imageSuccessCBK(arr) { |
|
207 |
arr.forEach(v => window.tinymce.get(this.tinymceId).insertContent(`<img class="wscnph" src="${v.url}" >`)) |
|
208 |
} |
|
209 |
} |
|
210 |
} |
|
211 |
</script> |
|
212 |
|
|
213 |
<style lang="scss" scoped> |
|
214 |
.tinymce-container { |
|
215 |
position: relative; |
|
216 |
line-height: normal; |
|
217 |
} |
|
218 |
|
|
219 |
.tinymce-container { |
|
220 |
::v-deep { |
|
221 |
.mce-fullscreen { |
|
222 |
z-index: 10000; |
|
223 |
} |
|
224 |
} |
|
225 |
} |
|
226 |
|
|
227 |
.tinymce-textarea { |
|
228 |
visibility: hidden; |
|
229 |
z-index: -1; |
|
230 |
} |
|
231 |
|
|
232 |
.editor-custom-btn-container { |
|
233 |
position: absolute; |
|
234 |
right: 4px; |
|
235 |
top: 4px; |
|
236 |
/*z-index: 2005;*/ |
|
237 |
} |
|
238 |
|
|
239 |
.fullscreen .editor-custom-btn-container { |
|
240 |
z-index: 10000; |
|
241 |
position: fixed; |
|
242 |
} |
|
243 |
|
|
244 |
.editor-upload-btn { |
|
245 |
display: inline-block; |
|
246 |
} |
|
247 |
</style> |