278 lines
6.2 KiB
Vue
Raw Normal View History

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">
2024-05-18 00:52:06 +08:00
<!-- @click="openFile(i)" -->
<view v-for="(file, i) in fileList" class="w-file" :key="`file_${i}_${file.type}`">
2024-04-28 10:10:03 +08:00
<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';
2024-05-18 00:52:06 +08:00
const emits = defineEmits(['update:modelValue','resize'])
2024-04-28 10:10:03 +08:00
defineExpose({show})
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)
}
})
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-05-18 00:52:06 +08:00
function resizeCollapse(){
setTimeout(() => emits('resize'), 800)
}
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)
}
}
}
function openFile(i) {
const file = _value.value[i]
2024-05-18 00:52:06 +08:00
// openLocalFile(file.name, `${options.url}/${file.id}?name=${file.name}`)
openLocalFile(file.name, `${BASE_URL}/image/${file.id}?name=${file.name}`)
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>
.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>