2024-04-28 10:10:03 +08:00

274 lines
6.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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">
<view v-for="(file, i) in fileList" class="w-file" :key="`file_${i}_${file.type}`" @click="openFile(i)">
<image :src="getFileImgByType(file.name)" mode="aspectFit"></image>
<text class="w-file-name">{{file.name}}</text>
<uni-tag :text="getSize(file.size)" size="mini" inverted></uni-tag>
<text style="margin-right: 10px;" v-if="file.progress < 100">{{ file.progress }}%</text>
<view v-else-if="!readonly" @click.stop="deleteFile(i, file)">
<uni-icons type="trash" size="20" color="#ce8d8e"></uni-icons>
</view>
</view>
</view>
</view>
</template>
<script setup>
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 } from '@/utils/tool.js';
const emits = defineEmits(['update:modelValue'])
defineExpose({show})
const props = defineProps({
formProps: {
type: Object,
default: () => {
return {}
}
},
modelValue: {
type: Object,
default: () => {
return []
}
},
readonly: Boolean
})
const options = {
url: BASE_URL + '/wflow/res',
header: {
Authorization: "Bearer " + uni.getStorageSync('wflow-token')
},
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)
}
})
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()
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()
}
}
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)
}
}
}
function openFile(i) {
const file = _value.value[i]
openLocalFile(file.name, `${options.url}/${file.id}?name=${file.name}`)
}
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) {
console.log(_value,_value.value[i])
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>
.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;
padding: 2px 10px;
background-color: #F7F7F7;
border-radius: 5px;
display: flex;
align-items: center;
margin-top: 2px;
image {
width: 22px;
height: 22px;
margin-right: 5px;
}
.w-file-name {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
/* 设置文本溢出时显示省略号 */
white-space: nowrap;
}
}
}
</style>