|
|
@@ -0,0 +1,250 @@
|
|
|
+# 撤销申请页面图片加载问题修复记录
|
|
|
+
|
|
|
+## 问题描述
|
|
|
+
|
|
|
+**现象**: 在已有撤销申请时,再次打开撤销申请界面(`revokeApplication.vue`),界面中的图片没有做加载显示,看控制台没有调用接口。
|
|
|
+
|
|
|
+**影响范围**: 移动端撤销申请页面的图片附件显示功能
|
|
|
+
|
|
|
+## 问题分析
|
|
|
+
|
|
|
+### 原因分析
|
|
|
+
|
|
|
+1. **缺少图片blob处理**: `revokeApplication.vue` 在 `handleExistingEvidenceData` 方法中只是简单地将 OSS 数据转换为附件列表,但没有像 `RevokeApplicationView.vue` 查看页面那样处理图片的 blob 数据获取。
|
|
|
+
|
|
|
+2. **图片URL处理不完整**: 对于图片文件,需要特殊处理URL前缀并获取blob数据才能正确显示。
|
|
|
+
|
|
|
+3. **缺少图片预加载机制**: 没有预加载机制确保图片能够正确显示。
|
|
|
+
|
|
|
+### 参考实现
|
|
|
+
|
|
|
+参考了 `RevokeApplicationView.vue` 中的图片处理机制:
|
|
|
+- `processAllImageFiles()` 方法处理图片blob数据
|
|
|
+- `getImageBlobUrl()` 方法获取图片blob URL
|
|
|
+- `preloadAllImages()` 方法预加载图片
|
|
|
+
|
|
|
+## 解决方案
|
|
|
+
|
|
|
+### 1. 增强附件数据处理 (`handleExistingEvidenceData`)
|
|
|
+
|
|
|
+```javascript
|
|
|
+// 处理现有证明材料附件数据时
|
|
|
+const attachmentFiles = response.data.map((item, index) => {
|
|
|
+ // 使用fileSuffix字段判断文件类型
|
|
|
+ const fileType = this.getFileTypeBySuffix(item.fileSuffix);
|
|
|
+ const isImage = this.isImageFile({
|
|
|
+ name: item.originalName,
|
|
|
+ type: fileType,
|
|
|
+ });
|
|
|
+
|
|
|
+ // 处理图片URL - 确保有正确的API前缀
|
|
|
+ let processedUrl = item.url;
|
|
|
+ if (isImage && item.url && item.url.startsWith('/resource/')) {
|
|
|
+ // 图片文件需要添加/api前缀
|
|
|
+ processedUrl = `/api${item.url}`;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构造完整的文件名(包含扩展名)
|
|
|
+ let fullFileName = item.originalName || `证明材料${index + 1}`;
|
|
|
+ if (
|
|
|
+ item.fileSuffix &&
|
|
|
+ !fullFileName
|
|
|
+ .toLowerCase()
|
|
|
+ .endsWith(`.${item.fileSuffix.toLowerCase()}`)
|
|
|
+ ) {
|
|
|
+ fullFileName = `${fullFileName}.${item.fileSuffix}`;
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ uid: `existing_${index}_${Date.now()}`,
|
|
|
+ name: fullFileName,
|
|
|
+ url: processedUrl,
|
|
|
+ ossId: item.ossId,
|
|
|
+ status: 'success',
|
|
|
+ type: fileType,
|
|
|
+ size: item.fileSize || 0,
|
|
|
+ };
|
|
|
+});
|
|
|
+
|
|
|
+this.attachmentList = attachmentFiles;
|
|
|
+
|
|
|
+// 🚀 关键步骤:处理图片文件以确保正确显示
|
|
|
+await this.processAllImageFiles();
|
|
|
+
|
|
|
+// 强制刷新组件显示
|
|
|
+this.$nextTick(() => {
|
|
|
+ // 预加载图片以确保能正确显示
|
|
|
+ this.preloadAllImages();
|
|
|
+});
|
|
|
+```
|
|
|
+
|
|
|
+### 2. 添加图片处理核心方法
|
|
|
+
|
|
|
+#### `processAllImageFiles()` - 处理所有图片文件
|
|
|
+
|
|
|
+```javascript
|
|
|
+async processAllImageFiles() {
|
|
|
+ console.log('=== 处理所有图片文件 ===');
|
|
|
+
|
|
|
+ // 处理附件列表中的图片
|
|
|
+ const imageFiles = this.attachmentList.filter((file) => this.isImageFile(file));
|
|
|
+ for (const file of imageFiles) {
|
|
|
+ if (file.url && !file.blobUrl) {
|
|
|
+ try {
|
|
|
+ console.log(`处理图片文件: ${file.name}`);
|
|
|
+ const blobUrl = await this.getImageBlobUrl(file.url);
|
|
|
+ if (blobUrl) {
|
|
|
+ file.blobUrl = blobUrl;
|
|
|
+ file.fileType = 'image';
|
|
|
+ file.type = file.type && file.type.startsWith('image') ? file.type : 'image';
|
|
|
+ file.isImage = true;
|
|
|
+ console.log(`图片文件处理成功: ${file.name} - ${blobUrl}`);
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error(`处理图片文件失败: ${file.name}`, error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### `getImageBlobUrl()` - 获取图片blob数据
|
|
|
+
|
|
|
+```javascript
|
|
|
+async getImageBlobUrl(imageUrl) {
|
|
|
+ try {
|
|
|
+ console.log(`获取图片blob数据: ${imageUrl}`);
|
|
|
+
|
|
|
+ // 处理图片URL路径
|
|
|
+ let apiUrl = imageUrl;
|
|
|
+ if (imageUrl.startsWith('/api/')) {
|
|
|
+ // 移除/api前缀,因为request会自动添加baseURL
|
|
|
+ apiUrl = imageUrl.replace('/api', '');
|
|
|
+ } else if (imageUrl.startsWith('/resource/')) {
|
|
|
+ // 直接使用相对路径
|
|
|
+ apiUrl = imageUrl;
|
|
|
+ } else if (imageUrl.startsWith('http')) {
|
|
|
+ // 完整URL,需要特殊处理
|
|
|
+ console.log('检测到完整URL,直接返回原URL');
|
|
|
+ return imageUrl;
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log(`API请求URL: ${apiUrl}`);
|
|
|
+
|
|
|
+ // 使用request方法获取图片数据
|
|
|
+ const response = await request({
|
|
|
+ url: apiUrl,
|
|
|
+ method: 'GET',
|
|
|
+ responseType: 'arraybuffer', // 设置响应类型为arraybuffer
|
|
|
+ header: {
|
|
|
+ isToken: true, // 图片请求可能需要token验证
|
|
|
+ },
|
|
|
+ });
|
|
|
+
|
|
|
+ // 将arraybuffer转换为blob
|
|
|
+ const blob = new Blob([response], { type: 'image/*' });
|
|
|
+ const blobUrl = URL.createObjectURL(blob);
|
|
|
+
|
|
|
+ console.log(`成功创建blob URL: ${blobUrl}`);
|
|
|
+ return blobUrl;
|
|
|
+ } catch (error) {
|
|
|
+ console.error(`获取图片blob数据失败: ${imageUrl}`, error);
|
|
|
+ // 如果请求失败,返回原始URL作为备用方案
|
|
|
+ return imageUrl;
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### `preloadAllImages()` - 预加载图片
|
|
|
+
|
|
|
+```javascript
|
|
|
+async preloadAllImages() {
|
|
|
+ console.log('=== 预加载所有图片 ===');
|
|
|
+
|
|
|
+ // 预加载附件列表中的图片
|
|
|
+ const imageFiles = this.attachmentList.filter((file) => this.isImageFile(file));
|
|
|
+ for (const file of imageFiles) {
|
|
|
+ if (file.url) {
|
|
|
+ try {
|
|
|
+ console.log(`预加载图片: ${file.name} - ${file.url}`);
|
|
|
+ const img = new Image();
|
|
|
+ img.onload = () => {
|
|
|
+ console.log(`图片预加载成功: ${file.name}`);
|
|
|
+ };
|
|
|
+ img.onerror = () => {
|
|
|
+ console.error(`图片预加载失败: ${file.name} - ${file.url}`);
|
|
|
+ };
|
|
|
+ img.src = file.blobUrl || file.url;
|
|
|
+ } catch (error) {
|
|
|
+ console.error(`预加载图片出错: ${file.name}`, error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 3. 增强模板错误处理
|
|
|
+
|
|
|
+在模板中为image组件添加错误处理:
|
|
|
+
|
|
|
+```vue
|
|
|
+<image
|
|
|
+ :src="image.blobUrl || image.url"
|
|
|
+ class="attachment-image"
|
|
|
+ mode="aspectFill"
|
|
|
+ @error="handleImageError"
|
|
|
+></image>
|
|
|
+```
|
|
|
+
|
|
|
+```javascript
|
|
|
+// 图片加载错误处理
|
|
|
+handleImageError(event) {
|
|
|
+ console.warn('图片加载失败:', event);
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+## 修复效果
|
|
|
+
|
|
|
+### 修复前
|
|
|
+- 已有撤销申请记录时,图片附件无法显示
|
|
|
+- 控制台没有任何API调用记录
|
|
|
+- 图片区域显示空白或加载失败
|
|
|
+
|
|
|
+### 修复后
|
|
|
+- 已有撤销申请记录时,图片附件正常显示
|
|
|
+- 控制台显示完整的图片处理流程日志
|
|
|
+- 图片正确加载并支持预览功能
|
|
|
+
|
|
|
+## 技术要点
|
|
|
+
|
|
|
+1. **blob数据处理**: 通过获取图片的arraybuffer数据并转换为blob URL,确保图片能正确显示
|
|
|
+2. **URL路径处理**: 正确处理不同格式的图片URL路径
|
|
|
+3. **异步处理**: 使用async/await确保图片处理的时序正确
|
|
|
+4. **错误处理**: 添加完善的错误处理和降级方案
|
|
|
+5. **内存管理**: 在页面卸载时清理blob URL,防止内存泄漏
|
|
|
+
|
|
|
+## 测试建议
|
|
|
+
|
|
|
+1. **基础功能测试**:
|
|
|
+ - 创建新的撤销申请(上传图片附件)
|
|
|
+ - 保存后重新进入页面,验证图片是否正常显示
|
|
|
+
|
|
|
+2. **边界条件测试**:
|
|
|
+ - 测试不同格式的图片文件(JPG, PNG, GIF等)
|
|
|
+ - 测试混合附件(图片+文档)
|
|
|
+ - 测试网络异常情况下的降级处理
|
|
|
+
|
|
|
+3. **性能测试**:
|
|
|
+ - 测试多张图片的加载性能
|
|
|
+ - 检查内存泄漏情况
|
|
|
+
|
|
|
+## 相关文件
|
|
|
+
|
|
|
+- **主要修改文件**: `mobile/src/pages/xskh/wjjl/revokeApplication.vue`
|
|
|
+- **参考实现文件**: `mobile/src/pages/xskh/wjjl/RevokeApplicationView.vue`
|
|
|
+- **修复日期**: 2025-01-03
|
|
|
+- **修复人员**: AI Assistant
|
|
|
+
|
|
|
+## 总结
|
|
|
+
|
|
|
+通过参考查看页面的成功实现,为撤销申请页面添加了完整的图片blob数据处理机制,确保了已有撤销申请记录的图片附件能够正确显示。修复方案具有良好的错误处理和性能优化特性。
|