使用技术 uniapp vue3 应用场景:微信小程序上传图片, 使用组件:uview-plus组件库
实现思路 移除组件自带的upload的上传事件,加插槽事件选择三种类型
实现效果如下:

html
javascript
<template>
<view class="box_centent">
<view class="uni-padding-wrap uni-common-mt"></view>
<view class="">
<template v-for="item in array" :key="item.id">
<view class="customs-declaration-box" v-if="shouldShowComponent(item.key)">
<view class="customs-declaration-title">
{{ item.name }}
<text class="required-label">必填</text>
<uni-icons custom-prefix="iconfont" v-if="item.demo&&item.key=='id'" @click="previewDemoImage(item.demo)" type="icon-hetongmoban" size="20" />
<!-- <image v-if="item.demo&&item.key!=='id'" @click="previewDemoImage(item.demo)" src="/static/icons/word.png" style="width:22px;height:22px" mode=""></image> -->
<uni-icons custom-prefix="iconfont" v-if="item.demo&&item.key!=='id'" @click="previewDemoImage(item.demo)" type="icon-hetongmoban" size="20" />
<!-- <uni-icons custom-prefix="iconfont" type="icon-moban" size="20" /> -->
</view>
<!-- 通用上传组件 -->
<view style="margin:auto;width: 92%;" class="">
<view class="uniheight"></view>
<up-upload
class="custom-upload"
v-if="item.key !== 'id'"
:fileList="fileList[item.key]"
@delete="(event) => deletePic(event, item.key)"
multiple
:maxCount="item.key=='other'?5:3"
:disabled="true"
:show-choose-btn="false"
accept="image/*,.pdf,.doc,.docx,.xls,.xlsx"
>
<!-- 触发按钮(不变) -->
<template #trigger>
<view class="upload-trigger" @click="showUploadOptions(item.key)">
<image src="/static/carlm.png" style="width:30px;height:30px" mode=""></image>
<view style="font-size:14px;">{{ fileList[item.key]?.length || 0 }}/{{item.key=='other'?5:3}}</view>
</view>
</template>
<!-- 自定义文件列表项:根据文件类型显示图片或图标 -->
<template #file="{ file }">
<view class="file-item">
<!-- 图片文件:直接显示图片 -->
<image
v-if="isImage(file.url)"
:src="file.url"
class="file-preview"
mode="widthFix"
></image>
<!-- 非图片文件:显示file.png图标 -->
<!-- <image
v-else
src="/static/icons/file.png"
class="file-icon"
></image> -->
<!-- 文件信息(名称、状态等) -->
<view class="file-info">
<view class="file-name">{{ getFileName(file.url) }}</view>
<view class="file-status" v-if="file.status === 'uploading'">上传中...</view>
<view class="file-status error" v-if="file.status === 'fail'">上传失败</view>
</view>
</view>
</template>
</up-upload>
</view>
<!-- 身份证信息部分 -->
<view class="customs-declaration-box" v-if="item.key === 'id'">
<view style="margin:auto;width: 92%;" class="">
<view class="uniheight"></view>
<!-- 上传人像页 -->
<view class=""
style="margin:auto;width: 92%;height: 160px;background-color: #FAFBFF;border-radius: 4px;border:1px solid #DFE5F0;display: flex;align-items: center;justify-content: center;position: relative;">
<!-- 显示已上传的人像页图片 -->
<image v-if="fileList['id'] && fileList['id'][0]"
:src="fileList['id'][0].status === 'success' ? fileList['id'][0].url : '/static/wImage@1x.png'"
style="width:100%;height: 160px;" mode=""></image>
<image v-else src="/static/wImage@1x.png" style="width:80%;height: 145px;" mode="">
</image>
<!-- 上传按钮 -->
<view class="" style="position: absolute;right:26%">
<view class=""
v-if="!fileList['id'] || !fileList['id'][0] || fileList['id'][0].status !== 'success'">
<up-upload :fileList="fileList['id'] || []"
@afterRead="(event) => handleIdUpload(event, 'id')"
@delete="(event) => deletePic(event, 'id')" :maxCount="1">
<template #trigger>
<view class=""
v-if="!fileList['id'] || !fileList['id'][0] || fileList['id'][0].status !== 'success'"
style="width: 35px;height: 35px;border-radius: 35px;background-color: #4C7CEE;display:flex;align-items:center;justify-content: center;cursor: pointer;">
<image src="/static/md-photo_camera 1@1x.png"
style="width: 23px;height:23px" mode=""></image>
</view>
</template>
</up-upload>
</view>
<view class="" v-else>
<up-upload @afterRead="(event) => handleIdUpload(event, 'id')"
@delete="(event) => deletePic(event, 'id')" :maxCount="1">
<template #trigger>
<view class=""
style="width: 35px;height: 35px;border-radius: 35px;background-color: #8fc480;display:flex;align-items:center;justify-content: center;cursor: pointer;">
<image src="/static/md-photo_camera 1@1x.png"
style="width: 23px;height:23px" mode=""></image>
</view>
</template>
</up-upload>
</view>
<view class="" :style="{
color: fileList['id'] && fileList['id'][0] && fileList['id'][0].status === 'success' ? '#666666' : '#666666',
marginLeft: '-29px'
}">
{{ fileList['id'] && fileList['id'][0] && fileList['id'][0].status === 'success'
? '点击替换人像頁' : '点击上传人像頁' }}
</view>
</view>
</view>
<view class="uniheight"></view>
<view class="uniheight"></view>
<!-- 上传国徽页 -->
<view class=""
style="margin:auto;width: 92%;height: 160px;background-color: #FAFBFF;border-radius: 4px;border:1px solid #DFE5F0;display: flex;align-items: center;justify-content: center;position: relative;">
<!-- 显示已上传的国徽页图片 -->
<image v-if="fileList['idB'] && fileList['idB'][0]"
:src="fileList['idB'][0].status === 'success' ? fileList['idB'][0].url : '/static/wImage@2x.png'"
style="width:100%;height: 160px;position:relative" mode=""></image>
<image v-else src="/static/wImage@2x.png"
style="width:80%;height: 145px;position:relative" mode=""></image>
<!-- 上传按钮 -->
<view class="" style="position: absolute;right:26%">
<!-- 未上传或上传失败状态 -->
<view class=""
v-if="!fileList['idB'] || !fileList['idB'][0] || fileList['idB'][0].status !== 'success'">
<up-upload :fileList="fileList['idB'] || []"
@afterRead="(event) => handleIdUpload(event, 'idB')"
@delete="(event) => deletePic(event, 'idB')" :maxCount="1">
<template #trigger>
<view class=""
style="width: 35px;height: 35px;border-radius: 35px;background-color: #4C7CEE;display:flex;align-items:center;justify-content: center;cursor: pointer;">
<image src="/static/md-photo_camera 1@1x.png"
style="width: 23px;height:23px" mode=""></image>
</view>
</template>
</up-upload>
</view>
<!-- 上传成功状态 -->
<view class="" v-else>
<up-upload @afterRead="(event) => handleIdUpload(event, 'idB')"
@delete="(event) => deletePic(event, 'idB')" :maxCount="1">
<template #trigger>
<view class=""
style="width: 35px;height: 35px;border-radius: 35px;background-color: #8fc480;display:flex;align-items:center;justify-content: center;cursor: pointer;">
<image src="/static/md-photo_camera 1@1x.png"
style="width: 23px;height:23px" mode=""></image>
</view>
</template>
</up-upload>
</view>
<!-- 提示文本 -->
<view class="" :style="{
color: fileList['idB'] && fileList['idB'][0] && fileList['idB'][0].status === 'success' ? '#666666' : '#666666',
marginLeft: '-29px'
}">
{{ fileList['idB'] && fileList['idB'][0] && fileList['idB'][0].status === 'success'
? '点击替换国徽页' : '点击上传国徽页' }}
</view>
</view>
</view>
</view>
<view class="uni-padding-wrap uni-common-mt"></view>
<view class="uni-padding-wrap uni-common-mt"></view>
<!-- <view class="" style="margin:auto;width: 86%;height: 30px;">
确认身份信息
</view>
<view class="" style="margin:auto;width: 86%;color: #BABABA;">
系统将根据您的上传照片自动识别填充
</view>
<view style="height: 15px;"></view>
<view class=""
style="margin:auto;width: 80%;height: 30px;display: flex;align-items: center;justify-content: space-between;">
<view class="">
真实姓名
</view>
<view class="">
李天霸
</view>
</view>
<view style="height: 15px;"></view>
<view class=""
style="margin:auto;width: 80%;height: 30px;display: flex;align-items: center;justify-content: space-between;">
<view class="">
证件号码
</view>
<view class="" style="color: #BABABA;">
41027749921099847
</view>
</view>
<view style="height: 15px;"></view> -->
</view>
</view>
<view class="uni-padding-wrap uni-common-mt"></view>
</template>
</view>
<view class="uni-padding-wrap uni-common-mt" v-show="suipupload"></view>
<!-- 3 -->
<!-- <view class="customs-declaration-box" v-if="classhow">
<view class="customs-declaration-title">
其他
</view>
<view style="margin:auto;width: 92%;" class="">
<view class="uniheight"></view>
<up-upload class="custom-upload" :fileList="fileList_other" @afterRead="afterRead_other"
@delete="deletePic_other" multiple :maxCount="5">
<template #trigger>
<view class="upload-trigger">
<image src="/static/carlm.png" style="width:30px;height:30px" mode="">
</image>
<view class="" style="font-size: 14px;">
{{fileList_other.length}}/5
</view>
</view>
</template>
</up-upload>
</view>
</view> -->
<view class="uni-padding-wrap uni-common-mt"></view>
<view class="uni-padding-wrap uni-common-mt"></view>
<view class="uni-padding-wrap uni-common-mt"></view>
<view class=""
style="width: 100%;height: 80px;background-color: white;position: fixed;bottom: 0px;display: flex;align-items: center;justify-content: center;z-index: 99;">
<!-- <up-bottom>确定</up-bottom> -->
<up-button type="" customStyle="border-radius:20px;width:90%;background-color:#E44A6C;color:white"
@click="shore" :text="chillr?'關閉':'確認'"></up-button>
</view>
</view>
</template>
js
javascript
<script setup>
import {
ref,
watch
} from 'vue';
import {
onShow,
onLoad
} from '@dcloudio/uni-app';
const chillr = ref('')
onLoad((options) => {
chillr.value = options.colse
})
// 3. 匹配图标(确保与扩展名对应)
// 统一使用 file.png 作为非图片文件的图标
const getFileIcon = (url) => {
// 调用 isImage 判断是否为图片:非图片 → 返回 pdf.png
return isImage(url) ? '' : '/static/icons/pdf.png';
};
const previewFile = (url) => {
console.log('预览文件 URL:', url); // 关键调试:打印 URL
if (!url) {
uni.showToast({ title: '文件路径无效', icon: 'none' });
return;
}
// ...原有代码...
};
// 显示上传选项弹窗
// 显示上传选项弹窗(新增微信聊天文件选项)
const showUploadOptions = (key) => {
uni.showActionSheet({
itemList: ['拍摄', '从相册选择', '選擇文件'], // 新增选项
success: (res) => {
switch (res.tapIndex) {
case 0: // 拍摄
chooseImage('camera', key);
break;
case 1: // 相册选择
chooseImage('album', key);
break;
case 2: // 从微信聊天选择
chooseWechatMessageFile(key);
break;
}
},
fail: (err) => {
console.log('取消选择', err);
}
});
};
// 从微信聊天记录(好友/群聊)选择文件
// 从微信聊天记录(好友/群聊)选择文件 - 修正API调用
const chooseWechatMessageFile = (key) => {
uni.chooseMessageFile({
count: 3 - (fileList.value[key]?.length || 0),
type: 'file',
success: (res) => {
// 关键修复:微信聊天文件的路径字段是 path,而非 tempFilePath
res.tempFiles.forEach(file => {
const tempFilePath = file.path; // 正确字段名是 path
if (tempFilePath) { // 增加校验,确保路径存在
handleFileUpload(tempFilePath, key);
} else {
console.error('微信文件路径获取失败:', file);
uni.showToast({ title: '文件路径错误', icon: 'none' });
}
});
},
fail: (err) => { /* ... */ }
});
};
// 1. 处理拍摄/相册选择(图片)
const chooseImage = (sourceType, key) => {
uni.chooseImage({
count: 3 - (fileList.value[key]?.length || 0), // 最多选择3张(减去已上传数量)
sizeType: ['original', 'compressed'],
sourceType: [sourceType], // 'camera' 或 'album'
success: (res) => {
// 选择成功后调用上传
res.tempFilePaths.forEach(tempPath => {
handleFileUpload(tempPath, key);
});
}
});
};
// 3. 统一文件上传逻辑
const handleFileUpload = (tempFilePath, key) => {
// 1. 先添加到文件列表(标记为上传中)
if (!fileList.value[key]) {
fileList.value[key] = [];
}
const fileIndex = fileList.value[key].length;
fileList.value[key].push({
url: tempFilePath,
status: 'uploading',
message: '',
id: ''
});
// 2. 调用上传接口
uploadFile(tempFilePath)
.then(result => {
// 上传成功:更新状态
fileList.value[key][fileIndex] = {
...fileList.value[key][fileIndex],
url: result.url,
status: 'success',
id: result.id
};
console.log('PDF文件上传成功,后端返回URL:', result.url); // 关键:检查此URL是否带.pdf扩展名
// 同步到全局存储
allUploadedUrls.value.push({ url: result.url, key });
uni.setStorageSync('allUploadedUrls', allUploadedUrls.value);
})
.catch(error => {
// 上传失败:更新状态
fileList.value[key][fileIndex].status = 'fail';
fileList.value[key][fileIndex].message = error.message;
});
};
// 4. 辅助方法:判断是否为图片
// 4. 辅助方法:判断是否为图片
const isImage = (url) => {
if (!url) return false; // 路径为空时视为非图片
const imgExts = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg', 'jfif']; // 覆盖常见图片格式
const ext = url.split('.').pop().toLowerCase().split('?')[0]; // 去除URL参数影响(如xxx.png?123)
return imgExts.includes(ext);
};
// 辅助方法:提取文件名(保持不变,确保正确获取扩展名)
const getFileName = (url) => {
if (!url) return '未知文件';
const urlWithoutParams = url.split('?')[0]; // 去除参数
const fileName = urlWithoutParams.split('/').pop(); // 提取最后一段作为文件名
return fileName || '未知文件';
};
const shore = () => {
// 可添加点击确定后的逻辑
// 检查是否有未上传的文件
let allUploaded = true;
// 检查 array 对应的上传项
array.value.forEach(item => {
if (item.key == 'id' && (!fileList.value[item.key] || fileList.value[item.key].length === 0)) {
allUploaded = false;
}
});
if (!allUploaded) {
uni.showToast({
title: '所有项都是必填项',
icon: 'none'
});
return;
} else {
// 其他
let filelasrt_other = []
fileList_other.value.forEach(item => {
filelasrt_other.push(item.url)
})
// 初始化文件数组
const fileGroups = {
id: [],
contract: [],
bill: [],
boxing: [],
form: [],
other:[]
};
// 处理已上传的文件
try {
const allUploadedUrls = uni.getStorageSync('allUploadedUrls') || [];
console.log(allUploadedUrls, '刪除后保存');
if (Array.isArray(allUploadedUrls)) {
allUploadedUrls.forEach(item => {
if (item.key && item.url) {
// 根据key将url分类到对应的数组
switch (item.key) {
case 'contract':
fileGroups.contract.push(item.url);
break;
case 'bill':
fileGroups.bill.push(item.url);
break;
case 'id':
case 'idB': // 身份证正反面都归类到id
fileGroups.id.push(item.url);
break;
case 'boxing':
fileGroups.boxing.push(item.url);
break;
case 'form':
fileGroups.form.push(item.url);
break;
case 'other':
fileGroups.other.push(item.url);
break;
default:
console.warn('未知文件类型:', item.key);
}
}
});
}
} catch (error) {
console.error('处理已上传文件时出错:', error);
}
// 构建最终信息对象
const info = {
...fileGroups,
text: '已上傳'
};
let declareclass = uni.getStorageSync('declare') || []; // 确保获取到数组,默认空数组
// 提取 declareclass 中所有必填的 key(这些 key 必须在 filteredInfo 中存在)
const requiredKeys = declareclass.map(item => item.key);
// 过滤 info 对象,仅保留存在于 declareclass 中的 key
const filteredInfo = Object.keys(info).reduce((acc, key) => {
if (requiredKeys.includes(key)) {
acc[key] = info[key];
}
return acc;
}, {});
filteredInfo.text = '已上傳';
console.log(filteredInfo, '輸出');
// 移除值为空数组的字段
for (let key in filteredInfo) {
if (Array.isArray(filteredInfo[key]) && filteredInfo[key].length === 0) {
delete filteredInfo[key];
}
}
// 新增:检查身份证图片数量是否为2
if (requiredKeys.includes('id') && (!filteredInfo.id || filteredInfo.id.length !== 2)) {
uni.showToast({
title: '请上传身份证正反面照片',
icon: 'none'
});
return;
}
// 核心检查:确保 declareclass 中的所有 key 都在 filteredInfo 中存在
const allRequiredExist = requiredKeys.every(key => filteredInfo.hasOwnProperty(key));
if (!allRequiredExist) {
// 存在未上传的必填项
uni.showToast({
title: '所有项都是必填项1',
icon: 'none'
});
return; // 阻止后续操作
}
// 所有必填项都存在,继续执行
console.log(filteredInfo, 'so?');
uni.setStorageSync('info_url', filteredInfo);
uni.setStorageSync('info_content_url', filteredInfo);
uni.setStorageSync('clsledir', '1');
uni.navigateBack(1);
uni.setStorageSync('info_urclassl', '1');
}
};
const previewDemoImage = (imageUrl) => {
// 校验图片URL是否有效
if (!imageUrl) {
uni.showToast({ title: '图片地址无效', icon: 'none' });
return;
}
// 调用微信原生预览接口
uni.previewImage({
urls: [imageUrl], // 预览的图片URL数组(单张图片也需放在数组中)
current: 0, // 默认显示第几张(这里只有一张,为0)
success: () => {
console.log('图片预览成功');
},
fail: (err) => {
console.error('图片预览失败:', err);
uni.showToast({ title: '预览失败,请检查图片地址', icon: 'none' });
}
});
};
let array = ref([]);
const towupload = ref(false);
const onwupload = ref(false);
const suipupload = ref(false);
// 处理身份证上传的通用函数
const handleIdUpload = (event, key) => {
const files = Array.isArray(event.file) ? event.file : [event.file];
files.forEach((file) => {
// 确保数组存在
if (!fileList.value[key]) {
fileList.value[key] = [];
}
// 清空现有数组(替换模式)
if (key === 'id' && fileList.value[key].length > 0) {
fileList.value[key] = [];
}
if (key === 'idB' && fileList.value[key].length > 0) {
fileList.value[key] = [];
}
// 添加新的上传项
fileList.value[key].push({
url: file.url,
status: 'uploading',
message: '',
id: ''
});
uploadFile(file.url)
.then((result) => {
const index = fileList.value[key].findIndex((item) => item.url === file.url);
if (index !== -1) {
// 创建新对象替换旧对象,确保响应式更新
const newItem = {
...fileList.value[key][index],
status: 'success',
url: result.url,
id: result.id
};
fileList.value[key].splice(index, 1, newItem);
// 更新 allUploadedUrls
const urlIndex = allUploadedUrls.value.findIndex(
(item) => item.key === key
);
if (urlIndex !== -1) {
allUploadedUrls.value.splice(urlIndex, 1, {
url: result.url,
key: key,
type: key === 'id' ? 'id' : 'idB',
fileName: file.name
});
} else {
allUploadedUrls.value.push({
url: result.url,
key: key,
type: key === 'id' ? 'id' : 'idB',
fileName: file.name
});
}
uni.setStorageSync('allUploadedUrls', allUploadedUrls.value);
// 身份证上传成功提示日志
const successMsg = key === 'id'
? '身份证人像页上传成功'
: '身份证国徽页上传成功';
uni.showToast({ title: successMsg, icon: 'none' });
console.log(successMsg, '文件ID:', result.id);
}
})
.catch((error) => {
const index = fileList.value[key].findIndex((item) => item.url === file.url);
if (index !== -1) {
fileList.value[key][index].status = 'fail';
fileList.value[key][index].message = error.message;
}
// 身份证上传失败提示日志
const failMsg = key === 'id'
? `身份证人像页上传失败: ${error.message}`
: `身份证国徽页上传失败: ${error.message}`;
uni.showToast({ title: failMsg, icon: 'none' });
console.error(failMsg, '错误详情:', error);
});
});
};
// const array = ref([]);
const fileList = ref({});
const fileList_other = ref([]);
const allUploadedUrls = ref([]); // 用于存储所有上传成功的 URL
// 删除图片
const deletePic = (event, key) => {
const deletedUrl = fileList.value[key][event.index].url;
console.log(deletedUrl);
fileList.value[key].splice(event.index, 1);
console.log('After delete:', fileList.value[key]);
console.log(allUploadedUrls.value);
// 从 allUploadedUrls 中移除删除的 URL 及其对应的 key
allUploadedUrls.value = allUploadedUrls.value.filter(item => !(item.url === deletedUrl && item.key === key));
uni.setStorageSync('allUploadedUrls', allUploadedUrls.value);
};
// 删除其他图片
const deletePic_other = (event) => {
fileList_other.value.splice(event.index, 1);
};
// 上传文件方法
const uploadFile = (filePath) => {
return new Promise((resolve, reject) => {
const baseUrl = uni.getStorageSync('http');
const token = uni.getStorageSync('token');
const fullUrl = `${baseUrl}/api/public/uploadImage`;
// 基础参数校验
if (!baseUrl || !token) {
reject(new Error('配置错误:服务器地址或Token缺失'));
return;
}
uni.uploadFile({
url: fullUrl,
filePath: filePath,
name: 'file',
formData: { user: 'test' },
header: {
'Authorization': `Bearer ${uni.getStorageSync('token')}` // 修正 Token 格式
},
success: (res) => {
console.log('上传接口响应状态:', res);
// 1. 处理 500 服务器错误
if (res.statusCode === 500) {
// 记录错误详情(方便排查)
console.error('服务器内部错误,响应内容:', res.data);
reject(new Error('服务器繁忙,请稍后再试')); // 友好提示用户
return;
}
// 2. 处理非 200/500 的其他状态码(如 404 接口不存在、403 权限不足)
if (res.statusCode !== 200) {
reject(new Error(`上传失败(状态码:${res.statusCode})`));
return;
}
// 3. 处理 200 状态码(HTTP请求成功,需解析业务逻辑)
try {
const data = JSON.parse(res.data);
if (data.code === 0) {
// 业务成功:返回文件信息
resolve({ url: data.data.url, id: data.data.id });
} else {
// 业务失败(如文件类型不支持、大小超限,后端明确返回错误信息)
reject(new Error(data.message || '上传失败,请检查文件是否符合要求'));
}
} catch (error) {
// 200状态码但响应格式错误(如后端返回HTML而非JSON)
console.error('响应格式错误,原始数据:', res.data);
reject(new Error('服务器返回数据格式错误'));
}
},
fail: (err) => {
uni.showToast({ title: '上傳失敗', icon: 'none' });
// 客户端调用失败(如网络问题、文件不存在)
console.error('上传调用失败:', err.errMsg);
reject(new Error(`上传失败:${err.errMsg}`));
}
});
});
};
// 处理文件上传后的逻辑
const afterRead = (event, key) => {
console.log('Before upload:', fileList.value[key]);
console.log(key);
const files = Array.isArray(event.file) ? event.file : [event.file];
files.forEach((file) => {
if (!fileList.value[key]) {
fileList.value[key] = [];
}
fileList.value[key].push({
url: file.url,
status: 'uploading',
message: '',
id: ''
});
uploadFile(file.url)
.then((result) => {
const index = fileList.value[key].findIndex((item) => item.url === file.url);
if (index !== -1) {
fileList.value[key][index] = {
...fileList.value[key][index],
status: 'success',
url: result.url,
id: result.id
};
allUploadedUrls.value.push({
url: result.url,
key: key
});
uni.setStorageSync('allUploadedUrls', allUploadedUrls.value);
// 新增:通用文件上传成功提示
const item = array.value.find(i => i.key === key);
const fileName = item?.name || '文件';
uni.showToast({ title: `${fileName}上传成功`, icon: 'none' });
console.log(`${fileName}上传成功`, result.url);
}
console.log('After upload success:', fileList.value[key]);
})
.catch((error) => {
const index = fileList.value[key].findIndex((item) => item.url === file.url);
if (index !== -1) {
fileList.value[key][index].status = 'fail';
fileList.value[key][index].message = error.message;
}
// 新增:通用文件上传失败提示
const item = array.value.find(i => i.key === key);
const fileName = item?.name || '文件';
uni.showToast({ title: `${fileName}上传失败: ${error.message}`, icon: 'none' });
console.error(`${fileName}上传失败`, error);
});
});
};
// 根据 key 判断是否显示组件
const shouldShowComponent = (key) => {
// 这里可以添加更多逻辑,目前默认都显示
return true;
};
function transformData(obj) {
const result = [];
// 遍历对象的每个属性
Object.keys(obj).forEach(key => {
// 处理特殊情况:id 字段需要拆分为 id 和 idB
if (key === 'id' && Array.isArray(obj[key]) && obj[key].length > 0) {
// 添加 id 字段
result.push({
key: 'id',
url: obj[key][0]
});
// 添加 idB 字段(如果存在第二个 URL)
if (obj[key].length > 1) {
result.push({
key: 'idB',
url: obj[key][1]
});
}
}
// 处理其他字段
else if (Array.isArray(obj[key]) && obj[key].length > 0) {
// 每个 URL 创建一个对象
obj[key].forEach(url => {
result.push({
key: key,
url: url
});
});
}
});
return result;
}
// 新增标记位,记录是否已初始化
const isInitialized = ref(false);
const classhow = ref(true)
onShow(() => {
if (!isInitialized.value) {
// 首次进入:初始化并读取存储
initializeFileList();
isInitialized.value = true;
} else {
// 页面回流:跳过初始化,避免清空已上传内容
console.log('页面重新显示,复用之前的文件状态');
}
});
// 抽离初始化逻辑为独立函数
function initializeFileList() {
// 1. 初始化 fileList(仅首次)
fileList.value = {
id: [],
idB: [],
contract: [],
bill: [],
boxing: [],
form: []
};
// 2. 初始化 other 文件列表
fileList_other.value = [];
const uni_order = uni.getStorageSync('Details');
if (uni_order) {
classhow.value = false;
}
// 3. 读取存储并回显
const declareArr = uni.getStorageSync('declare');
array.value = declareArr || [];
const clasasppr = uni.getStorageSync('info_url');
if (clasasppr) {
handleOtherFiles(clasasppr); // 抽离的回显逻辑
}
const storedUrls = uni.getStorageSync('allUploadedUrls') || [];
restoreUploadedUrls(storedUrls); // 抽离的回显逻辑
}
// 抽离:回显 other 类型文件
function handleOtherFiles(clasasppr) {
if (clasasppr.other && Array.isArray(clasasppr.other)) {
clasasppr.other.forEach(url => {
if (!fileList_other.value.some(item => item.url === url)) {
fileList_other.value.push({
url,
status: 'success',
message: ''
});
}
});
}
}
// 抽离:回显已上传的图片
function restoreUploadedUrls(storedUrls) {
allUploadedUrls.value = [];
storedUrls.forEach((item) => {
if (!fileList.value[item.key]) {
fileList.value[item.key] = [];
}
fileList.value[item.key].push({
url: item.url,
status: 'success',
id: item.id || '',
message: ''
});
allUploadedUrls.value.push({
url: item.url,
key: item.key
});
});
uni.setStorageSync('classupdate', allUploadedUrls.value);
}
</script>