数据页面::ResourceUrl="resourceUrl"
,注意,该代码是向裁剪页回传图片数据
<template>
<div>
<el-dialog :visible.sync="visible" :title="!dataForm.id ? $t('add') : $t('update')" :close-on-click-modal="false" :close-on-press-escape="false">
<el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmitHandle()" label-width="120px">
<el-form-item prop="coverUrl" :label="$t('course.coverUrl')">
<div class="list-img-box">
<img :src="courseUrl" style='width:120px;height:120px;border:none;' alt="自定义图片" @error="imgError()"><br/>
<el-button type="text" @click="uploadPicture('flagImg')">修改图片</el-button>
</div>
<input type="hidden" v-model="dataForm.coverUrl" placeholder="请添加图片">
</el-form-item>
</el-form>
<template slot="footer">
<el-button @click="visible = false">{{ $t('cancel') }}</el-button>
<el-button type="primary" @click="dataFormSubmitHandle()">{{ $t('confirm') }}</el-button>
</template>
</el-dialog>
<!-- 弹窗, 上传文件 -->
<upload v-if="uploadVisible" ref="upload" @uploadback="uploadUrl"></upload>
<!-- 剪裁组件弹窗 -->
<el-dialog title="裁切封面" :visible.sync="cropperModel" v-if="cropperModel" width="1130px" center append-to-body :before-close="dialogClose">
<cropper-image :Name="cropperName" :ResourceUrl="resourceUrl" @uploadImgSuccess = "handleUploadSuccess" ref="child" :key="componentKey">
</cropper-image>
</el-dialog>
<!--查看大封面-->
<el-dialog title="查看大封面" :visible.sync="imgVisible" center>
<img :src="imgName" v-if="imgVisible" style="width: 100%" alt="查看">
</el-dialog>
</div>
</template>
<script>
import debounce from 'lodash/debounce'
import CropperImage from './cropperImage'
export default {
data () {
return {
visible: false,
dataForm: {
id: '',
coverUrl: ''
},
courseUrl: '',
// 裁切图片参数
cropperModel: false,
cropperName: '',
resourceUrl: '',
imgName: '',
imgVisible: false,
// 该参数作用是点击上传图片确定按钮后,刷新页面数据
componentKey: 0
}
},
components: {
CropperImage
},
methods: {
init () {
this.visible = true
this.$nextTick(() => {
this.courseUrl = ''
this.$refs['dataForm'].resetFields()
if (this.dataForm.id) {
this.getInfo()
}
})
},
// 封面设置
uploadPicture (name) {
this.cropperName = name
this.cropperModel = true
},
// 点击叉号,关闭弹窗
dialogClose () {
this.cropperModel = false
// 点击叉号,清除之前上传的图片
this.resourceUrl = ''
this.$emit('refreshDataList')
},
// 图片上传成功后
handleUploadSuccess (data) {
this.dataForm.coverUrl = data.url
this.courseUrl = `${window.SITE_CONFIG['apiURL']}` + data.url
this.cropperModel = false
// 清除之前上传的图片
this.resourceUrl = ''
this.$emit('refreshDataList')
},
// 默认头像
imgError() {
this.courseUrl = require('@/assets/img/course.png');
},
// 获取信息
getInfo () {
this.$http.get(`/cd/course/info/${this.dataForm.id}`).then(({ data: res }) => {
if (res.code !== 0) {
return this.$message.error(res.msg)
}
this.dataForm = {
...this.dataForm,
...res.data
}
if (res.data.coverUrl != null) {
let prefixUrl = `${window.SITE_CONFIG['apiURL']}`
this.courseUrl = prefixUrl + res.data.coverUrl
// 回显的图片路径
this.resourceUrl = res.data.coverUrl
}
}).catch(() => {})
},
// 上传文件
uploadHandle () {
this.uploadVisible = true
let type = 0
this.$nextTick(() => {
this.$refs.upload.init(type)
})
},
// 上传文件成功后,子组件回传到父组件资源id
uploadUrl (val) {
this.dataForm.coverUrl = val.resourceUrl
let prefixUrl = `${window.SITE_CONFIG['apiURL']}`
this.courseUrl = prefixUrl + val.resourceUrl
},
// 表单提交
dataFormSubmitHandle: debounce(function () {
this.$refs['dataForm'].validate((valid) => {
if (!valid) {
return false
}
this.$http[!this.dataForm.id ? 'post' : 'put']('/cd/course', this.dataForm).then(({ data: res }) => {
if (res.code !== 0) {
return this.$message.error(res.msg)
}
this.$message({
message: this.$t('prompt.success'),
type: 'success',
duration: 500,
onClose: () => {
this.visible = false
this.componentKey += 1;
this.$emit('refreshDataList')
}
})
}).catch(() => {})
})
}, 1000, { 'leading': true, 'trailing': false })
}
}
</script>
裁剪页面:
<template>
<div class="cropper-content">
<div class="cropper-box">
<div class="cropper">
<vue-cropper
ref="cropper"
:img="option.img"
:outputSize="option.outputSize"
:outputType="option.outputType"
:info="option.info"
:canScale="option.canScale"
:autoCrop="option.autoCrop"
:autoCropWidth="option.autoCropWidth"
:autoCropHeight="option.autoCropHeight"
:fixed="option.fixed"
:fixedNumber="option.fixedNumber"
:full="option.full"
:fixedBox="option.fixedBox"
:canMove="option.canMove"
:canMoveBox="option.canMoveBox"
:original="option.original"
:centerBox="option.centerBox"
:height="option.height"
:infoTrue="option.infoTrue"
:maxImgSize="option.maxImgSize"
:enlarge="option.enlarge"
:mode="option.mode"
@realTime="realTime"
@imgLoad="imgLoad">
</vue-cropper>
</div>
<!--底部操作工具按钮-->
<div class="footer-btn">
<div class="scope-btn">
<label class="btn" for="uploads" >选择封面</label>
<input type="file" id="uploads" style="position:absolute; clip:rect(0 0 0 0);" accept="image/png, image/jpeg, image/gif, image/jpg" @change="selectImg($event)">
<el-button size="mini" type="danger" plain icon="el-icon-zoom-in" @click="changeScale(1)">放大</el-button>
<el-button size="mini" type="danger" plain icon="el-icon-zoom-out" @click="changeScale(-1)">缩小</el-button>
<el-button size="mini" type="danger" plain @click="rotateLeft">↺ 左旋转</el-button>
<el-button size="mini" type="danger" plain @click="rotateRight">↻ 右旋转</el-button>
</div>
<div class="upload-btn">
<el-button size="mini" type="success" @click="uploadImg('blob')">上传封面 <i class="el-icon-upload"></i></el-button>
</div>
</div>
</div>
<!--预览效果图-->
<div class="show-preview">
<div :style="previews.div" class="preview">
<img :src="previews.url" :style="previews.img">
</div>
</div>
</div>
</template>
<script>
import { VueCropper } from 'vue-cropper'
import Cookies from 'js-cookie'
export default {
name: 'CropperImage',
components: {
VueCropper
},
props: ['Name','ResourceUrl'],
data () {
return {
name: this.Name,
resourceUrl: this.ResourceUrl,
previews: {},
option: {
img: '', // 裁剪图片的地址
outputSize: 1, // 裁剪生成图片的质量(可选0.1 - 1)
outputType: 'jpeg', // 裁剪生成图片的格式(jpeg || png || webp)
info: true, // 图片大小信息
canScale: true, // 图片是否允许滚轮缩放
autoCrop: true, // 是否默认生成截图框
autoCropWidth: 500, // 默认生成截图框宽度
autoCropHeight: 320, // 默认生成截图框高度
fixed: true, // 是否开启截图框宽高固定比例
fixedNumber: [25, 16], // 截图框的宽高比例
full: false, // false按原比例裁切图片,不失真
// fixedBox: true, // 固定截图框大小,不允许改变
canMove: false, // 上传图片是否可以移动
canMoveBox: true, // 截图框能否拖动
original: false, // 上传图片按照原始比例渲染
centerBox: false, // 截图框是否被限制在图片里面
height: true, // 是否按照设备的dpr 输出等比例图片
infoTrue: false, // true为展示真实输出图片宽高,false展示看到的截图框宽高
maxImgSize: 3000, // 限制图片最大宽度和高度
enlarge: 1, // 图片根据截图框输出比例倍数
mode: '500px 320px', // 图片默认渲染方式
filename: '',
//centerBox: false, // 截图框是否被限制在图片里面
fixed: false, // 是否开启截图框宽高固定比例
}
}
},
mounted() {
let prefixUrl = `${window.SITE_CONFIG['apiURL']}`
let url = prefixUrl + this.resourceUrl;
// 回传的数据是base64,所以在这里将接收到的图片路径转base64格式
this.toBase64(url)
},
methods: {
toBase64(imgUrl) {
// 一定要设置为let,不然图片不显示
let image = new Image();
// 解决跨域问题
image.setAttribute('crossOrigin', 'anonymous');
let imageUrl = imgUrl;
image.src = imageUrl
// image.onload为异步加载
image.onload = () => {
let canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
let context = canvas.getContext('2d');
context.drawImage(image, 0, 0, image.width, image.height);
let quality = 0.8;
// 这里的dataurl就是base64类型
// 使用toDataUrl将图片转换成jpeg的格式,不要把图片压缩成png,因为压缩成png后base64的字符串可能比不转换前的长!
let dataurl = canvas.toDataURL('image/jpeg', quality);
this.option.img = dataurl
}
},
// 初始化函数
imgLoad (msg) {
// console.log(msg)
},
// 图片缩放
changeScale (num) {
num = num || 1
this.$refs.cropper.changeScale(num)
},
// 向左旋转
rotateLeft () {
this.$refs.cropper.rotateLeft()
},
// 向右旋转
rotateRight () {
this.$refs.cropper.rotateRight()
},
// 实时预览函数
realTime (data) {
this.previews = data
},
// 选择图片 显示预览图
selectImg (e) {
let file = e.target.files[0]
this.filename = file.name
if (!/\.(jpg|jpeg|png|gif|JPG|PNG|GIF)$/.test(e.target.value)) {
this.$message({
message: '图片类型要求:jpeg、jpg、png',
type: 'error'
})
return false
}
// 转化为blob
let reader = new FileReader()
reader.onload = (e) => {
let data
if (typeof e.target.result === 'object') {
data = window.URL.createObjectURL(new Blob([e.target.result]))
} else {
data = e.target.result
}
this.option.img = data
}
// 转化为base64
reader.readAsDataURL(file)
},
// 上传图片
uploadImg (type) {
if (type === 'blob') {
// 获取截图的blob数据
this.$refs.cropper.getCropBlob((data) => {
let formData = new FormData()
formData.append('file', data, this.filename)
this.$http({
url: `${window.SITE_CONFIG['apiURL']}/cd/resource/upload?token=${Cookies.get('token')}`,
method: 'post',
data: formData
}).then(({data}) => {
if (data.code === 0) {
this.$message({
message: '上传成功',
type: 'success'
})
console.log("-------",data)
let imgInfo = {
name: this.Name,
url: data.data.resourceUrl
}
this.$emit('uploadImgSuccess', imgInfo)
} else {
this.$message({
message: '文件服务异常,请联系管理员!',
type: 'error'
})
}
})
})
}
}
}
}
</script>
<style scoped lang="scss">
.cropper-content{
display: flex;
display: -webkit-flex;
justify-content: flex-end;
.cropper-box{
flex: 1;
width: 100%;
.cropper{
width: auto;
height: 400px;
}
}
.show-preview{
flex: 1;
-webkit-flex: 1;
display: flex;
display: -webkit-flex;
justify-content: center;
.preview{
overflow: hidden;
border:1px solid #67c23a;
background: #cccccc;
}
}
}
.footer-btn{
margin-top: 30px;
display: flex;
display: -webkit-flex;
justify-content: flex-end;
.scope-btn{
display: flex;
display: -webkit-flex;
justify-content: space-between;
padding-right: 10px;
}
.upload-btn{
flex: 1;
-webkit-flex: 1;
display: flex;
display: -webkit-flex;
justify-content: center;
}
.btn {
outline: none;
display: inline-block;
line-height: 1;
white-space: nowrap;
cursor: pointer;
-webkit-appearance: none;
text-align: center;
-webkit-box-sizing: border-box;
box-sizing: border-box;
outline: 0;
-webkit-transition: .1s;
transition: .1s;
font-weight: 500;
padding: 8px 15px;
font-size: 12px;
border-radius: 3px;
color: #fff;
background-color: #409EFF;
border-color: #409EFF;
margin-right: 10px;
}
}
</style>