@@ -9,7 +9,8 @@ | |||||
<view class="cu-form-group" style="border-top: none;"> | <view class="cu-form-group" style="border-top: none;"> | ||||
<view class="grid col-4 grid-square flex-sub"> | <view class="grid col-4 grid-square flex-sub"> | ||||
<view v-for="(file, index) in value" :key="index" class="bg-img"> | |||||
<view v-for="(file, index) in value" :key="index" class="bg-img" style="position: relative;"> | |||||
<view v-if="file.noUpdated" class="mask"></view> | |||||
<image | <image | ||||
v-if="isImgFile(file.type)" | v-if="isImgFile(file.type)" | ||||
@click="fileClick(index)" | @click="fileClick(index)" | ||||
@@ -20,11 +21,14 @@ | |||||
<view v-else-if="isDocFile(file.type)" @click="fileClick(index)" class="file-icon solids"> | <view v-else-if="isDocFile(file.type)" @click="fileClick(index)" class="file-icon solids"> | ||||
<l-icon type="text" /> | <l-icon type="text" /> | ||||
</view> | </view> | ||||
<view v-else class="file-icon solids"><l-icon type="text" /></view> | |||||
<view v-else class="file-icon solids" @click="fileClick(index)"><l-icon type="text" /></view> | |||||
<view v-if="!readonly" @click.stop="delFile(index)" class="cu-tag bg-red" style="height: 24px; width: 24px;"> | |||||
<view v-if="!readonly" @click.stop="delFile(index,file.uid)" class="cu-tag bg-red" style="height: 24px; width: 24px;"> | |||||
<l-icon type="close" color="white" style="width: 18px; height: 24px; font-size: 24px;" /> | <l-icon type="close" color="white" style="width: 18px; height: 24px; font-size: 24px;" /> | ||||
</view> | </view> | ||||
<view class="fileName"> | |||||
<text>{{file.name}}</text> | |||||
</view> | |||||
</view> | </view> | ||||
<view v-if="!readonly && value.length < Number(number)" @click="chooseFile" class="solids"> | <view v-if="!readonly && value.length < Number(number)" @click="chooseFile" class="solids"> | ||||
@@ -54,8 +58,7 @@ export default { | |||||
isImgFile(type) { | isImgFile(type) { | ||||
const typeString = (type || '').toLowerCase() | const typeString = (type || '').toLowerCase() | ||||
//return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'image'].includes(typeString) | |||||
return true; | |||||
return ['jpg','image/jpg','jpeg','image/jpeg', 'png', 'image/png','gif', 'image/gif','bmp', 'image/bmp','webp', 'image/webp','image'].includes(typeString) | |||||
}, | }, | ||||
isDocFile(type) { | isDocFile(type) { | ||||
@@ -63,12 +66,17 @@ export default { | |||||
return ['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'pdf'].includes(typeString) | return ['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'pdf'].includes(typeString) | ||||
}, | }, | ||||
delFile(index) { | |||||
async delFile(index,fileId) { | |||||
if (!(await this.CONFIRM('删除文件', '确定要删除该文件吗?', true))) { | |||||
return | |||||
} | |||||
const newList = JSON.parse(JSON.stringify(this.value)) | const newList = JSON.parse(JSON.stringify(this.value)) | ||||
newList.splice(index, 1) | newList.splice(index, 1) | ||||
this.$emit('input', newList) | this.$emit('input', newList) | ||||
this.$emit('change') | this.$emit('change') | ||||
this.$emit('del') | this.$emit('del') | ||||
//物理删除 | |||||
this.DELETE_FILE(fileId); | |||||
}, | }, | ||||
chooseFile() { | chooseFile() { | ||||
@@ -89,60 +97,84 @@ export default { | |||||
// #endif | // #endif | ||||
// #ifndef MP-DINGTALK | // #ifndef MP-DINGTALK | ||||
uni.chooseImage({ | |||||
count: Number(this.number), | |||||
sizeType: ['original', 'compressed'], | |||||
sourceType: ['album', 'camera'], | |||||
success: ({ tempFilePaths }) => { | |||||
const newList = JSON.parse(JSON.stringify(this.value || [])).concat( | |||||
tempFilePaths//.map(t => ({ path: t, type: this.getFileExt(t) })) | |||||
) | |||||
this.$emit('input', newList) | |||||
this.$emit('change', newList) | |||||
this.$emit('add') | |||||
} | |||||
}) | |||||
// uni.chooseFile({ | |||||
// count: Number(this.number), | |||||
// sizeType: ['original', 'compressed'], | |||||
// sourceType: ['album', 'camera'], | |||||
// success: ({ tempFilePaths }) => { | |||||
// const newList = JSON.parse(JSON.stringify(this.value || [])).concat( | |||||
// tempFilePaths//.map(t => ({ path: t, type: this.getFileExt(t) })) | |||||
// ) | |||||
// this.$emit('input', newList) | |||||
// this.$emit('change', newList) | |||||
// this.$emit('add') | |||||
// } | |||||
// }) | |||||
uni.chooseFile({ | |||||
count: Number(this.number), | |||||
sizeType: ['original', 'compressed'], | |||||
sourceType: ['album', 'camera'], | |||||
success: ({ tempFilePaths,tempFiles }) => { | |||||
const newList = JSON.parse(JSON.stringify(this.value || [])).concat( | |||||
// tempFilePaths//.map(t => ({ path: t, type: this.getFileExt(t) })) | |||||
tempFilePaths.map((t,i) => ({ path: t, type: tempFiles[i].type, size:tempFiles[i].size, name:tempFiles[i].name, noUpdated:true} )) | |||||
) | |||||
this.$emit('input', newList) | |||||
this.$emit('change', newList) | |||||
this.$emit('add') | |||||
} | |||||
}) | |||||
// #endif | // #endif | ||||
}, | }, | ||||
async fileClick(index) { | async fileClick(index) { | ||||
// if(typeof this.value[index] == "string"){ | |||||
// uni.previewImage({ urls: this.value.filter(item=>typeof this.value[index] == "string"), current: this.value[index] }) | |||||
// return | |||||
// } | |||||
const { path, type, uid, size = 0 } = this.value[index] | const { path, type, uid, size = 0 } = this.value[index] | ||||
if (this.isImgFile(type)) { | |||||
uni.previewImage({ urls: [path], current: path }) | |||||
} else if (this.isDocFile(type)) { | |||||
// #ifndef H5 || MP-DINGTALK | |||||
if (size >= 50 * 1024 * 1024) { | |||||
this.TOAST('小程序端无法下载超过50MB的文件,此文件大小为${size}KB,超过限制') | |||||
return | |||||
} | |||||
// #endif | |||||
// #ifndef MP-DINGTALK | |||||
const tempFilePath = await this.HTTP_DOWNLOAD(uid) | |||||
uni.openDocument({ filePath: tempFilePath, fileType: type }) | |||||
// #endif | |||||
// #ifdef MP-DINGTALK | |||||
this.TOAST('钉钉小程序只支持查看图片文件') | |||||
// #endif | |||||
} else { | |||||
// #ifndef MP-DINGTALK | |||||
this.TOAST('小程序端只支持打开图片和文档(word、pdf等)文件') | |||||
// #endif | |||||
// #ifdef MP-DINGTALK | |||||
this.TOAST('钉钉小程序只支持查看图片文件') | |||||
// #endif | |||||
// #ifdef APP-VUE | |||||
const tempFilePath = await this.HTTP_DOWNLOAD(uid) | |||||
uni.openDocument({ filePath: tempFilePath, fileType: type }) | |||||
// #endif | |||||
// #ifdef H5 | |||||
await this.HTTP_DOWNLOAD(uid) | |||||
// #endif | |||||
} | |||||
if (this.isImgFile(type)) { | |||||
uni.previewImage({ urls: [path], current: path }) | |||||
}else{ | |||||
uni.openDocument({ filePath: path, fileType: type }) | |||||
} | |||||
// if (this.isImgFile(type)) { | |||||
// uni.previewImage({ urls: [path], current: path }) | |||||
// } else if (this.isDocFile(type)) { | |||||
// // #ifndef H5 || MP-DINGTALK | |||||
// if (size >= 50 * 1024 * 1024) { | |||||
// this.TOAST('小程序端无法下载超过50MB的文件,此文件大小为${size}KB,超过限制') | |||||
// return | |||||
// } | |||||
// // #endif | |||||
// // #ifndef MP-DINGTALK | |||||
// const tempFilePath = await this.HTTP_DOWNLOAD(uid) | |||||
// uni.openDocument({ filePath: tempFilePath, fileType: type }) | |||||
// // #endif | |||||
// // #ifdef MP-DINGTALK | |||||
// this.TOAST('钉钉小程序只支持查看图片文件') | |||||
// // #endif | |||||
// } else { | |||||
// // #ifndef MP-DINGTALK | |||||
// this.TOAST('小程序端只支持打开图片和文档(word、pdf等)文件') | |||||
// // #endif | |||||
// // #ifdef MP-DINGTALK | |||||
// this.TOAST('钉钉小程序只支持查看图片文件') | |||||
// // #endif | |||||
// // #ifdef APP-VUE | |||||
// const tempFilePath = await this.HTTP_DOWNLOAD(uid) | |||||
// uni.openDocument({ filePath: tempFilePath, fileType: type }) | |||||
// // #endif | |||||
// // #ifdef H5 | |||||
// await this.HTTP_DOWNLOAD(uid) | |||||
// // #endif | |||||
// } | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -153,4 +185,29 @@ export default { | |||||
line-height: 100%; | line-height: 100%; | ||||
position: static; | position: static; | ||||
} | } | ||||
.fileName{ | |||||
padding: 2px 2px; | |||||
margin-bottom: 2px; | |||||
text-align: center; | |||||
position: absolute; | |||||
bottom: 0px; | |||||
width: 100%; | |||||
background: rgba(0,0,0,0.2); | |||||
color: #fff; | |||||
font-size: 12px; | |||||
text-overflow: ellipsis; | |||||
overflow: hidden; | |||||
white-space: nowrap; | |||||
} | |||||
.mask{ | |||||
position: absolute; | |||||
top: 0;left: 0; | |||||
width: 100%; | |||||
height: 100%; | |||||
// background: rgba(255,252,153,0.2); | |||||
background: rgba(0,0,0,0.7); | |||||
z-index: 100; | |||||
pointer-events: none; | |||||
} | |||||
</style> | </style> |
@@ -2,26 +2,27 @@ | |||||
<view class="cu-form-group"> | <view class="cu-form-group"> | ||||
<view class="grid col-4 grid-square flex-sub"> | <view class="grid col-4 grid-square flex-sub"> | ||||
<view | <view | ||||
v-for="(path, index) in value" | |||||
@tap="viewImg" | |||||
v-for="(item, index) in imgList" | |||||
@tap="viewImg(index)" | |||||
:key="index" | :key="index" | ||||
class="bg-img" | class="bg-img" | ||||
> | > | ||||
<!-- {{item.id?CONFIG('webHost')+item.url:item.url}} --> | |||||
<image | <image | ||||
v-if="showfile()" | v-if="showfile()" | ||||
:src="path.path ? path.path : path" | |||||
:src="item.id?CONFIG('webHost')+item.url:item.url" | |||||
mode="aspectFill" | mode="aspectFill" | ||||
></image> | ></image> | ||||
<view v-if="!readonly" @tap.stop="delImg(index)" class="cu-tag bg-red"> | |||||
<view v-if="!readonly" @tap.stop="delImg(index)" class="cu-tag bg-red" style="width: 18px; height: 18px; font-size: 24px"> | |||||
<l-icon | <l-icon | ||||
type="close" | type="close" | ||||
style="width: 18px; height: 24px; font-size: 24px" | |||||
style="width: 18px; height: 18px; font-size: 12px" | |||||
/> | /> | ||||
</view> | </view> | ||||
</view> | </view> | ||||
<view | <view | ||||
v-if="!readonly && value.length < Number(number)" | |||||
v-if="!readonly && imgList.length < Number(number)" | |||||
@tap="chooseImg" | @tap="chooseImg" | ||||
class="solids" | class="solids" | ||||
> | > | ||||
@@ -40,44 +41,190 @@ export default { | |||||
readonly: {}, | readonly: {}, | ||||
value: { default: () => [] }, | value: { default: () => [] }, | ||||
}, | }, | ||||
data(){ | |||||
return{ | |||||
imgList:[], | |||||
} | |||||
}, | |||||
methods: { | methods: { | ||||
delImg(index) { | delImg(index) { | ||||
const newList = JSON.parse(JSON.stringify(this.value)); | |||||
const newList = JSON.parse(JSON.stringify(this.imgList)); | |||||
newList.splice(index, 1); | newList.splice(index, 1); | ||||
this.imgList = newList | |||||
this.$emit("update:value", newList); | |||||
this.$emit("input", newList); | this.$emit("input", newList); | ||||
this.$emit("change"); | this.$emit("change"); | ||||
this.$emit("del"); | this.$emit("del"); | ||||
}, | }, | ||||
showfile() { | showfile() { | ||||
console.log(this.value); | |||||
return true; | return true; | ||||
}, | }, | ||||
chooseImg() { | chooseImg() { | ||||
uni.chooseImage({ | uni.chooseImage({ | ||||
count: Number(this.number), | |||||
count: (Number(this.number) - this.imgList.length), | |||||
sizeType: ["original", "compressed"], | sizeType: ["original", "compressed"], | ||||
sourceType: ["album", "camera"], | sourceType: ["album", "camera"], | ||||
success: ({ tempFilePaths }) => { | |||||
const newList = JSON.parse(JSON.stringify(this.value || [])).concat( | |||||
tempFilePaths | |||||
success: (res) => { | |||||
let {tempFilePaths,tempFiles} = res | |||||
if(!this.validate(tempFiles))return | |||||
const newList = JSON.parse(JSON.stringify(this.imgList || [])).concat( | |||||
tempFilePaths.map(item=>{ | |||||
return{ | |||||
url:item, | |||||
id:'' | |||||
} | |||||
}) | |||||
); | ); | ||||
//this.$parent.HTTP_UPLOAD(tempFilePaths[0]); | |||||
this.imgList = newList | |||||
this.$emit("update:value", newList); | |||||
this.$emit("input", newList); | this.$emit("input", newList); | ||||
this.$emit("change"); | |||||
this.$emit("change",newList); | |||||
this.$emit("add"); | this.$emit("add"); | ||||
}, | }, | ||||
}); | }); | ||||
}, | }, | ||||
uploadImage(){ | |||||
// 单图上传 | |||||
return new Promise(async (reslove,reject)=>{ | |||||
let hasNotUpdatedList = this.imgList.every(item=>item.id) | |||||
if(hasNotUpdatedList){ | |||||
reslove(this.imgList) | |||||
} | |||||
if(this.imgList.length){ | |||||
var postData = { | |||||
Base64Url: await this.imgToBase64(this.imgList[0].url) | |||||
} | |||||
this.HTTP_POST('StuInfoFresh/savePhoto', postData, '图片上传失败!').then((data) => { | |||||
if (data) { | |||||
reslove([{ | |||||
url:data.Url, | |||||
id:data.AnnexesFileId | |||||
}]) | |||||
}else{ | |||||
reject('图片上传失败!') | |||||
} | |||||
}) | |||||
}else{ | |||||
reslove("") | |||||
} | |||||
}) | |||||
}, | |||||
/** | |||||
* @description 控制promise.all并发数量 | |||||
* @param limit 并发数 | |||||
* @param array 参数列表 | |||||
* @param apiFn 执行函数 | |||||
* @returns {Promise<Awaited<unknown>[]>} | |||||
*/ | |||||
async promiseAllLimit(limit, array, apiFn) { | |||||
const ret = [] // 用于存放所有的promise实例 | |||||
const executing = [] // 用于存放目前正在执行的promise | |||||
for (const item of array) { | |||||
const p = apiFn(item) | |||||
ret.push(p) | |||||
if (limit <= array.length) { | |||||
// then回调中,当这个promise状态变为fulfilled后,将其从正在执行的promise列表executing中删除 | |||||
const e = p.then(() => executing.splice(executing.indexOf(e), 1)) | |||||
executing.push(e) | |||||
if (executing.length >= limit) { | |||||
// 一旦正在执行的promise列表数量等于限制数,就使用Promise.race等待某一个promise状态发生变更, | |||||
// 状态变更后,就会执行上面then的回调,将该promise从executing中删除, | |||||
// 然后再进入到下一次for循环,生成新的promise进行补充 | |||||
await Promise.race(executing) | |||||
} | |||||
} | |||||
} | |||||
return Promise.all(ret) | |||||
}, | |||||
imgToBase64(url){ | |||||
return new Promise((resolve,reject)=>{ | |||||
if(!url){ | |||||
resolve("") | |||||
} | |||||
var canvas = document.createElement('canvas'), | |||||
ctx = canvas.getContext('2d'), | |||||
img = new Image; | |||||
img.crossOrigin = 'Anonymous'; | |||||
img.onload = function () { | |||||
canvas.height = img.height; | |||||
canvas.width = img.width; | |||||
ctx.drawImage(img, 0, 0); | |||||
var dataURL = canvas.toDataURL('image/png'); | |||||
canvas = null; | |||||
resolve(dataURL) | |||||
}; | |||||
img.src = url; | |||||
}) | |||||
}, | |||||
validate(array){ | |||||
// let type = array.every(item=>{ | |||||
// return item.type && item.type.substring(0,6) == "image/" | |||||
// }) | |||||
// if(!type){ | |||||
// this.TOAST('文件类型错误'); | |||||
// return false | |||||
// } | |||||
let size = array.every(item=>{ | |||||
return item.size && item.size <= 100 * 1024 * 1024 | |||||
}) | |||||
if(!size){ | |||||
this.TOAST('文件大小不得超过100M'); | |||||
return false | |||||
} | |||||
return true | |||||
}, | |||||
viewImg(index) { | viewImg(index) { | ||||
uni.previewImage({ | uni.previewImage({ | ||||
urls: this.value, | |||||
current: this.value[index], | |||||
urls: this.imgList.map(item=>item.id?this.CONFIG('webHost')+item.url:item.url), | |||||
current: this.imgList[index].id?this.CONFIG('webHost')+this.imgList[index].url:this.imgList[index].url, | |||||
}); | }); | ||||
}, | }, | ||||
// previewFile() { | |||||
// var file = document.querySelector('input[type=file]').files[0]; | |||||
// var reader = new FileReader(); | |||||
// // fileReader.readAsDataURL(blob); | |||||
// // fileReader.onerror = () => { | |||||
// // reject(new Error('blobToBase64 error')); | |||||
// // }; | |||||
// // var encodedData = window.btoa("Hello, world"); | |||||
// reader.onloadend = function () { | |||||
// //$('#PhotoImg').attr('src', reader.result); | |||||
// var postData = { | |||||
// Base64Url: reader.result | |||||
// } | |||||
// this.HTTP_POST(config.webapi + "StuInfoFresh/savePhoto", postData, (data) => { | |||||
// if (data) { | |||||
// $('#Photo').val(data.AnnexesFileId); | |||||
// $('#PhotoImg').attr('src', config.web + data.Url); | |||||
// } else { | |||||
// learun.layer.toast('采集照片信息失败!'); | |||||
// } | |||||
// }); | |||||
// } | |||||
// if (file) { | |||||
// reader.readAsDataURL(file); | |||||
// } | |||||
// }, | |||||
}, | }, | ||||
created() { | |||||
console.log(123) | |||||
this.imgList = JSON.parse(JSON.stringify(this.value.map(item=>{ | |||||
item.isUploaded = true | |||||
return item | |||||
}))) | |||||
// [{url:"",id:""}] | |||||
} | |||||
}; | }; | ||||
</script> | </script> |
@@ -0,0 +1,217 @@ | |||||
<template> | |||||
<view> | |||||
<view class="cu-form-group" style="border-bottom: none; padding-bottom: 0;"> | |||||
<view class="title"> | |||||
<text v-if="required" class="lr-required">*</text> | |||||
{{ title || '' }} | |||||
</view> | |||||
</view> | |||||
<view class="cu-form-group"> | |||||
<view class="grid col-4 grid-square flex-sub"> | |||||
<view v-for="(item, index) in imgList" @tap="viewImg(item)" :key="index" class="bg-img"> | |||||
<image v-if="showfile()&&item&&(typeof item == 'string'||isImage(item.type))" :src="item.url?CONFIG('webHost') + item.url:item" mode="aspectFill"> | |||||
</image> | |||||
<l-icon v-if="showfile()&&!isImage(item.type)" type="text" /> | |||||
<text class="file-name">{{item.name}}</text> | |||||
<view v-if="!readonly" @tap.stop="delImg(index)" class="cu-tag bg-red" | |||||
style="width: 18px; height: 18px; font-size: 24px"> | |||||
<l-icon type="close" style="width: 18px; height: 18px; font-size: 12px" /> | |||||
</view> | |||||
</view> | |||||
<view v-show="!readonly && imgList.length < Number(number)&&isShow" class="solids"> | |||||
<l-icon type="file" /> | |||||
<lsj-upload ref="lsjUpload" height="80px" width="100%" :size="20" :option="{}" :count="1" | |||||
@change="chooseChange" style="opacity: 0;"></lsj-upload> | |||||
</view> | |||||
</view> | |||||
</view> | |||||
</view> | |||||
</template> | |||||
<script> | |||||
/** | |||||
* 附件上传组件 | |||||
* 直接选择手机文件 | |||||
* | |||||
* 注意:可以是图片、文档、等; | |||||
*/ | |||||
export default { | |||||
props: { | |||||
number: { | |||||
default: 1 | |||||
}, | |||||
readonly: {}, | |||||
value: { | |||||
default: () => [] | |||||
}, | |||||
folderId: {}, | |||||
title: {}, | |||||
required: {} | |||||
}, | |||||
data() { | |||||
return { | |||||
isShow: false, | |||||
imgList: [], | |||||
} | |||||
}, | |||||
methods: { | |||||
chooseChange(files) { | |||||
let array = Array.from(files); | |||||
if (array.length) { | |||||
this.$refs.lsjUpload.clear() | |||||
} | |||||
let tempFilePaths = [], | |||||
tempFiles = []; | |||||
array.forEach(item => { | |||||
tempFilePaths.push(item[1].path) | |||||
tempFiles.push(item[1].file) | |||||
}) | |||||
this.chooseChangeback(tempFilePaths, tempFiles) | |||||
}, | |||||
delImg(index) { | |||||
this.CONFIRM("", "是否确认删除?", true).then(res => { | |||||
if(!res)return | |||||
this.LOADING('正在删除…'); | |||||
const newList = JSON.parse(JSON.stringify(this.imgList)); | |||||
this.HTTP_POST('/learun/adms/annexes/wxdelete', this.imgList[index].id, "文件删除失败").then((data) => { | |||||
this.HIDE_LOADING(); | |||||
if (data) { | |||||
newList.splice(index, 1); | |||||
this.imgList = newList | |||||
this.$emit("update:value", newList); | |||||
this.$emit("input", newList); | |||||
this.$emit("change"); | |||||
this.$emit("del"); | |||||
} | |||||
}) | |||||
}) | |||||
}, | |||||
showfile() { | |||||
return true; | |||||
}, | |||||
async chooseChangeback(tempFilePaths, tempFiles) { | |||||
let uploadImageRes = await this.uploadImage(tempFilePaths[0], tempFiles[0] ? tempFiles[0].name : "") | |||||
let newList = this.imgList || [] | |||||
if (uploadImageRes) { | |||||
//请求‘获取附件列表’接口 | |||||
let data = await this.FETCH_FILEList(uploadImageRes); | |||||
if(data){ | |||||
newList = data.map(t=>({ | |||||
id: t.F_Id, | |||||
name: t.F_FileName, | |||||
url: t.F_FilePath.substring(t.F_FilePath.indexOf('Resource')), | |||||
type: t.F_FileType, | |||||
folderid:t.F_FolderId, | |||||
})) | |||||
} | |||||
} | |||||
this.imgList = newList | |||||
this.$emit("update:value", newList); | |||||
this.$emit("input", newList); | |||||
this.$emit("change", newList); | |||||
}, | |||||
uploadImage(url, name) { | |||||
if (!url) return | |||||
// 文件上传 | |||||
return new Promise(async (reslove, reject) => { | |||||
this.LOADING('正在上传…'); | |||||
let params = name ? { | |||||
folderId: this.folderId, | |||||
name | |||||
} : { | |||||
folderId: this.folderId | |||||
} | |||||
this.HTTP_UPLOAD2('/learun/adms/annexes/wxuploadinsingle', url, params).then((data) => { | |||||
this.HIDE_LOADING(); | |||||
this.$refs.lsjUpload.show() | |||||
if (data) { | |||||
reslove(data) | |||||
} else { | |||||
reject('上传失败!') | |||||
} | |||||
}) | |||||
}) | |||||
}, | |||||
validate(array) { | |||||
// let type = array.every(item=>{ | |||||
// return item.type && item.type.substring(0,6) == "image/" | |||||
// }) | |||||
// if(!type){ | |||||
// this.TOAST('文件类型错误'); | |||||
// return false | |||||
// } | |||||
let size = array.every(item => { | |||||
return item.size && item.size <= 200 * 1024 * 1024 | |||||
}) | |||||
if (!size) { | |||||
this.TOAST('文件大小不得超过200M'); | |||||
return false | |||||
} | |||||
return true | |||||
}, | |||||
isImage(type) { | |||||
if (type && type.length) { | |||||
return ["png", "jpg"].includes(type.substring(type.length - 3, type.length)) | |||||
} else { | |||||
return false | |||||
} | |||||
}, | |||||
viewImg(item) { | |||||
if (!this.isImage(item.type)) { | |||||
window.location.href = this.CONFIG("webHost") + item.url | |||||
} else { | |||||
uni.previewImage({ | |||||
urls: [this.CONFIG('webHost') + item.url], | |||||
current: this.CONFIG('webHost') + item.url | |||||
}); | |||||
} | |||||
}, | |||||
}, | |||||
created() { | |||||
// console.log(this.value) | |||||
this.imgList = JSON.parse(JSON.stringify(this.value.map(item => { | |||||
return { | |||||
id: item.F_Id, | |||||
name: item.F_FileName, | |||||
url: item.F_FilePath.substring(item.F_FilePath.indexOf('Resource')), | |||||
type: item.F_FileType, | |||||
folderid:item.F_FolderId, | |||||
} | |||||
}))) | |||||
this.$nextTick(() => { | |||||
this.isShow = true | |||||
}) | |||||
} | |||||
}; | |||||
</script> | |||||
<style scoped> | |||||
.file-name { | |||||
position: absolute; | |||||
bottom: 0; | |||||
width: 100%; | |||||
color: #606266; | |||||
font-size: 12px; | |||||
text-align: center; | |||||
background-color: rgba(255, 255, 255, 0.6); | |||||
text-overflow: ellipsis; | |||||
overflow: hidden; | |||||
white-space: nowrap; | |||||
} | |||||
</style> |
@@ -0,0 +1,211 @@ | |||||
<template> | |||||
<view> | |||||
<view class="cu-form-group" style="border-bottom: none; padding-bottom: 0;"> | |||||
<view class="title"> | |||||
<text v-if="required" class="lr-required">*</text> | |||||
{{ title || '' }} | |||||
</view> | |||||
</view> | |||||
<view class="cu-form-group"> | |||||
<view class="grid col-4 grid-square flex-sub"> | |||||
<view v-for="(item, index) in imgList" @tap="viewImg(item)" :key="index" class="bg-img"> | |||||
<image v-if="showfile()&&item&&(typeof item == 'string'||isImage(item.type))" :src="item.url?CONFIG('webHost') + item.url:item" mode="aspectFill"> | |||||
</image> | |||||
<l-icon v-if="showfile()&&!isImage(item.type)" type="text" /> | |||||
<text class="file-name">{{item.name}}</text> | |||||
<view v-if="!readonly" @tap.stop="delImg(index)" class="cu-tag bg-red" | |||||
style="width: 18px; height: 18px; font-size: 24px"> | |||||
<l-icon type="close" style="width: 18px; height: 18px; font-size: 12px" /> | |||||
</view> | |||||
</view> | |||||
<view v-if="!readonly && imgList.length < Number(number)" @click="chooseFile" class="solids"> | |||||
<l-icon type="file" /> | |||||
</view> | |||||
</view> | |||||
</view> | |||||
</view> | |||||
</template> | |||||
<script> | |||||
/** | |||||
* 附件上传组件 | |||||
* 使用相机拍摄 和 从相册选图 | |||||
* | |||||
* 注意:可以选择图片;如果选择文档的话则是从手机的‘文件管理’里面去选择,有可能会找不到文档; | |||||
*/ | |||||
export default { | |||||
props: { | |||||
number: { | |||||
default: 1 | |||||
}, | |||||
readonly: {}, | |||||
value: { | |||||
default: () => [] | |||||
}, | |||||
folderId: {}, | |||||
title: {}, | |||||
required: {} | |||||
}, | |||||
data() { | |||||
return { | |||||
isShow: false, | |||||
imgList: [], | |||||
} | |||||
}, | |||||
methods: { | |||||
chooseFile() { | |||||
uni.chooseImage({ | |||||
count: Number(this.number), | |||||
sizeType: ['original', 'compressed'], | |||||
sourceType: ['album', 'camera'], | |||||
success: ({ tempFilePaths,tempFiles }) => { | |||||
this.chooseChangeback(tempFilePaths,tempFiles) | |||||
} | |||||
}) | |||||
}, | |||||
delImg(index) { | |||||
this.CONFIRM("", "是否确认删除?", true).then(res => { | |||||
if(!res)return | |||||
this.LOADING('正在删除…'); | |||||
const newList = JSON.parse(JSON.stringify(this.imgList)); | |||||
this.HTTP_POST('/learun/adms/annexes/wxdelete', this.imgList[index].id, "文件删除失败").then((data) => { | |||||
this.HIDE_LOADING(); | |||||
if (data) { | |||||
newList.splice(index, 1); | |||||
this.imgList = newList | |||||
this.$emit("update:value", newList); | |||||
this.$emit("input", newList); | |||||
this.$emit("change"); | |||||
this.$emit("del"); | |||||
} | |||||
}) | |||||
}) | |||||
}, | |||||
showfile() { | |||||
return true; | |||||
}, | |||||
async chooseChangeback(tempFilePaths, tempFiles) { | |||||
let uploadImageRes = await this.uploadImage(tempFilePaths[0], tempFiles[0] ? tempFiles[0].name : "") | |||||
let newList = this.imgList || [] | |||||
if (uploadImageRes) { | |||||
//请求‘获取附件列表’接口 | |||||
let data = await this.FETCH_FILEList(uploadImageRes); | |||||
if(data){ | |||||
newList = data.map(t=>({ | |||||
id: t.F_Id, | |||||
name: t.F_FileName, | |||||
url: t.F_FilePath.substring(t.F_FilePath.indexOf('Resource')), | |||||
type: t.F_FileType, | |||||
folderid:t.F_FolderId, | |||||
})) | |||||
} | |||||
} | |||||
this.imgList = newList | |||||
this.$emit("update:value", newList); | |||||
this.$emit("input", newList); | |||||
this.$emit("change", newList); | |||||
}, | |||||
uploadImage(url, name) { | |||||
if (!url) return | |||||
// 文件上传 | |||||
return new Promise(async (reslove, reject) => { | |||||
this.LOADING('正在上传…'); | |||||
let params = name ? { | |||||
folderId: this.folderId, | |||||
name | |||||
} : { | |||||
folderId: this.folderId | |||||
} | |||||
this.HTTP_UPLOAD2('/learun/adms/annexes/wxuploadinsingle', url, params).then((data) => { | |||||
this.HIDE_LOADING(); | |||||
if (data) { | |||||
reslove(data) | |||||
} else { | |||||
reject('上传失败!') | |||||
} | |||||
}) | |||||
}) | |||||
}, | |||||
validate(array) { | |||||
// let type = array.every(item=>{ | |||||
// return item.type && item.type.substring(0,6) == "image/" | |||||
// }) | |||||
// if(!type){ | |||||
// this.TOAST('文件类型错误'); | |||||
// return false | |||||
// } | |||||
let size = array.every(item => { | |||||
return item.size && item.size <= 200 * 1024 * 1024 | |||||
}) | |||||
if (!size) { | |||||
this.TOAST('文件大小不得超过200M'); | |||||
return false | |||||
} | |||||
return true | |||||
}, | |||||
isImage(type) { | |||||
if (type && type.length) { | |||||
return ["png", "jpg"].includes(type.substring(type.length - 3, type.length)) | |||||
} else { | |||||
return false | |||||
} | |||||
}, | |||||
viewImg(item) { | |||||
if (!this.isImage(item.type)) { | |||||
window.location.href = this.CONFIG("webHost") + item.url | |||||
} else { | |||||
uni.previewImage({ | |||||
urls: [this.CONFIG('webHost') + item.url], | |||||
current: this.CONFIG('webHost') + item.url | |||||
}); | |||||
} | |||||
}, | |||||
}, | |||||
created() { | |||||
// console.log(this.value) | |||||
this.imgList = JSON.parse(JSON.stringify(this.value.map(item => { | |||||
return { | |||||
id: item.F_Id, | |||||
name: item.F_FileName, | |||||
url: item.F_FilePath.substring(item.F_FilePath.indexOf('Resource')), | |||||
type: item.F_FileType, | |||||
folderid:item.F_FolderId, | |||||
} | |||||
}))) | |||||
this.$nextTick(() => { | |||||
this.isShow = true | |||||
}) | |||||
} | |||||
}; | |||||
</script> | |||||
<style scoped> | |||||
.file-name { | |||||
position: absolute; | |||||
bottom: 0; | |||||
width: 100%; | |||||
color: #606266; | |||||
font-size: 12px; | |||||
text-align: center; | |||||
background-color: rgba(255, 255, 255, 0.6); | |||||
text-overflow: ellipsis; | |||||
overflow: hidden; | |||||
white-space: nowrap; | |||||
} | |||||
</style> |