uniapp 使用uni 您所在的位置:网站首页 uniapp表单验证提示怎么写 uniapp 使用uni

uniapp 使用uni

2024-07-03 03:09| 来源: 网络整理| 查看: 265

背景:

我这里是进行了一个正常的表单多文件上传。

踩坑: 踩坑1:

关于表单校验rules的问题。

我首先要想说一个uniapp这个rules,这个真恶心呀,也是我傻了,它里面每个属性都多了一个rules。

/** * 表单校验规则 */ const rules = { name: { rules: [{ required: true, errorMessage: '请输入姓名' },] }, avator: { rules: [{ required: true, errorMessage: '请上传头像' }] } }

这里有两个rules,我写了一个直接不生效了。写element写多了,都没想过是这里的错,而且我这还是用gpt生成的,没想过是这里的错,我真的会谢,以后要细心一点。

还有,官方文档说这里这里如果是自定义规则,需要onReady调用,可以搜搜其他的情况。

踩坑2:

关于文件上传组件的uni-file-picker这个问题

首先说明一下:

1. 我这个上传是一个跟着表单一起上传的,

2. 而且我这个上传有点设计的不好,因为我后端的实体类中图片这个属性是一个string类型,所以说上传很麻烦。

如果使用 uni-file-picker进行上传的话,通过官方文档uni-app官网 (dcloud.net.cn)这个组件,其实它给你整好了都,但是比较糟心的是,它对于表单上传文件及其不友好,具体请看官方截图:

 这个什么意思呢,就是你上传完之后文件的值不会绑定到你定义的变量中,你必须用其他方法进行传值。

前端:

下面有个博客可以看看他的两个方法,看完可以回来。

uniapp uni-file-picker 上传踩坑 - 掘金 (juejin.cn)icon-default.png?t=N7T8https://juejin.cn/post/7211020974024081467

第一个方法老哥的思想是没有问题的。第二个思想也没有问题,但是你需要在后端多写两个东西,单独的提交图片,单独的删除图片,我比较懒,就想在前端让图片随着表单一起提交,而不是再写俩后端,这样太麻烦了。

老哥也是个老前端了,写的代码质量都不一样,不过它的代码需要修改一下:

/** * 选择图片 */ const selectFileV = (res: any) => { let { tempFiles } = res; tempFiles.forEach((element: any) => { let { name, url, uuid, file } = element; volunCertifyFileLists.value.push({ name, url, uuid, file, }) }); console.log("志愿者图片的值:", volunCertifyFileLists.value) } // 删除图片 const deleteFileV = (res: any) => { let { tempFile: { uuid } } = res let tar = volunCertifyFileLists.value.findIndex((element: { name: '', url: '', uuid: '', file: '' }) => element.uuid === uuid) if (typeof tar === 'number') { volunCertifyFileLists.value.splice(tar, 1) } console.log("志愿者图片的值:", volunCertifyFileLists.value) }

改成这个样子,具体改的也就一个删除图片的函数,这里是用findIndex进行查找。测试了没啥bug,其他就没有啥了。

但是不得不说,看老哥的写的代码真好,高质量代码真的会改变人。

后端:

如果你没有我的2上传设计问题其实也就结束了,如果你也是后端实体类设计的图片属性的类型是string,你可以看看我的想法,不是说多好,但是够用。

前端弄完之后就是如何将文件和表单上传到后端了,这里因为后端属性的类型是string所以说正常一次性上传是不行的,正常思路就是点击submit的时候图片上传一次,表单上传一次。但是这样子需要的考虑太多了,我这里思路是:前端新建一个数组接收文件,表单中的图片属性就不要了,后端用实体类和一个文件数组接收,如下:

这样子就可以一起上传了,到service层的时候处理一下就行了。

最新状况,写出来了,但是踩坑2的想法不行了,因为微信小程序不能多文件上传,得遍历上传,这样子就不好了,还不如直接用老哥得方法2,这样还不麻烦

