uni-file-picker搭配uni.uploadFile在使用问题上踩了不少坑,我至今还是没办法在不改uniapp源码基础上实现限制重复文件的上传。因为始终怎么限制,uni-file-picker绑定的v-model的值fileList,好像只要上传了文件展示就一定会回显那一个附件。还有一个问题,就是上传的进度条并不能正常工作。直接css隐藏算了眼不见心不烦
多次试图驯服该组件,发现如果要把上传好的文件列表同步给父组件,就不要去传组件绑定的value值,因为这会出问题,把这个变量当做单纯展示的作用就好了,父子组件的数据传输,可以用双向绑定,文件的增删改都操作这个双向绑定的数据。
子组件:封装的文件上传
c-upload.vue
<template>
<uni-file-picker
v-model="fileList"
:auto-upload="false"
file-mediatype="all"
mode="grid"
@delete="delFile"
@select="select"
>
<text class="iconfont icon-zengjiatianjiajiahao"></text>
</uni-file-picker>
</template>
<script setup>
import {ref, reactive, watch} from "vue";
const props = defineProps({
appendixEntityList: {default: []},
});
const emit = defineEmits(["update:appendixEntityList"]);
let fileList = ref([]);
// 选择上传触发函数
const select = (e) => {
// 根据所选图片的个数,多次调用上传函数
let promises = [];
for (let i = 0; i < e.tempFilePaths.length; i++) {
const promise = uploadFiles(e.tempFilePaths, i);
promises.push(promise);
}
Promise.all(promises).then(() => {
});
};
// 上传函数
const uploadFiles = async (tempFilePaths, i) => {
await uni.uploadFile({
url: '/api/xxx/xxxx/xxxx', //后端用于处理图片并返回图片地址的接口
filePath: tempFilePaths[i],
name: "file",
header: {
Authorization: "Bearer " + uni.getStorageSync("token") || "",
ContentType: "application/x-www-form-urlencoded",
skipToken: true,
},
success: (res) => {
let v = JSON.parse(res.data); //返回的是字符串,需要转成对象格式
if (v.code == 200) {
props.appendixEntityList.push({
appendixId: v.data.id,
appendixOriginal: v.data.original,
appendixUrl: v.data.attachUrl,
});
emit("update:appendixEntityList", props.appendixEntityList);
}
},
fail: () => {
console.log("err");
},
});
};
//文件列表回显
const fileListEcho = () => {
if (props.appendixEntityList.length > 0) {
fileList.value = [];
props.appendixEntityList?.forEach((v) => {
//改成官方文档要求的格式。才能回显附件
fileList.value.push({
name: v?.appendixOriginal,
extname: v?.appendixType,
url: v?.appendixUrl,
});
});
}
};
// 移出图片函数
const delFile = async (val) => {
//在提交数组中删除那个被删的文件
props.appendixEntityList.some((v, i) => {
if (v.appendixOriginal === val.tempFile.name) {
props.appendixEntityList.splice(i, 1);
emit("update:appendixEntityList", props.appendixEntityList);
return true;
}
});
};
watch(
() => props.appendixEntityList,
(newVal) => {
fileListEcho();
},
);
</script>
<style lang="scss" scoped>
.icon-zengjiatianjiajiahao {
font-size: 42rpx;
color: #a2a3a5;
position: absolute;
right: 0;
top: -50rpx;
}
</style>
父组件:
<!-- 上传-->
<c-upload
ref="uploadRef"
v-model:appendixEntityList="form.appendixEntityList"
></c-upload>