fileList = upload.parseRequest(request);结果为空

前置条件:

springmvc

springmvc文件上传配置

文件正常上传,用MultipartFile file 能正常接收

出现情况:

整合dwz框架后,后台代码

此处没使用MultipartFile file接收文件,使用fileList = upload.parseRequest(request);来转换。

但转换结果为空。

原因:

在springmvc配置了multipartResolver后,已经转换过了。

解决方法,注释springmvc的文件配置

或者使用注解@RequestParam(value = "file")

select(files) { const newFiles = files.tempFiles.map(file => ({ name: file.name, url: file.path, extname: file.extname, size: file.size })); this.fileList = [...this.fileList, ...newFiles]; }, // 文件删除回调 deleteFile(file) { const index = this.fileList.findIndex(f => f.url === file.url); if (index !== -1) { this.fileList.splice(index, 1); } }, async handleSubmit(value){ console.log(this.fileList); // 检查图片数量是否符合要求 (2-6张) if (this.fileList.length < 2) { uni.showToast({ title: '请至少上传2张图片', icon: 'none', position: 'top' }); return; } if (this.fileList.length > 6) { uni.showToast({ title: '最多只能上传6张图片', icon: 'none', position: 'top' }); return; } // 1. 修正微信临时路径格式 const fixWxFilePath = (path) => { if (!path) return path; // 处理微信开发者工具的特殊路径 if (path.startsWith('http://tmp/')) { return `wxfile://tmp_${path.split('/').pop().split('.')[0]}`; } // 处理真机环境的过长路径 if (path.startsWith('wxfile://tmp_') && path.length > 45) { // 提取正确的32位hash const match = path.match(/wxfile:\/\/tmp_([a-f0-9]{32})/); if (match && match[1]) { return `wxfile://tmp_${match[1]}`; } // 简易截断方案 return `wxfile://tmp_${path.substring(13, 45)}`; } return path; }; // 2. 验证和修正文件列表 const validFiles = this.fileList .filter(Boolean) .map(file => { // 获取原始路径 const origUrl = file.url || file.path || file.tempFilePath || file.uri; return { ...file, url: fixWxFilePath(origUrl), origUrl }; }) .filter(file => file.url && typeof file.url === 'string' && file.url.trim() !== '' && file.url.startsWith('wxfile://tmp_') ); // 3. 详细错误报告 if (validFiles.length !== this.fileList.length) { const badFiles = this.fileList.filter(f => !validFiles.some(vf => vf.origUrl === (f.url || f.path || f.tempFilePath || f.uri)) ); console.error('无效文件:', badFiles); uni.showToast({ title: `发现 ${badFiles.length} 个无效文件`, icon: 'none', duration: 3000 }); return; } // 4. 创建上传参数前的最终验证 const filesParam = validFiles.map(file => { if (!file || !file.url) return null; // 前置值检查 const filePath = file.url; return { name: 'attachments', filePath: filePath }; }).filter(Boolean); // 如果修正后文件数量变化 if (filesParam.length !== validFiles.length) { uni.showToast({ title: `${validFiles.length - filesParam.length}个文件路径格式无效`, icon: 'none', duration: 3000 }); return; } console.log('上传参数:', filesParam); try{ const afterOrderData = { contactName:this.form.name, contactTelephone:this.form.mobile, contactAddress:this.form.address, name:this.form.productname, type:'2', contractId:this.form.contract, fixId:this.form.maincontract, deviceModel:this.form.deviceModel, deviceProblem:this.form.describe, } const afterOrderStr = JSON.stringify(afterOrderData); console.log(filesParam,'o'); const res = await uni.uploadFile({ url:`${BASEURL}/api/afterOrders`, method:'POST', header:{ 'Authorization': `Bearer ${this.token}` }, formData:{ afterOrder: afterOrderStr }, files:filesParam }) console.log(res); 难道我这里的处理不对吗
07-23
<template> <view class="" style="background: #F3F6FA;height: 100vh;overflow: auto;"> <view class="box"> <view class="boxxiao"> <view class=""> <view class="name"> 商品名称 </view> <input v-model="name" class="input" type="text" placeholder="请输入商品名称" /> </view> <view class=""> <view class="name"> 商品编码 </view> <input v-model="productNo" class="input" type="text" placeholder="请输入商品编码" /> </view> <view class=""> <view class="name"> 商品分类 </view> <input v-model="categoryName" @click="openPicker(1)" class="input" type="text" placeholder="请输入商品分类" /> </view> <view class=""> <view class="name"> 品牌 </view> <input v-model="brandName" @click="openPicker(2)" class="input" type="text" placeholder="请输入商品分类" /> </view> <view class=""> <view class="name"> 排序 </view> <input v-model="sort" class="input" type="text" placeholder="请输入排序" /> </view> <view class=""> <view class="name"> 单价 </view> <input v-model="price" class="input" type="text" placeholder="请输入单价" /> </view> <view class=""> <view class="name"> 重量 </view> <input v-model="weight" class="input" type="text" placeholder="请输入重量" /> </view> <view class=""> <view class="name"> 单位 </view> <input v-model="unit" class="input" type="text" placeholder="请输入单位" /> </view> </view> <view class="boxxiao1"> <view class="statc"> <view class=""> 状态 </view> <view class="statcright"> <view :class="{'xiaj':true,'shang':publishStatus=='1'}" @click="zhuangtai('1')"> 上架 </view> <view :class="{'xiaj':true,'shang':publishStatus=='0'}" @click="zhuangtai('0')"> 下架 </view> </view> </view> </view> <view class=""> <view class="updtitle"> 产品图片 </view> <view class="updoimg"> <view class="upindex"> <view class="unindexleft"> 主图 </view> <view class=""> <view class=""> <view class="uplbt"> <view class="imgbox" v-for="(item, index) in fileList" :key="index"> <image @click="dianj($event,index)" class="imgsdel" src="/static/Merchantindex/删除.png"></image> <image @click="chooseImage" class="imgs" :src="item"></image> </view> <image @click="chooseImage" v-if="fileList.length<1" style="width: 156rpx;height: 156rpx;padding: 0 10rpx 10rpx 10rpx;" src="/static/Merchantindex/Frame_17@2x.png" mode=""></image> </view> </view> </view> <view class="text13"> 请上传 大小不超过 5MB 格式为 pngipgjpeg 的文件 </view> </view> <view class="upindex"> <view class="unindexleft" @click="chooseImage"> 轮播图 </view> <view class=""> <view class="uplbt"> <view class="imgbox" v-for="(item, index) in fileList2" :key="index"> <image @click="dianj2($event,index)" class="imgsdel" src="/static/Merchantindex/删除.png"></image> <image class="imgs" :src="item"></image> </view> <image @click="chooseImage2" style="width: 156rpx;height: 156rpx;padding: 0 10rpx 10rpx 10rpx;" src="/static/Merchantindex/Frame_17@2x.png" mode=""></image> </view> <view class="text13"> 请上传 大小不超过 5MB 格式为 pngipgjpeg 的文件 </view> </view> </view> </view> <view class="guige"> <view class=""> 规格类型 </view> <view class="" @click="tianjia"> 添加 </view> </view> <view class="gglxbxo" v-for="(item,index) in skuList" :key="index"> <uni-data-select :localdata="range[index].options" v-model="range[index].value" @change="change($event, index)"></uni-data-select> <view class="xuanuzne" v-for="(items,jndex) in item.productAttr" :key="jndex"> <input v-model="items.value" class="sdasdinput" type="text" /> <view class="xiengz" @click="xiengfa(index)"> 新增 </view> <view class="xiengz" @click="shanchu(index,jndex)"> 删除 </view> </view> </view> <view class="guige"> <view class=""> 规格信息 </view> <view class=""> 刷新 </view> </view> <view class="gglxbxo" v-for="(ites,inde) in combinations" :key="inde"> <view class="dlasxlfle" v-for="(item,index) in skuList" :key="index"> <view class="dlasxlfle" v-if="item.range!=0"> <view class="name w130"> {{item.range}} </view> <input v-if="index==0" v-model="ites.spData.value" class="tesinput input" type="text" :placeholder="`请输入${item.range}`" /> <input v-if="index==1" v-model="ites.spData.value1" class="tesinput input" type="text" :placeholder="`请输入${item.range}`" /> </view> </view> <view class="dlasxlfle"> <view class=" name w130"> 销售价格 </view> <input v-model="ites.price" class="tesinput input" type="text" placeholder="请输入销售价格" /> </view> <view class="dlasxlfle"> <view class=" name w130"> 库存 </view> <input v-model="ites.stock" class="tesinput input" type="text" placeholder="请输入销售价格" /> </view> <view class="" style="height: 40rpx;"> </view> <view class="upindex"> <view class="unindexleft"> 展示图片 </view> <view class=""> <view class="uplbt"> <view v-if="ites.pic!=''&&ites.pic!=null&&ites.pic!=undefined" class="imgbox"> <image @click="dianj3($event,inde)" class="imgsdel" src="/static/Merchantindex/删除.png"> </image> <image class="imgs" :src="BASE_URL+ites.pic"></image> </view> <image @click="chooseImage3(inde)" style="width: 156rpx;height: 156rpx;padding: 0 10rpx 10rpx 10rpx;" src="/static/Merchantindex/Frame_17@2x.png" mode=""></image> </view> <view class="text13"> 请上传 大小不超过 5MB 格式为 pngipgjpeg 的文件 </view> </view> </view> </view> <view class="tetx"> 详细描述 </view> <view class="container"> <!-- <button @click="insertImage">插入图片</button> --> <editor v-if="isReadOnly1" id="editor" class="rech" :read-only="isReadOnly" placeholder="请输入内容" @input="onInput" @statusbar="statusbar" @ready="onEditorReady"> </editor> </view> </view> </view> <view class="tail" @click="dianchang()"> <view class="taill"> 上传 </view> </view> </view> <uv-picker ref="picker" :columns="columns" @confirm="confirm"></uv-picker> <uv-picker ref="picker1" :columns="columns1" @confirm="confirm1"></uv-picker> </template> <script> import { request, BASE_URL } from '@/utils/request.js'; export default { data() { return { inid: 0, isReadOnly: true, isReadOnly1: true, publishStatus: "1", combinations: [{ id: "", outSkuNo: null, pic: "", price: "", spData: { value: '', value2: '' }, stock: "", }], list: [{ name: "", option: [] }], data: [{ name: "", option: [] }], skuList: [{ productAttr: [{ value: '' }], range: 0, }], range: [{ value: -1, // 当前选中的值 options: [{ value: 0, text: '材质' }, { value: 1, text: '颜色' }, { value: 2, text: '尺寸' }, { value: 3, text: '其他' } ] }, { value: -1, // 当前选中的值 options: [{ value: 0, text: '材质' }, { value: 1, text: '颜色' }, { value: 2, text: '尺寸' }, { value: 3, text: '其他' } ] } ], id:"", BASE_URL: BASE_URL, name: "", productNo: "", sort: '', price: "", weight: "", unit: "", categoryName: "", brandName: "", shopIds: "", pic: "", albumPics: "", categoryId: "", detailMobileHtml: "", fileList: [], fileList2: [], fileList3: [], placeholder: '请输入内容', editorCtx: null, columns: [ [] ], columns1: [ [] ], category: [], brand: [] } }, watch: { editorCtx: { immediate: true, // 立即执行一次 handler(newVal) { if (newVal) { // 首次拿到实例 console.log('editorCtx 已就绪', newVal); } } }, // 深度监听 skuList skuList: { deep: true, handler(newVal, oldVal) { console.log('新值:', newVal); for (var i = 0; i < newVal.length; i++) { if (newVal[i].range == 0) { return } } this.combinations = [] if (newVal.length == 1) { for (var i = 0; i < newVal[0].productAttr.length; i++) { if (this.inid == 1) { this.combinations.push({ id: this.daskuList[i].id, outSkuNo: this.daskuList[i].outSkuNo, pic: this.daskuList[i].pic, price: this.daskuList[i].price, spData: { value: '', value2: '' }, stock: this.daskuList[i].stock }) } else { this.combinations.push({ id: "", outSkuNo: null, pic: "", price: "", spData: { value: '', value2: '' }, stock: "" }) } } for (var i = 0; i < newVal[0].productAttr.length; i++) { this.combinations[i].spData.value = newVal[0].productAttr[i].value } } if (newVal.length == 2) { for (var i = 0; i < newVal[0].productAttr.length; i++) { for (var j = 0; j < newVal[1].productAttr.length; j++) { if (this.inid == 1) { this.combinations.push({ id: this.daskuList[j].id, outSkuNo: this.daskuList[j].outSkuNo, pic: this.daskuList[j].pic, price: this.daskuList[j].price, spData: { value: '', value2: '' }, stock: this.daskuList[j].stock }) } else { this.combinations.push({ id: "", outSkuNo: null, pic: "", price: "", spData: { value: '', value2: '' }, stock: "" }) } } } console.log("数据", this.combinations) let z = 0 for (var i = 0; i < newVal[0].productAttr.length; i++) { for (var j = 0; j < newVal[1].productAttr.length; j++) { this.combinations[z].spData.value = newVal[0].productAttr[i].value this.combinations[z].spData.value1 = newVal[1].productAttr[j].value ++z } } } console.log("组合数据", this.combinations) }, }, }, onLoad(option) { this.inid = option.id if (option.id == 1) { console.log(option.id) let shangpxiangq = uni.getStorageSync("shangpxiangq") console.log("商品数据是", shangpxiangq) const data = shangpxiangq || {}; this.publishStatus = data.publishStatus || "1"; this.name = data.name || ""; this.productNo = data.productNo || ""; this.sort = data.sort || ""; this.price = data.price || ""; this.weight = data.weight || ""; this.unit = data.unit || ""; this.categoryName = data.categoryName || ""; this.brandName = data.brandName || ""; this.shopIds = data.shopIds || ""; this.pic = data.pic || ""; this.albumPics = data.albumPics || ""; this.categoryId = data.categoryId || ""; this.detailMobileHtml = data.detailMobileHtml || ""; this.list = JSON.parse(data.productAttr) this.daskuList = data.skuList this.id=data.id let skuList = data.skuList console.log(this.list) console.log("撒低级", this.list[0].options) this.skuList = [] for (var i = 0; i < this.list.length; i++) { this.skuList.push({ productAttr: [], range: this.list[i].name, }) for (var j = 0; j < this.range[i].options.length; j++) { if (this.range[i].options[j].text == this.list[i].name) { this.range[i].value = this.range[i].options[j].value console.log("默认值为", this.range) break } } for (var j = 0; j < this.list[i].options.length; j++) { this.skuList[i].productAttr.push({ value: this.list[i].options[j].name }) } } console.log("回家撒比", this.combinations) // skuList: [{ // productAttr: [{ // value: '' // }], // range: 0, // }], // this.skuList=skuList // id: "" // outSkuNo: null // pic: "" // price: "" // spData: {value: "白色", value2: ""} // stock: "" // 1: // id: "" // outSkuNo: null // pic: "" // price: "" // spData: {value: "黑色", value2: ""} // stock: "" // console.log(skuList) // this.skuList=skuList if (this.pic != '') { this.fileList.push(BASE_URL + this.pic) } if (this.albumPics != '') { let ims = this.albumPics.split(",") for (var i = 0; i < ims.length; i++) { this.fileList2.push(BASE_URL + ims[i]) } } this.isReadOnly1 = false const timer = setTimeout(() => { // this.insertContents(this.detailMobileHtml) this.isReadOnly1 = true }, 1); // const timer1 = setTimeout(() => { // this.isReadOnly=false // }, 4000); } else { // this.isReadOnly1 = true this.isReadOnly = false } }, mounted() { this.getInfo() this.getcategory() this.getbrand() }, methods: { dianj3(event, index) { console.log(index) this.combinations[index].pic = "" }, dianj(event, index) { console.log(index) this.fileList = [] console.log(this.fileList) event.stopPropagation(); }, dianj2(event, index) { console.log(index) this.albumPics="" this.fileList2.splice(index, 1); console.log(this.fileList2) for (var i = 0; i < this.fileList2.length; i++) { if(this.albumPics==""||this.albumPics==null||this.albumPics==undefined){ this.albumPics=this.fileList2[i].replace(BASE_URL, ''); }else{ this.albumPics=this.albumPics+","+this.fileList2[i].replace(BASE_URL, ''); } } console.log(this.albumPics) // this.albumPics=this.fileList2 event.stopPropagation(); }, zhuangtai(iss) { this.publishStatus = iss }, onInput(e) { // 获取编辑器的当前内容 this.detailMobileHtml = e.detail.html; }, async dianchang() { console.log("数据啊22", this.skuList) console.log("数据啊21", this.combinations) if (this.name == "") { uni.showToast({ title: '商品名称不能为', icon: 'none', // 可选值:'success'、'loading'、'none' duration: 1000 // 显示时长,单位 ms }); return } if (this.categoryName == "") { uni.showToast({ title: '商品分类不能为', icon: 'none', // 可选值:'success'、'loading'、'none' duration: 1000 // 显示时长,单位 ms }); return } let skuList = [] // let spData={} for (var i = 0; i < this.skuList.length; i++) { if (this.skuList[i].range == 0 || this.skuList[i].range == "") { uni.showToast({ title: '规格不能为', icon: 'none', // 可选值:'success'、'loading'、'none' duration: 1000 // 显示时长,单位 ms }); return } for (var j = 0; j < this.skuList[i].productAttr.length; j++) { if (this.skuList == 1) { if (this.skuList[i].productAttr[j].value == "") { uni.showToast({ title: '规格不能为', icon: 'none', // 可选值:'success'、'loading'、'none' duration: 1000 // 显示时长,单位 ms }); return } } else { if (this.skuList[i].productAttr[j].value == "" || this.skuList[i].productAttr[j].value1 == "") { uni.showToast({ title: '规格不能为', icon: 'none', // 可选值:'success'、'loading'、'none' duration: 1000 // 显示时长,单位 ms }); return } } } } for (var i = 0; i < this.combinations.length; i++) { if (this.skuList.length == 1) { skuList.push({ id: this.combinations[i].id, outSkuNo: null, pic: this.combinations[i].pic, price: this.combinations[i].price, spData: JSON.stringify({ [this.skuList[0].range]: this.combinations[i].spData.value }), stock: this.combinations[i].stock, [this.skuList[0].range]: this.combinations[i].spData.value }) } else { skuList.push({ id: this.combinations[i].id, outSkuNo: null, pic: this.combinations[i].pic, price: this.combinations[i].price, spData: JSON.stringify({ [this.skuList[0].range]: this.combinations[i].spData.value, [this.skuList[1].range]: this.combinations[i].spData.value1, }), stock: this.combinations[i].stock, [this.skuList[0].range]: this.combinations[i].spData.value, [this.skuList[1].range]: this.combinations[i].spData.value1 }) } } console.log("数据啊会受到覅", skuList) let productAttr = [] for (var i = 0; i < this.skuList.length; i++) { productAttr.push({ name: '', options: [] }) productAttr[i].name = this.skuList[i].range for (var j = 0; j < this.skuList[i].productAttr.length; j++) { productAttr[i].options.push({ name: "" }) productAttr[i].options[j] = { name: this.skuList[i].productAttr[j].value } } } const formData = { name: this.name, productNo: this.productNo, sort: this.sort, price: this.price, weight: this.weight, unit: this.unit, categoryName: this.categoryName, brandName: this.brandName, shopIds: this.shopIds, pic: this.pic, albumPics: this.albumPics, publishStatus: this.publishStatus, detailMobileHtml: this.detailMobileHtml, productAttr: JSON.stringify(productAttr), skuList: skuList, categoryId:this.categoryId, id:this.id }; console.log("上传的数据", formData) if (this.inid == 1) { const res = await request({ url: 'pms/product', method: 'put', data: formData }); uni.showToast({ title: '修改成功', icon: 'success', duration: 2000 // 提示框显示2秒 }); // 延迟2秒后返回上一页 setTimeout(() => { uni.navigateBack({ delta: 1 // 返回上一页 }); }, 2000); // 延迟2秒 } else { const res = await request({ url: 'pms/product', method: 'post', data: formData }); uni.showToast({ title: '上传成功', icon: 'success', duration: 2000 // 提示框显示2秒 }); // 延迟2秒后返回上一页 setTimeout(() => { uni.navigateBack({ delta: 1 // 返回上一页 }); }, 2000); // 延迟2秒 } }, shanchu(index, jndex) { if (this.skuList[index].productAttr.length == 1) { this.skuList.splice(index, 1) return } this.skuList[index].productAttr.splice(jndex, 1) }, tianjia() { this.skuList.push({ productAttr: [{ value: '' } // 初始一个对象 ], range: 0, }) }, xiengfa(index) { this.skuList[index].productAttr.push({ value: '' }); }, change(e, index) { console.log("e:", e); console.log("index:", index); this.skuList[index].range = this.range[0].options[e].text }, openPicker(ins) { if (ins == 1) { this.$refs.picker.open(); } if (ins == 2) { this.$refs.picker1.open(); } }, confirm(e) { console.log('confirm', e); this.categoryName = e.value[0] this.categoryId = this.category[e.indexs[0]].id }, confirm1(e) { console.log('confirm', e); this.brandName = e.value[0] }, async getInfo() { const res = await request({ url: 'wechat/getInfo', method: 'get' }); this.shopIds = res.shopIds[0] console.log("个人信息", res.shopIds[0]) // this.isReadOnly = false }, async getcategory() { console.log(this.shopIds) const res = await request({ url: 'pms/category/page?pageNum=1&pageSize=999999', method: 'get' }); console.log("商品分类", res) for (var i = 0; i < res.rows.length; i++) { this.columns[0].push(res.rows[i].name) } this.category = res.rows }, async getbrand() { console.log(this.shopIds) const res = await request({ url: 'pms/brand/page?pageNum=1&pageSize=99999', method: 'get' }); console.log("品牌分类", res) for (var i = 0; i < res.rows.length; i++) { this.columns1[0].push(res.rows[i].name) } this.brand = res.rows }, async chooseImage() { uni.chooseImage({ count: 1, sizeType: ['original', 'compressed'], sourceType: ['album', 'camera'], success: (res) => { const tempFilePaths = res.tempFilePaths; this.fileList[0] = tempFilePaths[0] uni.uploadFile({ url: `${this.BASE_URL}/common/upload`, // 替换为你的上传地址 filePath: tempFilePaths[0], name: 'file', // 对应后端接收的字段名 header: { 'Authorization': `Bearer ${uni.getStorageSync('user_token')}` // 设置 token }, formData: { // 这里可以添加额外的表单数据 }, success: (uploadRes) => { console.log(uploadRes); this.pic = JSON.parse(uploadRes.data).fileName console.log(JSON.parse(uploadRes.data).fileName); }, fail: (error) => { console.error('上传失败:', error); } }); } }); }, chooseImage3(index) { uni.chooseImage({ count: 1, sizeType: ['original', 'compressed'], sourceType: ['album', 'camera'], success: (res) => { // this.fileList2.push(res.tempFilePaths[0]) // this.uploadFile(res.tempFilePaths[0]); uni.uploadFile({ url: `${this.BASE_URL}/common/upload`, // 替换为你的上传地址 filePath: res.tempFilePaths[0], name: 'file', // 对应后端接收的字段名 header: { 'Authorization': `Bearer ${uni.getStorageSync('user_token')}` // 设置 token }, formData: { // 这里可以添加额外的表单数据 }, success: (uploadRes) => { console.log(uploadRes); this.combinations[index].pic = JSON.parse(uploadRes .data).fileName console.log("图片的地址是", this.combinations[index].pic) // this.fileList3[index]=BASE_URL+uploadRes }, fail: (error) => { console.error('上传失败:', error); } }); } }); }, chooseImage2() { uni.chooseImage({ count: 1, sizeType: ['original', 'compressed'], sourceType: ['album', 'camera'], success: (res) => { this.fileList2.push(res.tempFilePaths[0]) // this.uploadFile(res.tempFilePaths[0]); uni.uploadFile({ url: `${this.BASE_URL}/common/upload`, // 替换为你的上传地址 filePath: res.tempFilePaths[0], name: 'file', // 对应后端接收的字段名 header: { 'Authorization': `Bearer ${uni.getStorageSync('user_token')}` // 设置 token }, formData: { // 这里可以添加额外的表单数据 }, success: (uploadRes) => { console.log(uploadRes); if (this.albumPics == "") { this.albumPics = JSON.parse(uploadRes.data).fileName } else { this.albumPics = this.albumPics + ',' + JSON.parse(uploadRes .data).fileName } console.log(this.albumPics); }, fail: (error) => { console.error('上传失败:', error); } }); } }); }, onEditorReady() { uni.createSelectorQuery().in(this).select('#editor').context((res) => { if (res) { this.editorCtx = res.context; console.log("执行") if(this.detailMobileHtml!=""){ this.insertContents(this.detailMobileHtml) } } }).exec(); }, insertContents(html) { if (!this.editorCtx) { uni.showToast({ title: '编辑器未就绪', icon: 'none' }); return; } if (!this.editorCtx) return; const set = () => this.editorCtx.setContents({ html }); // #ifdef H5 this.editorCtx.blur && this.editorCtx.blur(set); this.editorCtx.blur({ success: set }); const timer1 = setTimeout(() => { this.isReadOnly = false }, 2000); }, insertImage() { wx.chooseImage({ count: 1, sizeType: ['original', 'compressed'], sourceType: ['album', 'camera'], success: (res) => { const filePath = res.tempFilePaths[0]; this.editorCtx.insertImage({ src: filePath, alt: '图片', width: '100%', height: 'auto', success: () => { console.log('图片插入成功'); } }); } }); } } } </script> <style> @import url("Uploadproduct.css") </style> 往下滑动一段距离后 点击输入框 输入框的内容会跑到其他位置 uniapp开发的微信小程序
最新发布
08-17
u-upload.vue:480 请注意 showLoading 与 hideLoading 必须配对使用 为什么会出现这个?怎么解决? 原代码: <template> <view class="container" :style="appThemeStyle"> <!-- 标题 --> <view class="page-title">个人信息</view> <!-- 表单组件 --> <view class="form-wrapper"> <u-form :model="form" ref="uForm" label-width="140rpx"> <u-form-item label="上传:"> <u-upload :action="action" :header="header" name="flie" :custom-request="customUpload"></u-upload> </u-form-item> </u-form> </view> </view> </template> <script setup> import { ref } from 'vue' import * as UploadApi from '@/api/upload' import request from '@/utils/request' const action = ref('http://43.139.219.151:201/index.php?s=/api/upload/image') const header = ref({ storeld: '10001', platform: 'H5', 'Access-Token': 'c1ce1578e1bf22f18a43d4ecc45c6a18' }) const customUpload = ({ file, onProgress, onSuccess, onError }) => { // 1. 获取必要参数 const filePath = file.path; // 文件路径 const token = uni.getStorageSync("token"); // 获取本地存储的 token // 2. 发起自定义上传请求 const uploadTask = uni.uploadFile({ url: "https://your-custom-api.com/upload", // 替换为你的接口地址 filePath: filePath, name: "file", // 后端接收的文件字段名 header: { Authorization: `Bearer ${token}` // 添加 token 鉴权 [^2] }, formData: { userId: "123" // 附加表单数据(可选) }, success: (res) => { // 3. 处理成功响应 const response = JSON.parse(res.data); // 解析响应数据 onSuccess({ url: response.data.url // 返回图片地址给组件 [^1] }); }, fail: (err) => { // 4. 处理失败 onError(err); } }); // 5. 监听上传进度 uploadTask.onProgressUpdate((res) => { onProgress(res.progress); // 更新进度条 }); } </script>
08-16
<template> <div> <el-dialog :visible.sync="dialogVisible" width="70%" :show-close="false" :close-on-click-modal="false" append-to-body @open="handleOpen" @close="handleClose" > <template slot="title"> <div style="text-align: center; font-size: 22px;"> {{ title }} </div> </template> <el-form :model="detailForm" label-width="130px" v-loading="loading"> <el-row> <el-col :span="8"> <el-form-item label="日期:"> <el-input readonly v-model="detailForm.recordDate"></el-input> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="班别:"> <el-input readonly v-model="detailForm.workClass"></el-input> </el-form-item> </el-col> </el-row> <el-form-item label="异常机况:"> <el-table :data="eqpList" style="width: 100%" id="eqpTable"> <el-table-column prop="area" label="Area"></el-table-column> <el-table-column prop="eqpId" label="Eqp Id"></el-table-column> <el-table-column prop="eqpName" label="Eqp Name"></el-table-column> <el-table-column prop="eqpStatus" label="Eqp Status"></el-table-column> <el-table-column prop="eqpHour" label="Hour"></el-table-column> <el-table-column prop="eqpUser" label="User"></el-table-column> <el-table-column prop="comments" label="Comment"></el-table-column> </el-table> <el-input type="textarea" v-model="detailForm.abnormal" :autosize="{ minRows: 2 }" placeholder="请输入异常机况 或 选中粘贴图片" @paste="handlePaste($event, abnormalImageRef)" :readonly="!detailForm.editAuth" ></el-input> <el-upload ref="abnormalImageRef" v-model="detailForm.abnormalImageList" action="#" :http-request="handleHttpUpload" list-type="picture-card" :before-upload="beforeUpload" :on-success="() => uploadSuccess('abnormalImageList')" :on-error="uploadError" :on-remove="(file, fileList) => handleRemove('abnormalImageList', fileList)" :accept="fileType.join(',')" :on-preview="handlePreview" :disabled="!detailForm.editAuth" > <i class="el-icon-plus"></i> </el-upload> </el-form-item> <el-form-item label="产片:"> <el-table :data="lotList" style="width: 100%" id="lotTable"> <el-table-column prop="eqp" label="机台"></el-table-column> <el-table-column prop="priority" label="Priority"></el-table-column> <el-table-column prop="lotId" label="Lot ID"></el-table-column> <el-table-column prop="maskTitle" label="Mask Title"></el-table-column> <el-table-column prop="dueDay" label="Due Day"></el-table-column> </el-table> <el-input type="textarea" v-model="detailForm.product" :autosize="{ minRows: 2 }" placeholder="请输入产片 或 选中粘贴图片" @paste="handlePaste($event, productImageRef)" :readonly="!detailForm.editAuth" ></el-input> <el-upload ref="productImageRef" v-model="detailForm.productImageList" action="#" :http-request="handleHttpUpload" list-type="picture-card" :before-upload="beforeUpload" :on-success="() => uploadSuccess('productImageList')" :on-error="uploadError" :on-remove="(file, fileList) => handleRemove('productImageList', fileList)" :accept="fileType.join(',')" :on-preview="handlePreview" :disabled="!detailForm.editAuth" > <i class="el-icon-plus"></i> </el-upload> </el-form-item> <el-form-item label="工程师交接事项:"> <el-input type="textarea" v-model="detailForm.engHandover" :autosize="{ minRows: 2 }" placeholder="请输入工程师交接事项 或 选中粘贴图片" @paste="handlePaste($event, engHandoverImageRef)" :readonly="!detailForm.editAuth" ></el-input> <el-upload ref="engHandoverImageRef" v-model="detailForm.engHandoverImageList" action="#" :http-request="handleHttpUpload" list-type="picture-card" :before-upload="beforeUpload" :on-success="() => uploadSuccess('engHandoverImageList')" :on-error="uploadError" :accept="fileType.join(',')" :on-remove="(file, fileList) => handleRemove('engHandoverImageList', fileList)" :on-preview="handlePreview" :disabled="!detailForm.editAuth" > <i class="el-icon-plus"></i> </el-upload> </el-form-item> <el-form-item label="课长:" v-if="detailForm.managerName !== null"> <el-input v-model="detailForm.managerName" readonly></el-input> </el-form-item> <el-form-item label="接班人:" v-if="detailForm.assigneeName !== null"> <el-input type="textarea" v-model="detailForm.assigneeName" readonly autosize></el-input> </el-form-item> </el-form> <template slot="footer"> <el-button type="primary" @click="save" v-if="detailForm.editAuth">保存</el-button> <el-button @click="closeDialog">取消</el-button> <el-button type="primary" @click="submit" v-if="detailForm.submitAuth">提交</el-button> <el-button type="primary" @click="audit" v-if="detailForm.auditAuth">审核</el-button> <el-button type="primary" @click="assign" v-if="detailForm.assignAuth">签核</el-button> </template> </el-dialog> <el-dialog :visible.sync="previewVisible" :show-close="false"> <img width="100%" :src="previewImageUrl" alt="Preview Image"/> </el-dialog> </div> </template> <script> import { getJournalForEdit, saveJournal, submitJournal, auditJournal, assignJournal, clearEditUser } from '@/api/mfgLog/area'; import request from '@/utils/request'; import {Message, MessageBox } from "element-ui"; import dayjs from 'dayjs'; import { getToken } from '@/utils/auth' export default { data() { return { loading: false, dialogVisible: false, title: '光罩厂制造部站点交接记录簿', fileType: ['image/jpeg', 'image/png', 'image/gif'], abnormalImageRef: null, engHandoverImageRef: null, productImageRef: null, previewVisible: false, previewImageUrl: '', lotList: [], eqpList: [], detailForm: { recordDate: '', workClass: '', workArea: '', abnormal: '', lotList: [], eqpList: [], abnormalImage: '', abnormalImageList: [], product: '', productImage: '', productImageList: [], engHandover: '', engHandoverImage: '', engHandoverImageList: [], managerName: '', assigneeName: '', editAuth: false, submitAuth: false, auditAuth: false, assignAuth: false, id: '' }, timer: null }; }, mounted() { // 监听事件以重置计时器 window.addEventListener('keydown', this.resetTimer); window.addEventListener('mousemove', this.resetTimer); window.addEventListener('mouseenter', this.resetTimer); // 浏览器关闭事件 window.addEventListener('beforeunload', (e) => { this.userInactive(); }); }, beforeDestroy() { // 清除事件监听和计时器 window.removeEventListener('keydown', this.resetTimer); window.removeEventListener('mousemove', this.resetTimer); window.removeEventListener('mouseenter', this.resetTimer); clearTimeout(this.timer); }, methods: { handleOpen() { this.resetTimer(); }, handleClose() { clearTimeout(this.timer); }, resetTimer() { // 用户进行了操作,重置计时器 if (this.timer) { clearTimeout(this.timer); } this.startTimer(); }, startTimer() { // 设置5分钟后的无操作处理 this.timer = setTimeout(() => { // 用户5分钟内无操作,执行相关逻辑 if (this.dialogVisible) { this.userInactive(); } }, 5 * 60 * 1000); }, userInactive() { // 用户处于非活跃状态的逻辑处理 if (this.detailForm.editAuth) { this.save(); } this.closeDialog(); }, showDialog(row) { this.loading = true; getJournalForEdit(row).then(res => { Object.assign(this.detailForm, res.data); // 显示提示信息 if (!this.detailForm.editAuth && !this.detailForm.assignAuth && this.detailForm.editUser) { Message.warning({ message: "当前日志正在被 " + this.detailForm.editUserName + " 编辑", position: 'top', // 确保消息显示在页面顶部 duration: 5000 // 消息显示时间为 5 秒 }); return 0; } this.detailForm.abnormalImageList = []; if (this.detailForm.abnormalImage?.length > 0) { let abnormalList = this.detailForm.abnormalImage.split(","); for (let index in abnormalList) { this.detailForm.abnormalImageList.push({ url: abnormalList[index] }); } } this.detailForm.productImageList = []; if (this.detailForm.productImage?.length > 0) { let productList = this.detailForm.productImage.split(","); for (let index in productList) { this.detailForm.productImageList.push({ url: productList[index] }); } } this.detailForm.engHandoverImageList = []; if (this.detailForm.engHandoverImage?.length > 0) { let engHandoverList = this.detailForm.engHandoverImage?.split(","); for (let index in engHandoverList) { this.detailForm.engHandoverImageList.push({ url: engHandoverList[index] }); } } if (this.detailForm.lotList && Array.isArray(this.detailForm.lotList)) { this.lotList = this.detailForm.lotList; } else { this.lotList = []; // 否则初始化为数组 } if (this.detailForm.eqpList && Array.isArray(this.detailForm.eqpList)) { this.eqpList = this.detailForm.eqpList; } else { this.eqpList = []; // 否则初始化为数组 } this.title = "光罩厂制造部 " + this.detailForm.workArea + " 站点交接记录簿"; // 判断当前时间是否允许提交/审核日志 if (this.detailForm.submitAuth || this.detailForm.auditAuth) { // 白班18点30分之前不允许提交和审核 let authTime = this.detailForm.recordDate + " 18:30:00"; if ('N' == this.detailForm.workClass.substring(0, 1)) { // 晚班06点30分之前不允许提交和审核 authTime = dayjs(this.detailForm.recordDate).add(1, 'day').format("YYYY-MM-DD") + " 06:30:00"; } if (dayjs().isBefore(dayjs(authTime))) { this.detailForm.submitAuth = false; this.detailForm.auditAuth = false; } } // 父系统页面打开遮罩 window.parent.postMessage("open", '*'); this.dialogVisible = true; // 设置初始计时器 this.loading = false; }).catch(error => { console.log(error); this.loading = false; }); }, closeDialog() { clearEditUser({ id: this.detailForm.id }).catch(error => { Message.error(error.msg ? error.msg : error); }); this.$emit('close'); // 父系统页面关闭遮罩 window.parent.postMessage("close", '*'); this.dialogVisible = false; }, save() { this.detailForm.abnormalImage = this.detailForm.abnormalImageList.map(item => item.url).join(","); this.detailForm.productImage = this.detailForm.productImageList.map(item => item.url).join(","); this.detailForm.engHandoverImage = this.detailForm.engHandoverImageList.map(item => item.url).join(","); this.loading = true; saveJournal(this.detailForm).then(res => { this.loading = false; Message.success("保存成功"); this.closeDialog(); }).catch(error => { this.loading = false; }); }, submit() { MessageBox.confirm("确认要提交吗?", "提示", { confirmButtonText: '确认', cancelButtonText: '取消', type: 'warning', }).then(res => { this.detailForm.abnormalImage = this.detailForm.abnormalImageList.map(item => item.url).join(","); this.detailForm.productImage = this.detailForm.productImageList.map(item => item.url).join(","); this.detailForm.engHandoverImage = this.detailForm.engHandoverImageList.map(item => item.url).join(","); this.loading = true; submitJournal(this.detailForm).then(res => { this.loading = false; Message.success("提交成功"); this.closeDialog(); }).catch(error => { this.loading = false; Message.error(error.msg ? error.msg : error); }); }).catch(error => { console.log(error); }); }, audit() { MessageBox.confirm("确认要提交审核吗?", "提示", { confirmButtonText: '确认', cancelButtonText: '取消', type: 'warning', }).then(res => { this.detailForm.abnormalImage = this.detailForm.abnormalImageList.map(item => item.url).join(","); this.detailForm.productImage = this.detailForm.productImageList.map(item => item.url).join(","); this.detailForm.engHandoverImage = this.detailForm.engHandoverImageList.map(item => item.url).join(","); this.detailForm.lotList = this.detailForm.lotList this.detailForm.eqpList = this.detailForm.eqpList this.loading = true; auditJournal(this.detailForm).then(res => { this.loading = false; Message.success("审核成功"); this.closeDialog(); }).catch(error => { this.loading = false; Message.error(error.msg ? error.msg : error); }); }).catch(error => { console.log(error); }); }, assign() { MessageBox.confirm("确认要签核吗?", "提示", { confirmButtonText: '确认', cancelButtonText: '取消', type: 'warning', }).then(res => { this.loading = true; assignJournal({ id: this.detailForm.id }).then(res => { this.loading = false; Message.success("签核成功"); this.closeDialog(); }).catch(error => { this.loading = false; Message.error(error.msg ? error.msg : error); }); }).catch(error => { console.log(error); }); }, handleHttpUpload(options) { return process.env.VUE_APP_BASE_API + '/viewException/uploadImage' }, handleRemove(listName, fileList) { console.log(listName) console.log(fileList) console.log(this.detailForm[listName]) this.detailForm[listName] = fileList; }, headers(){ return { "Authorization": 'Bearer ' + getToken() } }, beforeUpload(rawFile) { const imgType = this.fileType.includes(rawFile.type); if (!imgType) { Message.warning({ title: '温馨提示', message: '上传图片不符合所需的格式!', }); } return imgType; }, uploadSuccess(imageListName) { Message.success({ title: '温馨提示', message: '图片上传成功!', }); this.detailForm[imageListName].forEach(item => { if (item.url.indexOf("/api/") < 0) item.url = item.response.url; }); }, uploadError() { Message.error({ title: '温馨提示', message: '图片上传失败,请您重新上传!', }); }, handlePaste(event, uploadRef) { const items = (event.clipboardData || window.clipboardData).items; let file = null; if (!items || items.length === 0) { Message.error("当前浏览器不支持粘贴板"); return; } // 搜索剪切板items for (let i = 0; i < items.length; i++) { if (items[i].type.indexOf("image") !== -1) { file = items[i].getAsFile(); break; } } if (!file) { return; } uploadRef.handleStart(file); // 将粘贴过来的图片加入预上传队列 uploadRef.submit(); // 提交图片上传队列 }, handlePreview(file) { this.previewImageUrl = file.url; this.previewVisible = true; } } }; </script> <style scoped> .layout-padding-custom { padding: 20px; } .border-vxe-table { margin-top: 20px; } </style> 报错vue.runtime.esm.js:619 [Vue warn]: Error in v-on handler: "TypeError: reqs[uid].abort is not a function" found in ---> <ElUploadList> at packages/upload/src/upload-list.vue <ElUpload> at packages/upload/src/index.vue <ElFormItem> at packages/form/src/form-item.vue <ElForm> at packages/form/src/form.vue <ElDialog> at packages/dialog/src/component.vue <Detail> at src/views/mfgLog/area/detail.vue <Index> at src/views/mfgLog/area/index.vue <AppMain> at src/layout/components/AppMain.vue <Layout> at src/layout/index.vue <App> at src/App.vue <Root> warn @ vue.runtime.esm.js:619 logError @ vue.runtime.esm.js:1893 globalHandleError @ vue.runtime.esm.js:1888 handleError @ vue.runtime.esm.js:1848 invokeWithErrorHandling @ vue.runtime.esm.js:1871 invoker @ vue.runtime.esm.js:2188 invokeWithErrorHandling @ vue.runtime.esm.js:1863 Vue.$emit @ vue.runtime.esm.js:3903 click @ element-ui.common.js:28831 invokeWithErrorHandling @ vue.runtime.esm.js:1863 invoker @ vue.runtime.esm.js:2188 original._wrapper @ vue.runtime.esm.js:6961 vue.runtime.esm.js:1897 TypeError: reqs[uid].abort is not a function at VueComponent.abort (element-ui.common.js:29351:1) at VueComponent.abort (element-ui.common.js:29717:1) at doRemove (element-ui.common.js:29688:1) at VueComponent.handleRemove (element-ui.common.js:29695:1) at invokeWithErrorHandling (vue.runtime.esm.js:1863:1) at Proxy.invoker (vue.runtime.esm.js:2188:1) at invokeWithErrorHandling (vue.runtime.esm.js:1863:1) at Vue.$emit (vue.runtime.esm.js:3903:1) at click (element-ui.common.js:28831:1) at invokeWithErrorHandling (vue.runtime.esm.js:1863:1)
08-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值