目录
一、element-admin 七牛云上传图片
二、文章编辑器
1. 安装TinyMCE
2. 安装tinymce-vue
3.下载中文包
4.将相关资源放到public中
5.封装
三、实现页面跳转并传递数据
四、处理时间戳
template
<el-upload action="https://up-z0.qiniup.com" :data="postData" :on-success="handleAvatarSuccess"
:on-error="handleError" :before-upload="beforeAvatarUpload" :on-preview="handlePictureCardPreview"
:on-remove="handleRemove" :file-list="upImgList" :limit="1" :on-exceed="overLimitNum">
<el-button size="small" type="primary">上传封面</el-button>
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件,图片要求16:9,建议800×450</div>
</el-upload>
data
upImgList: [],
postData: {
token: ''
},
domain: '',
js
handleRemove(file, fileList) { //文件列表移除文件,处理删除逻辑
let list = [];
if (fileList.length == 0) {
this.upImgList = list;
} else {
for (var i = 0; i < fileList.length; i++) {
list.push({
name: fileList[i].name,
url: fileList[i].url
})
}
this.upImgList = list;
}
},
handlePictureCardPreview(file) {
this.form.articleCover = file.url;
},
handleAvatarSuccess(res, file) { //上传成功后在图片框显示图片
//this.imageUrl = this.domain+'/'+ res.key;
this.upImgList.push({
name: res.hash,
url: this.domain + '/' + res.key
});
this.form.articleCover = this.upImgList[0].url;
},
handleError(res) { //显示错误
console.log("handleError ---- ", res)
},
overLimitNum(files, fileList) { //当文件个数超出限制时所触发
this.$message.warning('抱歉,最多上传1张图片!')
},
beforeAvatarUpload(file) { //在图片提交前进行验证
const isJPG = file.type === 'image/jpeg'
const isPNG = file.type === 'image/png'
const isLt2M = (file.size / 1024 / 1024) < 2
if (!isJPG && !isPNG) {
this.$message.error('上传头像图片只能是 JPG/PNG 格式!')
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!')
}
return (isJPG || isPNG) && isLt2M
}
PS:本地上传可以使用http请求,发布到线上后使用http请求会被拦截报错导致上传失败,应该使用https请求
若项目是vue3.x,则:
npm install tinymce -S
如项目是vue2.x,则:
npm install tinymce@5.4.1 -S
若项目是vue3.x,则:
npm install @tinymce/tinymce-vue -S
若项目是vue2.x,则:
npm install @tinymce/tinymce-vue@3.2.8 -S
下载地址:
https://www.tiny.cloud/get-tiny/language-packages/
在public目录下新建tinymce,将上面下载的语言包解压到该目录
在node_modules里面找到tinymce,将skins目录复制到public/tinymce里面
<template>
<div class="tinymce-box">
<editor v-model="myValue"
:init="init"
:disabled="disabled"
@onClick="onClick">
</editor>
</div>
</template>
<script>
import tinymce from 'tinymce/tinymce' //tinymce默认hidden,不引入不显示
import Editor from '@tinymce/tinymce-vue'
import 'tinymce/themes/silver'
// 编辑器插件plugins
// 更多插件参考:https://www.tiny.cloud/docs/plugins/
import 'tinymce/plugins/image'// 插入上传图片插件
import 'tinymce/plugins/media'// 插入视频插件
import 'tinymce/plugins/table'// 插入表格插件
import 'tinymce/plugins/lists'// 列表插件
import 'tinymce/plugins/wordcount'// 字数统计插件
export default {
components:{
Editor
},
name:'tinymce',
props: {
value: {
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
},
plugins: {
type: [String, Array],
default: 'lists image media table wordcount'
},
toolbar: {
type: [String, Array],
default: 'undo redo | formatselect | bold italic forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | lists image media table | removeformat'
}
},
data(){
return{
init: {
language_url: '/tinymce/langs/zh_CN.js',
language: 'zh_CN',
skin_url: '/tinymce/skins/ui/oxide',
// skin_url: 'tinymce/skins/ui/oxide-dark',//暗色系
height: 300,
plugins: this.plugins,
toolbar: this.toolbar,
branding: false,
menubar: false,
// 此处为图片上传处理函数,这个直接用了base64的图片形式上传图片,
// 如需ajax上传可参考https://www.tiny.cloud/docs/configure/file-image-upload/#images_upload_handler
images_upload_handler: (blobInfo, success, failure) => {
const img = 'data:image/jpeg;base64,' + blobInfo.base64()
success(img)
}
},
myValue: this.value
}
},
mounted () {
tinymce.init({})
},
methods: {
// 添加相关的事件,可用的事件参照文档=> https://github.com/tinymce/tinymce-vue => All available events
// 需要什么事件可以自己增加
onClick (e) {
this.$emit('onClick', e, tinymce)
},
// 可以添加一些自己的自定义事件,如清空内容
clear () {
this.myValue = ''
}
},
watch: {
value (newValue) {
this.myValue = newValue
},
myValue (newValue) {
this.$emit('input', newValue)
}
}
}
</script>
<style scoped>
</style>
ps:
文章编辑器与图片上传七牛云结合进行封装
<template>
<div class="">
<editor v-model="myValue" :init="init" :disabled="disabled" @onClick="onClick">
</editor>
</div>
</template>
<script>
import tinymce from 'tinymce' //tinymce默认hidden,不引入不显示
import Editor from '@tinymce/tinymce-vue'
import 'tinymce/themes/silver'
// 编辑器插件plugins
// 更多插件参考:https://www.tiny.cloud/docs/plugins/
import 'tinymce/plugins/image'// 插入上传图片插件
// import 'tinymce/plugins/media'// 插入视频插件
import 'tinymce/plugins/table'// 插入表格插件
import 'tinymce/plugins/lists'// 列表插件
import 'tinymce/plugins/wordcount'// 字数统计插件
import { haveToken } from '@/api/content'
import axios from 'axios'
export default {
components: {
Editor
},
name: 'tinymce',
props: {
value: {
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
},
// plugins: {
// type: [String, Array],
// default: 'lists image media table wordcount'
// },
// toolbar: {
// type: [String, Array],
// default: 'undo redo | formatselect | bold italic forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | lists image media table | removeformat'
// }
},
data() {
return {
init: {
language_url: '/tinymce/langs/zh-Hans.js',
language: 'zh-Hans',
skin_url: '/tinymce/skins/ui/oxide',
// skin_url: 'tinymce/skins/ui/oxide-dark',//暗色系
height: 600,
plugins: "lists image table colorpicker textcolor wordcount contextmenu",
toolbar: 'code undo redo restoredraft | cut copy paste pastetext | forecolor backcolor bold italic underline strikethrough link anchor | alignleft aligncenter alignright alignjustify outdent indent | \
styleselect formatselect fontselect fontsizeselect | bullist numlist | blockquote subscript superscript removeformat | \
table image media charmap emoticons hr pagebreak insertdatetime print preview | fullscreen | bdmap indent2em lineheight formatpainter axupimgs',
branding: false,
menubar: false,
// 此处为图片上传处理函数,这个直接用了base64的图片形式上传图片,
// 如需ajax上传可参考https://www.tiny.cloud/docs/configure/file-image-upload/#images_upload_handler
images_upload_handler: (blobInfo, success, failure) => {
// const img = 'data:image/jpeg;base64,' + blobInfo.base64()
// success(img)
this.imgUpload(blobInfo, success, failure);
}
},
myValue: this.value,
postData: {
token: "" //七牛云token
}
}
},
mounted() {
this.getUploadToken(),
tinymce.init({})
},
methods: {
// 添加相关的事件,可用的事件参照文档=> https://github.com/tinymce/tinymce-vue => All available events
// 需要什么事件可以自己增加
onClick(e) {
this.$emit('onClick', e, tinymce)
},
// 可以添加一些自己的自定义事件,如清空内容
clear() {
this.myValue = ''
},
async getUploadToken() {
haveToken().then((res) => {
this.postData.token = res.uptoken
})
},
imgUpload(blobInfo, success, failure) {
const axiosInstance = axios.create({ withCredentials: false }); //withCredentials 禁止携带cookie,带cookie在七牛上有可能出现跨域问题
let data = new FormData();
data.append("token", this.postData.token); //七牛需要的token,后台获取
data.append("file", blobInfo.blob());
axiosInstance({
method: "POST",
url: 'https://up-z0.qiniup.com', //上传地址,视情况更换
data: data,
timeout: 30000, //超时时间,因为图片上传有可能需要很久
onUploadProgress: progressEvent => {
//imgLoadPercent 是上传进度,可以用来添加进度条
let imgLoadPercent = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
}
})
.then(res => {
// 调用成功回调,返回用七牛外链地址和返回的key拼接的图片路径
success(`https://qiniu.kingrisingsun.xyz/${res.data.key}`);
})
.catch(function (err) {
console.log(err);
//上传失败
});
},
},
watch: {
value(newValue) {
this.myValue = newValue
},
myValue(newValue) {
this.$emit('input', newValue)
}
}
}
</script>
<style scoped>
</style>
文章回显带有html标签的解决办法
1.vue 利用v-html将渲染的内容添加到对应标签即可
<div class="exhibition-content" v-html="t">
<!-- {{ tableData[0].articleContent }} -->
</div>
data() {
return {
t: ''
}
}
conversion() {
let str = this.tableData[0].articleContent
this.t = str
},
2.利用正则表达式将HTML标签给过滤掉 (存在弊端,图片的回显会失败)
<div class="exhibition-content">
{{ tableData[0].articleContent }}
</div>
handleTag() {
let str = this.firstNew.newContent
return this.firstNew.newContent = str.replace(/<[^>]+>/g, '')
}
query 【query传递数据是通过URL传递的,类似ajax中的get方式】
发送:
<!-- e:需要传递的数据 -->
<el-button type="primary" @click="doEdit(e)"></el-button>
doEdit(e) {
this.$router.push({
path: '/', //跳转路径
query: { entity: e } //传递数据
})
},
接收:
this.$route.query.entity
params 【params方式,类似ajax中的post方式】
发送:
<!-- e:需要传递的数据 -->
<el-button type="primary" @click="doEdit(e)"></el-button>
doEdit(e) {
this.$router.push({
name: '/', //跳转路径
params : { entity: e } //传递数据
})
},
接收:
this.$route.params.entity
PS:这里不能用path路径,只能用name【请对照router.js中的路由规则中的name项】,否则取不到传过去的数据
过滤器(filter):
formatDate(val) {
var date = new Date(Number(val)); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
var Y = date.getFullYear() + "-";
var M = (date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1) + "-";
var D = date.getDate() + " ";
var h = date.getHours() + ":";
var m = date.getMinutes() + ":";
var s = (date.getSeconds() < 10 ? "0" + (date.getSeconds()) : date.getSeconds());
return Y + M + D + h + m + s;
},
交代的需求一定要及时处理,不能因为这个需求相对简单而将其滞后先处理相对困难的部分,否则可能会在处理完当前处理的问题后因为间隔时间过长导致之前简单的需求忘记实现或修改。(好记性不如烂笔头,日后在开发中应当将交代的需求记录下来,处理完后进行标记,更加直观的展现未处理和已处理的需求)
编写代码时不应仅限于满足功能的实现,还应该注重实现代码的严谨性和规范性,否则就可能为将来的使用埋下隐患,目前对代码的规范了解甚少,应当多了解相关的规范以便在日后的开发中更加注意细节的处理,增加代码的规范性(如在跳转页面后判断页面功能时应使用英文避免使用中文 this.type = “编辑”改为this.type = “edit”)。
近几次的开发都暴露出了基础知识的薄弱,平日应加强基础知识的学习,查漏补缺,避免出现化简为繁的尴尬情况。
测试的时候应当严谨,同一个功能尽量选用不同的情境(即数据)进行多次测试,出现问题及时进行处理。如果测试的时候过于随意,就可能导致一些问题被掩盖无法发现,从而导致线上出现问题。而等到线上出现问题时再去修改,往往会造成恶劣的后果和不可估量的损失,这种情况在以后的开发中一定要避免避免再避免
{{ cmt.username }}
{{ cmt.content }}
{{ cmt.commentDate | formatDate('YYYY.MM.DD hh:mm') }}