2024-04-28 10:10:03 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<view>
|
|
|
|
|
|
<lsj-upload v-if="!readonly" ref="fileUpload" childId="upload1" width="100%" height="100%" :option="options"
|
|
|
|
|
|
:formats="''" :debug="false" :instantly="false" :count="formProps.maxNumber" :size="formProps.maxSize"
|
|
|
|
|
|
:multiple="formProps.multiple" @change="fileChange" instantly @uploadEnd="uploadEnd" @progress="onprogre">
|
|
|
|
|
|
<slot>
|
|
|
|
|
|
<view class="w-upload-btn">
|
|
|
|
|
|
<uni-icons type="cloud-upload" :size="40" color="#b3b3b3"></uni-icons>
|
|
|
|
|
|
<text>{{formProps.placeholder || '请选择附件'}} | 单个附件不得超过{{formProps.maxSize}}MB</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</slot>
|
|
|
|
|
|
|
|
|
|
|
|
</lsj-upload>
|
|
|
|
|
|
|
|
|
|
|
|
<view class="w-file-list" :key="fileList.length">
|
2025-03-26 17:51:01 +08:00
|
|
|
|
<view v-for="(file, i) in fileList" class="w-file" :key="`file_${i}_${file.type}`" @click.stop="downFile(i)">
|
2024-04-28 10:10:03 +08:00
|
|
|
|
<image :src="getFileImgByType(file.name)" mode="aspectFit"></image>
|
|
|
|
|
|
<text class="w-file-name">{{file.name}}</text>
|
2025-03-26 17:51:01 +08:00
|
|
|
|
<text :class="{'mr_10': file.size}" @click.stop="onPreview(i)">预览</text>
|
2025-03-25 14:52:27 +08:00
|
|
|
|
<uni-tag v-if="file.size" :text="getSize(file.size)" size="mini" inverted></uni-tag>
|
2025-01-21 17:36:10 +08:00
|
|
|
|
<text style="margin-right: 20rpx;" v-if="file.progress < 100">{{ file.progress }}%</text>
|
2024-04-28 10:10:03 +08:00
|
|
|
|
<view v-else-if="!readonly" @click.stop="deleteFile(i, file)">
|
|
|
|
|
|
<uni-icons type="trash" size="20" color="#ce8d8e"></uni-icons>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
2024-06-02 20:15:25 +08:00
|
|
|
|
<view class="fixed" :class="{show:showIframe}" v-if="showDisplay" @click="showDisplay=false">
|
|
|
|
|
|
<view class="iframeMain" @click.stop="showDisplay=true">
|
|
|
|
|
|
<video v-if="getType(iframeUrl) == 'video'" class="iframe" :src="iframeUrl"></video>
|
2024-06-05 21:35:18 +08:00
|
|
|
|
<image v-else-if="getType(iframeUrl) == 'image'" class="iframe" :src="iframeUrl">
|
2024-06-02 20:15:25 +08:00
|
|
|
|
</image>
|
2025-03-26 17:51:01 +08:00
|
|
|
|
<PreviewIframe @watchChild="watchChildClick" v-else :iframeUrl="iframeUrl"/>
|
|
|
|
|
|
|
2024-06-02 20:15:25 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
2024-04-28 10:10:03 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
2025-03-26 17:51:01 +08:00
|
|
|
|
// import PreviewIframe from "@/components/previewIframe.vue"
|
2024-06-02 20:15:25 +08:00
|
|
|
|
import {
|
|
|
|
|
|
ref,
|
|
|
|
|
|
computed,
|
|
|
|
|
|
nextTick,
|
|
|
|
|
|
onMounted
|
|
|
|
|
|
} from 'vue'
|
|
|
|
|
|
import {
|
|
|
|
|
|
BASE_URL
|
|
|
|
|
|
} from '@/api/request.js'
|
|
|
|
|
|
import {
|
|
|
|
|
|
delFile
|
|
|
|
|
|
} from '@/api/resource.js'
|
|
|
|
|
|
import {
|
|
|
|
|
|
onUnload
|
|
|
|
|
|
} from "@dcloudio/uni-app";
|
|
|
|
|
|
import {
|
|
|
|
|
|
getFileImgByType,
|
|
|
|
|
|
saveFileTemp,
|
|
|
|
|
|
removeFileTemp,
|
|
|
|
|
|
openLocalFile,
|
|
|
|
|
|
isVideoLink,
|
|
|
|
|
|
isImageLink
|
|
|
|
|
|
} from '@/utils/tool.js';
|
|
|
|
|
|
const emits = defineEmits(['update:modelValue', 'resize'])
|
2025-03-26 17:51:01 +08:00
|
|
|
|
import { encode } from 'js-base64';
|
2024-06-02 20:15:25 +08:00
|
|
|
|
defineExpose({
|
|
|
|
|
|
show
|
|
|
|
|
|
})
|
|
|
|
|
|
const showDisplay = ref(false)
|
|
|
|
|
|
const showIframe = ref(false)
|
|
|
|
|
|
const iframeUrl = ref("")
|
2024-04-28 10:10:03 +08:00
|
|
|
|
const props = defineProps({
|
|
|
|
|
|
formProps: {
|
|
|
|
|
|
type: Object,
|
|
|
|
|
|
default: () => {
|
|
|
|
|
|
return {}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
modelValue: {
|
|
|
|
|
|
type: Object,
|
|
|
|
|
|
default: () => {
|
|
|
|
|
|
return []
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
readonly: Boolean
|
|
|
|
|
|
})
|
|
|
|
|
|
const options = {
|
2024-05-18 00:52:06 +08:00
|
|
|
|
url: BASE_URL + '/wflow/res',
|
2024-04-28 10:10:03 +08:00
|
|
|
|
header: {
|
2024-05-18 00:52:06 +08:00
|
|
|
|
Authorization: "Bearer " + uni.getStorageSync('wflow-token'),
|
2024-04-28 10:10:03 +08:00
|
|
|
|
},
|
|
|
|
|
|
name: 'file',
|
|
|
|
|
|
formData: {
|
|
|
|
|
|
isImg: 'false'
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const isHide = ref(false)
|
|
|
|
|
|
|
|
|
|
|
|
const _value = computed({
|
|
|
|
|
|
get() {
|
|
|
|
|
|
return props.modelValue || []
|
|
|
|
|
|
},
|
|
|
|
|
|
set(val) {
|
|
|
|
|
|
emits('update:modelValue', val)
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
nextTick(() => {
|
|
|
|
|
|
if (!isHide.value && fileUpload.value) {
|
|
|
|
|
|
fileUpload.value.show()
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(() => { //处理文件回显
|
|
|
|
|
|
fileList.value = _value.value.map(f => {
|
|
|
|
|
|
return {
|
|
|
|
|
|
name: f.name,
|
|
|
|
|
|
progress: 100,
|
|
|
|
|
|
size: f.size,
|
|
|
|
|
|
url: f.url,
|
|
|
|
|
|
type: 'success'
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
if (!props.readonly) {
|
|
|
|
|
|
//可编辑状态下设置文件的列表
|
|
|
|
|
|
fileUpload.value.setFiles(fileList.value)
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
2025-03-26 17:51:01 +08:00
|
|
|
|
const watchChildClick = () => {
|
|
|
|
|
|
console.log("watchChildClick")
|
|
|
|
|
|
showDisplay.value = false;
|
|
|
|
|
|
showIframe.value = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-04-28 10:10:03 +08:00
|
|
|
|
onUnload(() => {
|
|
|
|
|
|
uni.$off('hideFp')
|
|
|
|
|
|
uni.$off('showFp')
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
//由于webview层级最高,这个用来防止点击穿透,事件从uni-popup组件里面发射来
|
|
|
|
|
|
uni.$on('hideFp', () => {
|
|
|
|
|
|
//开发期间可能会偶发找不到ref组件实例的问题
|
|
|
|
|
|
if (fileUpload.value) {
|
|
|
|
|
|
isHide.value = true
|
|
|
|
|
|
fileUpload.value.hide()
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
uni.$on('showFp', () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
isHide.value = false
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
if (fileUpload.value) {
|
|
|
|
|
|
fileUpload.value.show()
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 800)
|
|
|
|
|
|
} catch (e) {}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
const fileUpload = ref()
|
|
|
|
|
|
const fileList = ref([])
|
|
|
|
|
|
const fileMap = ref()
|
|
|
|
|
|
fileMap.value = new Map()
|
2024-06-02 20:15:25 +08:00
|
|
|
|
|
|
|
|
|
|
function resizeCollapse() {
|
2024-05-18 00:52:06 +08:00
|
|
|
|
setTimeout(() => emits('resize'), 800)
|
|
|
|
|
|
}
|
2024-06-02 20:15:25 +08:00
|
|
|
|
|
2024-04-28 10:10:03 +08:00
|
|
|
|
function fileChange(file) {
|
|
|
|
|
|
if (file instanceof Map) {
|
|
|
|
|
|
fileList.value = []
|
|
|
|
|
|
fileMap.value.clear()
|
|
|
|
|
|
file.forEach((f) => {
|
|
|
|
|
|
const fileM = {
|
|
|
|
|
|
name: f.name,
|
|
|
|
|
|
progress: f.progress,
|
|
|
|
|
|
size: f.size,
|
|
|
|
|
|
type: f.type
|
|
|
|
|
|
}
|
|
|
|
|
|
fileList.value.push(fileM)
|
|
|
|
|
|
fileMap.value.set(f.name, fileM)
|
|
|
|
|
|
})
|
|
|
|
|
|
fileUpload.value.upload()
|
|
|
|
|
|
}
|
2024-05-18 00:52:06 +08:00
|
|
|
|
resizeCollapse();
|
2024-04-28 10:10:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function onprogre(item) {
|
|
|
|
|
|
fileMap.value.get(item.name).progress = item.progress
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function uploadEnd(file) {
|
|
|
|
|
|
const fileM = fileMap.value.get(file.name)
|
|
|
|
|
|
if (fileM) {
|
|
|
|
|
|
fileM.type = file.type
|
|
|
|
|
|
fileM.progress = file.progress
|
|
|
|
|
|
if (file.type === 'success') {
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
icon: 'none',
|
|
|
|
|
|
title: '上传成功'
|
|
|
|
|
|
})
|
|
|
|
|
|
if (!Array.isArray(_value.value)) {
|
|
|
|
|
|
_value.value = []
|
|
|
|
|
|
}
|
|
|
|
|
|
const _file = JSON.parse(file.responseText)
|
|
|
|
|
|
//将文件
|
|
|
|
|
|
saveFileTemp({
|
|
|
|
|
|
id: _file.id,
|
|
|
|
|
|
name: _file.name,
|
|
|
|
|
|
path: file.path,
|
|
|
|
|
|
size: getSize(file.size)
|
|
|
|
|
|
})
|
|
|
|
|
|
_value.value.push(_file)
|
|
|
|
|
|
//强制更新下数据
|
|
|
|
|
|
emits('update:modelValue', _value)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
//不保存
|
|
|
|
|
|
removeFileTemp(file.name)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-06-02 20:15:25 +08:00
|
|
|
|
function getType(url){
|
|
|
|
|
|
if(isImageLink(url)){
|
|
|
|
|
|
return "image"
|
|
|
|
|
|
}else if(isVideoLink(url)){
|
|
|
|
|
|
return "video"
|
|
|
|
|
|
}else{
|
|
|
|
|
|
return ''
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
function downFile(i) {
|
2025-01-21 17:36:10 +08:00
|
|
|
|
// if (!props.readonly) {
|
|
|
|
|
|
// //可编辑状态下不能操作下载和查看
|
|
|
|
|
|
// return;
|
|
|
|
|
|
// }
|
2024-04-28 10:10:03 +08:00
|
|
|
|
const file = _value.value[i]
|
2024-06-02 20:15:25 +08:00
|
|
|
|
// const fileExtension = file.name.slice(file.name.lastIndexOf('.') + 1);
|
|
|
|
|
|
// // 常见的图片文件后缀名
|
|
|
|
|
|
// const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp'];
|
|
|
|
|
|
// // 视频类型列表
|
|
|
|
|
|
// const videoTypes = ['mp4', 'webm', 'ogg'];
|
|
|
|
|
|
// 判断文件后缀名是否在常见图片文件后缀名数组中
|
2025-03-25 14:52:27 +08:00
|
|
|
|
console.log(file)
|
|
|
|
|
|
const url = file.url ? (file.url.includes("http://") ? file.url : `${BASE_URL}/image/${file.url}`) : `${BASE_URL}/image/${file.id}`;
|
|
|
|
|
|
|
|
|
|
|
|
if (isVideoLink(`${url}`) || isImageLink(`${url}`)) {
|
2024-06-02 20:15:25 +08:00
|
|
|
|
// 是图片和视频
|
|
|
|
|
|
showDisplay.value = true;
|
|
|
|
|
|
showIframe.value = true;
|
2025-03-25 14:52:27 +08:00
|
|
|
|
iframeUrl.value = `${url}`;
|
2024-06-02 20:15:25 +08:00
|
|
|
|
} else {
|
2025-03-26 17:51:01 +08:00
|
|
|
|
// window.open(`${url}`)
|
2024-06-02 20:15:25 +08:00
|
|
|
|
}
|
2024-05-18 00:52:06 +08:00
|
|
|
|
// openLocalFile(file.name, `${options.url}/${file.id}?name=${file.name}`)
|
2024-06-02 20:15:25 +08:00
|
|
|
|
// openLocalFile(file.name, `${BASE_URL}/image/${file.id}`)
|
2024-04-28 10:10:03 +08:00
|
|
|
|
}
|
2025-03-26 17:51:01 +08:00
|
|
|
|
function onPreview(i) {
|
|
|
|
|
|
const file = _value.value[i]
|
|
|
|
|
|
// const fileExtension = file.name.slice(file.name.lastIndexOf('.') + 1);
|
|
|
|
|
|
// // 常见的图片文件后缀名
|
|
|
|
|
|
// const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp'];
|
|
|
|
|
|
// // 视频类型列表
|
|
|
|
|
|
// const videoTypes = ['mp4', 'webm', 'ogg'];
|
|
|
|
|
|
// 判断文件后缀名是否在常见图片文件后缀名数组中
|
|
|
|
|
|
console.log(file)
|
|
|
|
|
|
const url = file.url ? (file.url.includes("http://") ? file.url : `${BASE_URL}/image/${file.url}`) : `${BASE_URL}/image/${file.id}`;
|
|
|
|
|
|
|
|
|
|
|
|
if (isVideoLink(`${url}`) || isImageLink(`${url}`)) {
|
|
|
|
|
|
// 是图片和视频
|
|
|
|
|
|
showDisplay.value = true;
|
|
|
|
|
|
showIframe.value = true;
|
|
|
|
|
|
iframeUrl.value = `${url}`;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// window.open(`${url}`)
|
|
|
|
|
|
showDisplay.value = true;
|
|
|
|
|
|
showIframe.value = true;
|
|
|
|
|
|
iframeUrl.value = `http://219.147.96.221:8012/onlinePreview?url=${encodeURIComponent(encode(url))}`;
|
|
|
|
|
|
}
|
|
|
|
|
|
// http://219.147.96.221:8012/onlinePreview?url=${encodeURIComponent(encode(src))}
|
|
|
|
|
|
}
|
2024-04-28 10:10:03 +08:00
|
|
|
|
|
|
|
|
|
|
function getSize(size) {
|
|
|
|
|
|
if (size > 1048576) {
|
|
|
|
|
|
return (size / 1048576).toFixed(1) + 'MB'
|
|
|
|
|
|
} else if (size > 1024) {
|
|
|
|
|
|
return (size / 1024).toFixed(1) + 'KB'
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return size + 'B'
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function deleteFile(i, file) {
|
|
|
|
|
|
console.log(i, file)
|
|
|
|
|
|
uni.showModal({
|
|
|
|
|
|
title: '提示',
|
|
|
|
|
|
content: '您确认要删除该文件吗,删除后需要重新上传,确认删除?',
|
|
|
|
|
|
success: function(res) {
|
|
|
|
|
|
if (res.confirm) {
|
2024-05-18 00:52:06 +08:00
|
|
|
|
console.log(_value.value[i])
|
2024-04-28 10:10:03 +08:00
|
|
|
|
delFile(_value.value[i].id).then(() => {
|
|
|
|
|
|
_value.value.splice(i, 1)
|
|
|
|
|
|
emits('update:modelValue', _value)
|
|
|
|
|
|
fileMap.value.delete(file.name)
|
|
|
|
|
|
fileList.value.splice(i, 1)
|
|
|
|
|
|
fileUpload.value.clear(file.name)
|
|
|
|
|
|
}).catch(err => {
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
icon: 'none',
|
|
|
|
|
|
title: err.msg || '删除文件失败'
|
|
|
|
|
|
})
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function show(show = true) {
|
|
|
|
|
|
if (show) {
|
|
|
|
|
|
fileUpload.value.show()
|
|
|
|
|
|
} else {
|
|
|
|
|
|
fileUpload.value.hide()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="less" scoped>
|
2025-03-26 17:51:01 +08:00
|
|
|
|
.mr_10{
|
|
|
|
|
|
margin-right: 20rpx
|
|
|
|
|
|
}
|
2024-04-28 10:10:03 +08:00
|
|
|
|
.w-upload-btn {
|
|
|
|
|
|
padding: 10rpx;
|
|
|
|
|
|
background-color: #F7F7F7;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
color: #b3b3b3;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.w-file-list {
|
|
|
|
|
|
&>view {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.w-file {
|
|
|
|
|
|
flex: 1;
|
2025-01-21 17:36:10 +08:00
|
|
|
|
padding: 4rpx 20rpx;
|
2024-04-28 10:10:03 +08:00
|
|
|
|
background-color: #F7F7F7;
|
2025-01-21 17:36:10 +08:00
|
|
|
|
border-radius: 10rpx;
|
2024-04-28 10:10:03 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
2025-01-21 17:36:10 +08:00
|
|
|
|
margin-top: 4rpx;
|
2024-04-28 10:10:03 +08:00
|
|
|
|
|
|
|
|
|
|
image {
|
2025-01-21 17:36:10 +08:00
|
|
|
|
width: 24rpx;
|
|
|
|
|
|
height: 24rpx;
|
|
|
|
|
|
margin-right: 10rpx;
|
2024-04-28 10:10:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.w-file-name {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
|
/* 设置文本溢出时显示省略号 */
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-06-02 20:15:25 +08:00
|
|
|
|
|
|
|
|
|
|
.fixed {
|
|
|
|
|
|
position: fixed;
|
|
|
|
|
|
z-index: 9999;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
bottom: 0;
|
|
|
|
|
|
background-color: rgba(0, 0, 0, .3);
|
|
|
|
|
|
display: none;
|
|
|
|
|
|
|
|
|
|
|
|
&.show {
|
|
|
|
|
|
display: initial;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.iframeMain {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
left: 50%;
|
|
|
|
|
|
top: 50%;
|
|
|
|
|
|
transform: translate(-50%, -50%);
|
2025-03-26 17:51:01 +08:00
|
|
|
|
// width: 650rpx;
|
2024-06-02 20:15:25 +08:00
|
|
|
|
font-size: 0;
|
|
|
|
|
|
|
|
|
|
|
|
.iframe {
|
|
|
|
|
|
width: 100%;
|
2025-03-26 17:51:01 +08:00
|
|
|
|
height: 1000rpx;
|
2024-06-02 20:15:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-04-28 10:10:03 +08:00
|
|
|
|
</style>
|