123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- <template>
- <div :class="{fullscreen:fullscreen}" class="tinymce-container" :style="{width:containerWidth}">
- <textarea :id="tinymceId" class="tinymce-textarea" />
- <!--<div class="editor-custom-btn-container">
- <editorImage color="#1890ff" class="editor-upload-btn" @successCBK="imageSuccessCBK" />
- </div>-->
- </div>
- </template>
- <script>
- /**
- * docs:
- * https://panjiachen.github.io/vue-element-admin-site/feature/component/rich-editor.html#tinymce
- */
- // import editorImage from './components/EditorImage'
- import plugins from './plugins'
- // import toolbar from './toolbar'
- import load from './dynamicLoadScript'
- import { uploadImg } from '@/api/qiniu'
- // why use this cdn, detail see https://github.com/PanJiaChen/tinymce-all-in-one
- const tinymceCDN = 'https://cdn.jsdelivr.net/npm/tinymce-all-in-one@4.9.3/tinymce.min.js'
- export default {
- name: 'Tinymce',
- // components: { editorImage },
- props: {
- id: {
- type: String,
- default: function() {
- return 'vue-tinymce-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
- }
- },
- value: {
- type: String,
- default: ''
- },
- toolbar: {
- type: Array,
- required: false,
- default() {
- return []
- // return ['removeformat undo redo | bullist numlist | outdent indent | forecolor | fullscreen code', 'bold italic blockquote | h2 p media link | alignleft aligncenter alignright | fontsizeselect | fontselect'] // 修改后 第一步
- }
- },
- menubar: {
- type: String,
- default: 'file edit insert view format table'
- },
- height: {
- type: [Number, String],
- required: false,
- default: 360
- },
- width: {
- type: [Number, String],
- required: false,
- default: 'auto'
- }
- },
- data() {
- return {
- hasChange: false,
- hasInit: false,
- tinymceId: this.id,
- fullscreen: false,
- languageTypeList: {
- 'en': 'en',
- 'zh': 'zh_CN',
- 'es': 'es_MX',
- 'ja': 'ja'
- }
- }
- },
- computed: {
- containerWidth() {
- const width = this.width
- if (/^[\d]+(\.[\d]+)?$/.test(width)) { // matches `100`, `'100'`
- return `${width}px`
- }
- return width
- }
- },
- watch: {
- value(val) {
- if (!this.hasChange && this.hasInit) {
- this.$nextTick(() =>
- window.tinymce.get(this.tinymceId).setContent(val || ''))
- }
- }
- },
- mounted() {
- this.init()
- },
- activated() {
- if (window.tinymce) {
- this.initTinymce()
- }
- },
- deactivated() {
- this.destroyTinymce()
- },
- destroyed() {
- this.destroyTinymce()
- },
- methods: {
- init() {
- // dynamic load tinymce from cdn
- load(tinymceCDN, (err) => {
- if (err) {
- this.$message.error(err.message)
- return
- }
- this.initTinymce()
- })
- },
- initTinymce() {
- const _this = this
- window.tinymce.init({
- // images_upload_url: '/static/image/',
- // images_upload_base_path: '/static/image',
- selector: `#${this.tinymceId}`,
- language: this.languageTypeList['zh'],
- height: this.height,
- body_class: 'panel-body ',
- object_resizing: false,
- // toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar,
- menubar: this.menubar,
- plugins: plugins,
- end_container_on_empty_block: true,
- powerpaste_word_import: 'clean',
- code_dialog_height: 450,
- code_dialog_width: 1000,
- advlist_bullet_styles: 'square',
- advlist_number_styles: 'default',
- imagetools_cors_hosts: ['www.tinymce.com', 'codepen.io'],
- default_link_target: '_blank',
- toolbar: ['searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript code codesample fontsizeselect fontselect', 'hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen'],
- fontsize_formats: '0pt 8pt 10pt 12pt 14pt 18pt 24pt 36pt',
- link_title: false,
- image_dimensions: false,
- content_style: 'div {margin: 0px; border:0px ; padding: 0px}',
- nonbreaking_force_tab: true, // inserting nonbreaking space need Nonbreaking Space Plugin
- init_instance_callback: editor => {
- if (_this.value) {
- editor.setContent(_this.value)
- }
- _this.hasInit = true
- editor.on('NodeChange Change KeyUp SetContent', () => {
- this.hasChange = true
- this.$emit('input', editor.getContent())
- })
- },
- setup(editor) {
- editor.on('FullscreenStateChanged', (e) => {
- _this.fullscreen = e.state
- })
- },
- images_upload_handler(blobInfo, success, failure, progress) {
- progress(0)
- // const token = _this.$store.getters.token
- const formData = new FormData()
- const image = blobInfo.blob()
- // formData.append('token', response.data.qiniu_token)
- formData.append('key', '1111')
- formData.append('image', image, image.name)
- console.log(blobInfo.blob())
- uploadImg(formData).then(response => {
- success(response.data.url)
- // const url = response.data.qiniu_url
- // upload(formData).then(() => {
- // success(url)
- // progress(100)
- // })
- }).catch(err => {
- failure('出现未知问题,刷新页面,或者联系程序员')
- console.log(err)
- })
- },
- // it will try to keep these URLs intact
- // https://www.tiny.cloud/docs-3x/reference/configuration/Configuration3x@convert_urls/
- // https://stackoverflow.com/questions/5196205/disable-tinymce-absolute-to-relative-url-conversions
- convert_urls: false
- // 整合七牛上传
- // images_dataimg_filter(img) {
- // setTimeout(() => {
- // const $image = $(img);
- // $image.removeAttr('width');
- // $image.removeAttr('height');
- // if ($image[0].height && $image[0].width) {
- // $image.attr('data-wscntype', 'image');
- // $image.attr('data-wscnh', $image[0].height);
- // $image.attr('data-wscnw', $image[0].width);
- // $image.addClass('wscnph');
- // }
- // }, 0);
- // return img
- // },
- // images_upload_handler(blobInfo, success, failure, progress) {
- // progress(0);
- // const token = _this.$store.getters.token;
- // getToken(token).then(response => {
- // const url = response.data.qiniu_url;
- // const formData = new FormData();
- // formData.append('token', response.data.qiniu_token);
- // formData.append('key', response.data.qiniu_key);
- // formData.append('file', blobInfo.blob(), url);
- // upload(formData).then(() => {
- // success(url);
- // progress(100);
- // })
- // }).catch(err => {
- // failure('出现未知问题,刷新页面,或者联系程序员')
- // console.log(err);
- // });
- // },
- })
- },
- destroyTinymce() {
- const tinymce = window.tinymce.get(this.tinymceId)
- if (this.fullscreen) {
- tinymce.execCommand('mceFullScreen')
- }
- if (tinymce) {
- tinymce.destroy()
- }
- },
- setContent(value) {
- window.tinymce.get(this.tinymceId).setContent(value)
- },
- getContent() {
- window.tinymce.get(this.tinymceId).getContent()
- },
- imageSuccessCBK(arr) {
- arr.forEach(v => window.tinymce.get(this.tinymceId).insertContent(`<img class="wscnph" src="${v.url}" >`))
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .tinymce-container {
- position: relative;
- line-height: normal;
- }
- .tinymce-container {
- ::v-deep {
- .mce-fullscreen {
- z-index: 10000;
- }
- }
- }
- .tinymce-textarea {
- visibility: hidden;
- z-index: -1;
- }
- .editor-custom-btn-container {
- position: absolute;
- right: 4px;
- top: 4px;
- /*z-index: 2005;*/
- }
- .fullscreen .editor-custom-btn-container {
- z-index: 10000;
- position: fixed;
- }
- .editor-upload-btn {
- display: inline-block;
- }
- </style>
|