Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d48ea83

Browse files
committed
feature:新增富文本编辑器插件功能入口,提供导出图片功能,全局loading配置
1 parent f14805d commit d48ea83

File tree

6 files changed

+378
-32
lines changed

6 files changed

+378
-32
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
"eslint": "5.15.3",
9090
"eslint-plugin-vue": "5.2.2",
9191
"html-webpack-plugin": "3.2.0",
92+
"html2canvas": "^1.0.0-rc.5",
9293
"husky": "1.3.1",
9394
"lint-staged": "8.1.5",
9495
"mockjs": "1.0.1-beta3",

src/components/Tinymce/components/EditorImage.vue

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
<template>
22
<div class="upload-container">
3-
<el-button :style="{background:color,borderColor:color}" icon="el-icon-upload" size="mini" type="primary" @click=" dialogVisible=true">
3+
<el-button
4+
:style="{background:color,borderColor:color}"
5+
icon="el-icon-upload"
6+
size="mini"
7+
type="primary"
8+
@click=" dialogVisible=true"
9+
>
410
upload
511
</el-button>
612
<el-dialog :visible.sync="dialogVisible">
@@ -15,14 +21,20 @@
1521
action="https://httpbin.org/post"
1622
list-type="picture-card"
1723
>
18-
<el-button size="small" type="primary">
24+
<el-button
25+
size="small"
26+
type="primary"
27+
>
1928
Click upload
2029
</el-button>
2130
</el-upload>
2231
<el-button @click="dialogVisible = false">
2332
Cancel
2433
</el-button>
25-
<el-button type="primary" @click="handleSubmit">
34+
<el-button
35+
type="primary"
36+
@click="handleSubmit"
37+
>
2638
Confirm
2739
</el-button>
2840
</el-dialog>
@@ -49,12 +61,16 @@ export default {
4961
},
5062
methods: {
5163
checkAllSuccess() {
52-
return Object.keys(this.listObj).every(item => this.listObj[item].hasSuccess)
64+
return Object.keys(this.listObj).every(
65+
item => this.listObj[item].hasSuccess
66+
)
5367
},
5468
handleSubmit() {
5569
const arr = Object.keys(this.listObj).map(v => this.listObj[v])
5670
if (!this.checkAllSuccess()) {
57-
this.$message('Please wait for all images to be uploaded successfully. If there is a network problem, please refresh the page and upload again!')
71+
this.$message(
72+
'Please wait for all images to be uploaded successfully. If there is a network problem, please refresh the page and upload again!'
73+
)
5874
return
5975
}
6076
this.$emit('successCBK', arr)
@@ -92,7 +108,12 @@ export default {
92108
const img = new Image()
93109
img.src = _URL.createObjectURL(file)
94110
img.onload = function() {
95-
_self.listObj[fileName] = { hasSuccess: false, uid: file.uid, width: this.width, height: this.height }
111+
_self.listObj[fileName] = {
112+
hasSuccess: false,
113+
uid: file.uid,
114+
width: this.width,
115+
height: this.height
116+
}
96117
}
97118
resolve(true)
98119
})

src/components/Tinymce/example.vue

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
<template>
2+
<div class="layout-container">
3+
<div ref="list" class="layout-body">
4+
<tinymce
5+
v-model="content"
6+
:menu="menu"
7+
:height="height"
8+
:new-event-list="eventList"
9+
/>
10+
</div>
11+
<div class="util-component" style="display:none;">
12+
<el-upload
13+
:multiple="true"
14+
:file-list="dataList.list"
15+
:on-progress="uploadProgress"
16+
:on-success="handleSuccess"
17+
class="editor-slide-upload"
18+
action="https://httpbin.org/post"
19+
list-type="picture-card"
20+
>
21+
<el-button id="editorUploader" size="small" type="primary">
22+
Click upload
23+
</el-button>
24+
</el-upload>
25+
</div>
26+
<div ref="imageWrapper" class="show-html" v-html="content" />
27+
</div>
28+
</template>
29+
30+
<script>
31+
import Tinymce from './index'
32+
import html2canvas from 'html2canvas'
33+
import { Loading } from 'element-ui'
34+
export default {
35+
name: 'TinymceDemo',
36+
components: { Tinymce },
37+
data() {
38+
return {
39+
showPreviewDialog: false,
40+
dataurl: '',
41+
eventList: [
42+
{
43+
toolbarName: 'uploadImg',
44+
tooltip: 'uploadImg',
45+
text: 'uploadImg',
46+
fn: (e, callback) => {
47+
this.handleAdd('uploadImg', data => {
48+
if (callback && typeof callback === 'function') {
49+
callback(data)
50+
}
51+
})
52+
}
53+
},
54+
// {
55+
// toolbarName: 'uploadVideo',
56+
// tooltip: 'uploadVideo',
57+
// text: 'uploadVideo',
58+
// fn: (e, callback) => {
59+
// this.handleAdd('uploadVideo', data => {
60+
// if (callback && typeof callback === 'function') {
61+
// callback(data)
62+
// }
63+
// })
64+
// }
65+
// },
66+
{
67+
toolbarName: 'spreview',
68+
tooltip: 'spreview',
69+
text: 'spreview',
70+
fn: (e, callback) => {
71+
this.toImage()
72+
}
73+
}
74+
],
75+
isUpload: false,
76+
dataList: {
77+
list: [
78+
{
79+
url: ''
80+
}
81+
],
82+
type: 'image',
83+
setDom: v => `<a>${v.dom}</a>`
84+
},
85+
height: 700,
86+
menu: {
87+
file: { title: '文件', items: 'newdocument' },
88+
edit: {
89+
title: '编辑',
90+
items: 'undo redo | cut copy paste pastetext | selectall'
91+
},
92+
insert: { title: '插入', items: 'link media | image hr' },
93+
view: { title: '查看', items: 'visualaid' },
94+
format: {
95+
title: '格式',
96+
items:
97+
'bold italic underline strikethrough superscript subscript | formats | removeformat'
98+
},
99+
table: {
100+
title: '表格',
101+
items: 'inserttable tableprops deletetable | cell row column'
102+
},
103+
tools: { title: '工具', items: 'spellchecker code' }
104+
},
105+
loadingInstance: null,
106+
content: `<h1 style="text-align: center;">测试demo!</h1>
107+
<p>嗨</p>
108+
<img class="img" src="https://ali-image-test.dabanjia.com/image/20200508/1588911589606_5140%24ban.jpg" width="200"/>
109+
<p>枕着幸福在梦中微笑,清零生活的压力烦恼,阳光透过窗与你拥抱,伸伸懒腰迎接周末来到,问候源于无法按捺的心跳,愿你周末乐逍遥,生活更美妙!
110+
周末来到,让烦恼跑光,让忧愁找不到,跟寂寞说再见,跟压力说拜拜,跟快乐说你好,牵着幸福的手,携上平安,开开心心的过周末!
111+
每个人,都有一个世界;每首歌,都有一个故事;每一周,都有一个周末;每个人,都要一个愿望;我的愿望很现实:周末清晨,搅黄你的美梦!周末快乐!
112+
</p>
113+
`
114+
}
115+
},
116+
computed: {
117+
fileType() {
118+
// 自定义配置上传组件支持的文件,需要对上传组件进行封装,制定文件规格
119+
if (this.dataList.type === 'image') {
120+
return 'png|jpe?g|gif|svg'
121+
}
122+
if (this.dataList.type === 'video') {
123+
// 暂时只支持mp4
124+
return 'mp4'
125+
// return "mp4|webm|ogg|mp3|wav|flac|aac";
126+
}
127+
return ''
128+
}
129+
},
130+
mounted() {
131+
// 实时获取高度,并减去padding值
132+
this.height = this.$refs.list.clientHeight - 32
133+
},
134+
methods: {
135+
toImage() {
136+
var width = 330 // 获取dom 宽度
137+
var height = this.$refs.imageWrapper.scrollHeight // 获取dom 高度
138+
var canvas = document.createElement('canvas') // 创建一个canvas节点
139+
var scale = 2 // 定义任意放大倍数 支持小数默认设置为2,确保图片清晰度
140+
canvas.width = width * scale * scale // 定义canvas 宽度 * 缩放
141+
canvas.height = height * scale * scale // 定义canvas高度 *缩放
142+
canvas.getContext('2d').scale(scale, scale) // 获取context,设置scale
143+
var opts = {
144+
tainttest: true, // 检测每张图片都已经加载完成
145+
scale: scale, // 添加的scale 参数
146+
useCORS: true,
147+
canvas: canvas, // 自定义 canvas
148+
logging: true, // 日志开关
149+
width: width, // dom 原始宽度
150+
height: height // dom 原始高度
151+
}
152+
html2canvas(this.$refs.imageWrapper, opts).then(canvas => {
153+
const dataurl = canvas.toDataURL('image/png')
154+
this.dataurl = dataurl
155+
if (this.dataurl !== '') {
156+
console.log(this.dataurl, '生成base64')
157+
}
158+
})
159+
},
160+
error(e) {
161+
console.log(e)
162+
},
163+
handleAdd(key, callback) {
164+
this.dataList.list[0].url = ''
165+
this.isUpload = false
166+
switch (key) {
167+
case 'uploadImg':
168+
this.dataList.type = 'image'
169+
document.getElementById('editorUploader').click()
170+
171+
break
172+
case 'uploadVideo':
173+
this.dataList.type = 'video'
174+
document.getElementById('editorUploader').click()
175+
176+
break
177+
// 批量操作,可自定义所有操作
178+
case 'selectImg':
179+
break
180+
case 'selectVideo':
181+
break
182+
}
183+
const unWatch = this.$watch('isUpload', val => {
184+
if (val && callback && typeof callback === 'function') {
185+
callback(this.dataList)
186+
// 取消监听
187+
unWatch()
188+
}
189+
})
190+
},
191+
uploadProgress() {
192+
this.loadingInstance = Loading.service({
193+
lock: true,
194+
text: '数据加载中,请稍后...',
195+
background: 'rgba(0, 0, 0, 0.1)'
196+
})
197+
},
198+
// 定义模板
199+
handleSuccess(data, file) {
200+
this.loadingInstance.close()
201+
this.dataList.list[0].url = file.url
202+
const { type } = this.dataList
203+
if (type === 'image') {
204+
this.dataList.setDom = v =>
205+
`<img class="img-scale" src="${v.url}" width="200">`
206+
}
207+
if (type === 'video') {
208+
// 自定义配置模板信息,宽高后期都可变成输入
209+
this.dataList.setDom = v =>
210+
`<p >
211+
<video controls="controls" width="200" height="350" >
212+
<source src="https://dev-saas.oss-cn-beijing.aliyuncs.com/056eb234fa9844b0b7ec3e13bd39faf7.mp4" type="video/mp4" />
213+
<source src="${v.url}" type="video/mp4" />
214+
</video>
215+
216+
</p>
217+
`
218+
}
219+
this.isUpload = true
220+
}
221+
}
222+
}
223+
</script>
224+
<style scoped>
225+
.show-html {
226+
position: fixed;
227+
right: 40px;
228+
top: 80px;
229+
width: 330px;
230+
padding: 16px;
231+
background: #fff;
232+
border: 1px solid goldenrod;
233+
}
234+
</style>

0 commit comments

Comments
 (0)