我是参考下面老哥得方法得

uni-app 同时上传多个文件_uni.uploadfile上传多个文件-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/wk198786/article/details/131595601怎么说呢,如果想多文件上传,小程序端只能轮询,uniapp官方说了小程序不支持上传数组,所以说,综合考虑,还是自动上传好,做个总结就是你如果上传得文件多,那就自动上传,不费事,费内存,不过可以写个删除得,就比如如果前端这边修改图片删除了,后端也跟着删除。因为我的项目是需要两个字段都多张上传,虽然可以一件上传,但是太麻烦了,而且进行前端回显得话,自动上传也方便。以前想着省点流量,变成手动上传。还是自动上传好点。

这里我找了几个平台,抖音网页版是自动上传,咸鱼,今日头条,美团,都是自动上传。

不过代码写完了都,得留一下做个备注。

这是又找到得好文章:

uni-app 微信小程序 实现图片视频多文件上传功能_uniapp上传图片或视频-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_36410795/article/details/120552848

具体代码: 前端: 学生信息 Submit import { ref, reactive } from 'vue' interface StudentInfo { avator: string; // 头像地址 volunCertify: string | []; // 志愿者证明图片地址 professCertify: string | []; // 专业人才证明图片地址 } const formData = reactive({ avator: '', volunCertify: [], professCertify: [], }) // 头像列表 const avatar = ref('https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0'); const onChooseAvatar = (e: any) => { // console.log("e.detail的值: ", e) const { avatarUrl } = e.detail avatar.value = avatarUrl // console.log("新的头像值:", avatar.value) } /** * 两个图片列表 */ const volunCertifyFileLists = ref([]); const professCertifyFileLists = ref([]); /** * 选择图片 */ const selectFileV = (res: any) => { let { tempFiles } = res; tempFiles.forEach((element: any) => { let { name, url, uuid, file } = element; volunCertifyFileLists.value.push({ name, url, uuid, file, }) }); console.log("志愿者图片的值:", volunCertifyFileLists.value) } const selectFileP = (res: any) => { let { tempFiles } = res; tempFiles.forEach((element: any) => { let { name, url, uuid, file } = element; professCertifyFileLists.value.push({ name, url, uuid, file, }) }); console.log("专业技术人才图片的值:", professCertifyFileLists.value) } // 删除图片 const deleteFileV = (res: any) => { let { tempFile: { uuid } } = res let tar = volunCertifyFileLists.value.findIndex((element: { name: '', url: '', uuid: '', file: '' }) => element.uuid === uuid) if (typeof tar === 'number') { volunCertifyFileLists.value.splice(tar, 1) } console.log("志愿者图片的值:", volunCertifyFileLists.value) } const deleteFileP = (res: any) => { let { tempFile: { uuid } } = res let tar = professCertifyFileLists.value.findIndex((element: { name: '', url: '', uuid: '', file: '' }) => element.uuid === uuid) if (typeof tar === 'number') { professCertifyFileLists.value.splice(tar, 1) } console.log("专业技术人才图片的值:", professCertifyFileLists.value) } /** * 表单校验规则 */ const rules = { } // 上传的图片数组 const imgFiles = ref([]) /** * 拼接函数 */ const concat = () => { imgFiles.value = []; // 拼接头像 if (avatar.value != 'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0') { formData.avator = avatar.value; } // 拼接志愿者图片 if (volunCertifyFileLists.value.length > 0) { volunCertifyFileLists.value.forEach((item, index) => { imgFiles.value.push({ name: `volunteer${index + 1}`, uri: item.url }) }) } // 拼接专业人才证明图片 if (professCertifyFileLists.value.length > 0) { professCertifyFileLists.value.forEach((item, index) => { imgFiles.value.push({ name: `profess${index + 1}`, uri: item.url }) }) } } // 表单校验 const formRules = ref(); /** * 进行轮询提交图片 */ const uploadFile = (imgs: any[]) => { const uploadTasks = imgs.map((file: any, index: number) => { return new Promise((resolve, reject) => { const uploadTask = uni.uploadFile({ url: '', filePath: file.uri, name: 'imgFile', formData: formData, header: { 'Content-Type': 'multipart/form-data' }, success: function (res) { resolve(res.data) }, fail: function (err) { reject(err) }, }); // 这里可以根据需要显示进度条 uploadTask.onProgressUpdate((res) => { console.log('上传进度', res.progress) console.log('已经上传的数据长度', res.totalBytesSent) console.log('预期需要上传的数据总长度', res.totalBytesExpectedToSend) }) }) }) Promise.all(uploadTasks) .then((res) => { console.log('上传成功', res) // 上传成功后的操作 }) .catch((err) => { console.log('上传失败', err) // 上传失败后的操作 }) } /** * 表单提交 */ const submit = async (formRules: any) => { formRules.validate(async (valid: any, errors: any) => { if (!valid) { uni.showLoading({ title: '提交中...', mask: true }) // 拼接图片 concat() console.log("imgFiles.value的值:", imgFiles.value); console.log("选择之后的数据: ", formData); uploadFile(imgFiles.value) uni.hideLoading() } else { // 当表单验证失败时 console.log('表单校验失败', errors); // 输出错误详情 } }) } .container { height: 100vh; background-color: #fafafa; } .header { font-size: 20px; text-align: center; } .main { text-align: center; padding-top: 1px; } .avatar-wrapper { width: 64px; height: 64px; border-radius: 50%; } .avatar { width: 64px; height: 64px; border-radius: 50%; margin-left: -14px; }

唯一值得说的是两个代码,一个是轮询上传,一个是选择图片删除图片,写法都挺好得。

后端: public Result updateDto(@RequestParam("imgFile") MultipartFile imgFile) throws IOException { String originalFilename = imgFile.getOriginalFilename(); imgFile.transferTo(new File("D:\\images\\"+originalFilename)); return Result.success("修改成功"); }

这里如果遇见有文件报错500,估计是文件限制大小得原因,改一下就行了

这里后端删除图片我没有写,大概给一下思路,你提交删除就要先判断一下你的图片字段是否有值,如果有值,那就通过链接先把服务器上的图片删除了,然后再添加新的图片。如果没值,那说明本就没有图片,直接赋值即可,这个比较方便,因为是点击提交一件上传的。

 

更新一下,关于第一个老哥的点击上传就上传,点击删除就删除

如果你选择第一个链接老哥的做法,给你个忠告,uniapp它的文件删除很麻烦,如果你先上传一个图片,然后再删除是没法将服务器图片属性传入删除函数,如果是本身就有值,那就没啥问题可以传的到删除函数。因为他的删除函数的形参是绑定内存中虚拟的图片的属性,就是你提交一个图片后,它组件里面会先在内存中生成一个虚拟的图片,虽然你是提交了服务器,并且用v-model进行绑定了,但是组件内只有虚拟图片属性。你如果点击删除,对于删除函数中的形参他是内存中的图片,而不是v-model所绑定的值。。所以说你如果想删除只能用组件给的uuid进行删除。思路是第一个老哥的做法,传的话带个uuid作为图片的唯一属性即可。后端根据uuid作为图片的名字,然后截取字符串,相同的话直接删除即可,我跟老哥一样感觉这是一个大坑。

还有一件事是如果在表单中用户反悔了,删除完图片之后就退出了,从新进,这个情况下是挺麻烦的,此时图片已经被删除了,或者说,它添加了一张图片之后就退出了。

对于第一个删除图片返回,我的想法是删除图片的时候不要调用后端,就在前端删除,可以拿个数组存着,到时候一并传回后端,然后一下子删完。添加一张图片之后退出的话也是这样,给他加一个按钮,如果点击退出,那就直接把新增的图片给后端,让后端从服务器删了就行。其实我感觉这个情况还是看架构,如果公司架构师好的话,这个情况完全可以避免。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有