在编辑页面,有图片字段需要选择手机图片进行上传、预览、回显、删除等,尤其是当提交表单后,再次选择编辑该表单页面时,如何正确的显示图片,并保证再次提交时,可以没有异常。这里主要记录了一种在编辑表单时(图片字段返回的是图片地址)的一种处理方式,不一定是最佳实践,但是可以实现功能的正常使用。
文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间。
<uni-file-picker
v-model="imageValue"
fileMediatype="image"
mode="grid"
@select="select"
@progress="progress"
@success="success"
@fail="fail"
/>
<script>
export default {
data() {
return {
imageValue:[]
}
},
methods:{
// 获取上传状态
select(e){
console.log('选择文件:',e)
},
// 获取上传进度
progress(e){
console.log('上传进度:',e)
},
// 上传成功
success(e){
console.log('上传成功')
},
// 上传失败
fail(e){
console.log('上传失败:',e)
}
}
}
script>
将本地资源上传到开发者服务器,客户端发起一个 POST 请求,其中 content-type 为 multipart/form-data。
uni.uploadFile({
url: 'https://www.example.com/upload', //附件上传的服务器接口地址,非真实的接口地址
filePath: tempFilePaths[0],//要上传文件资源的路径,不同的组件
name: 'file',//文件对应的 key , 开发者在服务器端通过这个 key 可以获取到文件二进制内容,即附件信息的接收字段名称
formData: {//HTTP 请求中其他额外的 form data
'user': 'test'
},
success: (uploadFileRes) => {//回调方法
console.log(uploadFileRes.data);
}
});
官方文档地址: 《
文件上传组件用法》、《uni.uploadFile(OBJECT)方法使用方法》。
为了满足在前面提到的需求,我定义了一个变量isUploadImage,用于判断在编辑表单时,是否更新了图片。同时为了区分有时候需要上传附件,有时候不需要上传附件,把业务数据提交的方法抽离出了一个doSubmitData()方法。
首先,当新增时,isUploadImage默认为true,即需要上传附件,这个时候添加附件后,调用doSubmit()时,实际上附件对象file变量为空,通过代码“this.$refs[‘files’].files[0];”获取上传的附件对象(这里其实可以通过监听组件的select或success实现赋值),然后再用uni.uploadFile()方法实现上传时,传入相关对象即可,当上传成功后,会返回图片的上传信息(不同附件上传接口不太一样,我这里返回了图片的名称,而且固定的前缀+图片名称,就可以实现图片的访问),然后把图片的名称再放到业务参数中和业务数据完成数据的提交。
当编辑时,因为调用了查询详情,这个时候isUploadImage被设置为false,如果没有对图片做任何处理,数据提交时,将不会在提交图片,避免报错(这里应该有更加合理的实践,但是目前没有找到,而且如果没有修改避免再提交占用带宽也挺不错的注意),如果修改就需要删除图片,这个时候就会调用删除方法把isUploadImage设置为true,再次提交数据的时候,又会和新增的时候一样正常提交数据了。
编辑时的回显,是:value=“imgPath”,并在加载详情的时候,为imgPath赋值实现的,这里的imgPath是一个对象,我为其中url属性赋值了,但是官方文档提示需要三个必填属性(不确定回显后,如果不删除直接上传会保存的问题是不是和这个有关系,未经验证):
<template>
<view class="container">
<uni-forms ref="formData" :modelValue="formData">
<view class="context-section">
<u-form-item label="图片附件" label-width="180">
<uni-file-picker @delete="deleteImage" ref="files" :value="imgPath" file-mediatype="image" mode="grid" :limit="1"/>
<view style="color: #c0c4cc">请上传图片,图片大小不超过20Mview>
u-form-item>
<view class="mt-3">
<view style="text-align: center;" >
<u-button class="btn" type="primary" size="medium" @click="doSubmit" >提交u-button>
view>
view>
view>
uni-forms>
view>
template>
<script>
import config from '@/config/config';
export default {
data() {
return {
file: null,
imgPath: {},
isUploadImage:true,//处理修改订单时,图片不修改的情况
formData: {//业务数据,包括附件名称
id: '',
fileName: "",
remark: ""
}
}
},
onLoad(option) {
if (option && option.id) { //编辑页面,填充需要修改的数据
this.getDetail(option.id);
this.isUploadImage = false;
}
},
methods: {
getDetail(id) {
this.$u.api.getDetail({
id: id
}).then(res => {
if (res.success == 'true' || res.success) {
this.formData = res.data
if (this.formData && this.formData.fileName) {
console.log(config.filePrefix + this.formData.fileName);
this.imgPath = {
'url': config.filePrefix + this.formData.fileName
}
}
}
});
},
deleteImage(e){
console.log(e);
this.imgPath = {};
this.file = null;
this.isUploadImage = true;//修改了图片允许图片上传
},
doSubmit() {
this.$refs['formData'].validate().then(res => {
uni.showLoading({
title: '提交中...'
});
if(!this.isUploadImage){//不需要上传图片时
this.doSubmitData();
return;
}
if (!this.file) {
if(this.$refs['files'].files.length > 0){
this.file = this.$refs['files'].files[0];
}
}
if(!this.file){
console.log("没有附件信息!");
}
// 发送文件到后台
uni.uploadFile({
url: config.uploadUrl, // 后台接收文件的 API 地址
filePath: this.file.path,
name: 'file',
header: {
"Content-Type": "multipart/form-data",
},
success: (res) => {
// 文件上传成功后的处理
console.log(res.data);
if(res.data){
let reJson = JSON.parse(res.data);
if(reJson && reJson.data && reJson.data.length>0){
this.formData.fileName= reJson.data[0].fileName;
}
}
this.doSubmitData();
},
fail: (err) => {
uni.hideLoading()
uni.showToast({
title: '上传附件失败,请稍候再试!',
duration: 1000,
icon: 'none'
});
return;
},
});
}).catch(err => {
console.log(err);
uni.showToast({
title: "系统异常,错误信息:" + err,
duration: 1000
})
})
},
doSubmitData(){//上传业务数据,包括图片地址
console.log(this.formData);
this.$u.api.doAdd(this.formData).then(res => {
uni.hideLoading()
if (res.success == 'true' || res.success) {
uni.showToast({
title: '创建成功!',
duration: 1000,
success: function() {
uni.reLaunch({
url: '/pages/index/index'
})
}
})
}
});
}
}
}
script>
<style lang="scss">
style>