You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

295 lines
7.3 KiB
Vue

4 months ago
<!--
上传图片组件 基于uview upload
:action STring 上传文件的接口 可以不传 会有当前默认的参数
:maxSize String 最大尺寸
:maxNum String 最大数量
:upHeaderFild String 请求后端字段头
:echoPicList Array 回显图片列表
:headerWithJti Object 请求头 可以不传 会有当前默认的参数
:showProgress Boolean 是否显示进度条
:limitTypeList Array 限制文件类型 ['png', 'jpg', 'jpeg']
:showTipsNumber Boolean 是否显示上传数量限制
@okCallBack fn 回调上传列表
:oneNumberStyle Boolean 当图片最大值为1时可以通过次来使数量显示紧挨后面
-->
<template>
<view style="display: flex;flex-wrap: wrap;" :class="{agreementImage:oneNumberStyle}" class="agreementImage">
<span v-for="(item,index) in value" :key="index" :style="{width:width,height:height,marginRight: (value.length == index + 1 )? '' : '16rpx',marginBottom:(value.length == index + 1 )? '' : '10rpx',position:'relative'}" >
<u-image :fade="false" :src="item[filePath]" width="100%" height="100%" @click="imageClick(item,index)">
<image slot="loading" :style="{width:width,height:height}" :src="loadSrcFn(item[filePath])"></image>
</u-image>
<view class="del-icon" v-if="delIcon" @tap.stop="deleteItem(item,index)">
<u-icon name="close" color="#fff" size="15" ></u-icon>
</view>
</span>
<u-upload ref="uUpload"
:width="width"
:height="height"
:action="actionCompute"
:max-size="maxSize * 1024 * 1024"
:max-count="maxNum - value.length"
:show-upload-list="false"
:name="upHeaderFild"
:file-list="oldList"
:header="headerWithJtiCompute"
:show-progress='showProgress'
:uploadText="uploadText"
defaultMaxCountFlag
echoFlag
@on-uploaded="loadShow = false"
@on-error="upError"
@on-success="imageSuccess"
@on-choose-complete="imageComplete"
:limitType="limitTypeList"
></u-upload>
<view class="number-tips end" v-if="showTipsNumber">
({{value.length}}/{{maxNum}})
</view>
<my-loading :load-show="loadShow" ref="auiLoading" :mask="true"></my-loading>
</view>
</template>
<script>
// import "common/lixing-pbulic.scss"
export default{
data(){
return{
// 上传数量
certificatesNum:"0",
// 当前图片列表 会在每次上传删除时回调给父组件
nowList:[],
// 回显图片
oldList:[],
// 要删除的图片
removeList:[],
loadShow:false,
lists:[],//本次上传成功的本地图片列表用来当作加载中图片回显用
}
},
computed:{
actionCompute(){
if(!this.action){
return this.$baseURL.baseURL + '/base/file/upload'
}else{
return this.action
}
},
headerWithJtiCompute(){
if(!this.headerWithJti){
return {
"jti":this.vuex_user.jti // token验证
}
}else{
return this.headerWithJti
}
}
},
props:{
value:{
type: Array,
default:() => {
return []
}
},
width:{
type:String,
default:'200rpx'
},
height:{
type:String,
default:'200rpx'
},
// 上传成功后文件id 的 key 回显文件的key
fileId: {
type: String,
default: "fileId",
},
// 上传成功后文件path 的 key 回显文件的key
filePath: {
type: String,
default: "filePath",
},
thumbnailPath:{
type: String,
default: "thumbnailPath",
},
// 是否可删除
delIcon:{
type:Boolean,
default:true
},
// 上传成功是否显示sort值
sortFlag:{
type:Boolean,
default:true
},
// 是否需要缩略图
thumbnailFlag:{
type:Boolean,
default:false
},
loadSrc:{
type:String,
default:"http://file.hecrab.com/crab-net/yxs-loading.gif"
},
// 上传文件的接口
action:{
type:String,
default:''
},
// 最大尺寸
maxSize:{
type:[String,Number],
default: '5' //'5 * 1024 * 1024'
},
// 最大数量
maxNum:{
type:[String,Number],
default:'1'
},
// 请求后端字段头
upHeaderFild:{
type:String,
default:'multipartFile'
},
// 回显图片列表
echoPicList:{
type:Array,
default:()=>{
return []
}
},
// 请求头
headerWithJti:{
type:Object,
default:()=>{
return null
}
},
// 是否显示进度条
showProgress:{
type:Boolean,
default:true
},
// 限制文件类型
limitTypeList:{
type:Array,
default:()=>{
return ['png', 'jpg', 'jpeg']
}
},
// 是否显示上传数量限制
showTipsNumber:{
type:Boolean,
default:true
},
oneNumberStyle:{
type:Boolean,
default:false
},
// 上传区域的提示文字
uploadText: {
type: String,
default: '选择图片'
},
},
methods:{
upload(){
this.$refs.uUpload.upload()
},
// 删除图片事件
deleteItem(item, index){
uni.showModal({
title:"提示",
content:"您确定要删除此项吗",
success:res=>{
if(res.confirm){
let list = JSON.parse(JSON.stringify(this.value))
list.splice(index , 1);
this.$emit('input', list)
}
}
})
},
// 上传成功
imageSuccess(res, index, file, name) {
if(!res.flag){
// this.loadShow = false
return this.myError(res.msg);
}
if(this.value.length >= this.maxNum) return this.$u.toast("超出上传图片数量!")
let successImg = {
[this.fileId]: res.data.id,
[this.filePath]: res.data.fullPath,
}
if(this.sortFlag)successImg.sort = this.value.length
if(this.thumbnailFlag){
successImg[this.thumbnailPath] = res.data.thumbnailPath
}
let list = JSON.parse(JSON.stringify(this.value))
list.push(successImg)
this.$emit('input', list)
// this.loadShow = false
this.$emit("okCallBack" , list);
this.lists = file
console.log(file)
},
imageComplete(){
this.removeList=[]
this.loadShow = true
},
imageClick(item,index){
let list = this.value.map((item) => {
return item[this.filePath]
});
uni.previewImage({
urls: list,
current:index
});
},
// 抛错
upError(res, index, lists, name){
this.loadShow = false
// this.$u.toast(res)
},
// 如果找到了本地图片路径用本地路径加载图片 否则用默认加载中图片
loadSrcFn(path){
let index = this.lists.findIndex(item=>{
return item.response && item.response.data && item.response.data.fullPath == path
})
return index > -1 ? this.lists[index].url || this.loadSrc : this.loadSrc
}
}
}
</script>
<style lang="scss" scoped>
.number-tips{
font-size: 28rpx;
color: #999999;
text-align: right;
}
.del-icon{
position: absolute;
top: 0;
right: 0;
width: 34rpx;
height: 34rpx;
background-color: #fa3534;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
}
.agreementImage{
display: flex;
.end{
display: flex;
align-items: flex-end;
flex: 1;
justify-content: flex-end;
}
}
</style>