图片组件统一改造方案
目标
将客户、设备、备件模块的图片上传功能统一改造为使用 UnifiedAttachmentUpload 组件,实现:
- 统一的上传体验
- OSS Key 永久引用支持
- 多图片支持(逗号分隔)
- 预签名URL自动转换
改造范围
1. 客户模块 ✅ (已完成)
- 实体类:
BzCustomer.javacustomerPhotoUrl- 照片URL字段customerPhotoKeys- 照片Key字段(新增)
- 前端表单:
ui/src/views/business/customer/components/customer-form.vue - 列表页面:
ui/src/views/business/customer/index.vue - 后端Service:
BzCustomerServiceImpl.java:75,211 - Mapper:
BzCustomerMapper.xml
2. 设备模块 🔄 (进行中)
- 实体类:
BzEquipment.javaequipmentPhotoUrl- 照片URL字段equipmentPhotoKeys- 照片Key字段(新增)✅
- 前端表单:待修改
- 后端Service:
BzEquipmentServiceImpl.java:58,252- 需修改 - Mapper:
BzEquipmentMapper.xml- 待添加 Keys 字段
3. 备件模块 🔄 (进行中)
- 实体类:
BzSparePart.javapartImageUrl- 图片URL字段partImageKeys- 图片Key字段(新增)✅
- 前端表单:待修改
- 后端Service:
BzSparePartServiceImpl.java:74- 需修改 - Mapper:
BzSparePartMapper.xml- 待添加 Keys 字段
核心原理
数据流向
上传 → OSS → 返回 {fileUrl, fileKey} → 前端分别存储 → 后端保存
↓
查询 ← 从 Keys 字段读取 ← Mapper ← Service 转换为预签名URLKeys vs URL
| 字段类型 | 存储内容 | 特点 | 用途 |
|---|---|---|---|
| Keys | business/customer/xxx.jpg |
永久有效的OSS Key | 数据库存储 |
| URL | https://oss.com/xxx.jpg?sign=xxx |
临时预签名URL | 前端展示 |
转换逻辑
// 查询时:从Keys转换为URL
String keys = "key1.jpg,key2.jpg";
String urls = OssUtils.convertToPresignedUrl(keys);
// 结果:url1?sign=xxx,url2?sign=xxx
// 批量转换
OssUtils.convertListToPresignedUrl(
list,
Entity::getPhotoKeys, // 从Keys字段读取
Entity::setPhotoUrl // 设置到URL字段
);
已完成的修改
1. 后端实体类
✅ BzCustomer.java
// 第93-119行
private String customerPhotoUrl; // URL字段
private String customerPhotoKeys; // Keys字段
✅ BzEquipment.java
// 第51-57行
private String equipmentPhotoUrl; // URL字段
private String equipmentPhotoKeys; // Keys字段(新增)
✅ BzSparePart.java
// 第101-107行
private String partImageUrl; // URL字段
private String partImageKeys; // Keys字段(新增)
2. 后端Service
✅ BzCustomerServiceImpl.java
// 第75行 - 列表查询
OssUtils.convertListToPresignedUrl(list, BzCustomer::getCustomerPhotoKeys, BzCustomer::setCustomerPhotoUrl);
// 第59-62行 - 单条查询
if (customer != null && customer.getCustomerPhotoKeys() != null) {
customer.setCustomerPhotoUrl(OssUtils.convertToPresignedUrl(customer.getCustomerPhotoKeys()));
}
3. 前端组件
✅ customer-form.vue (第66-77行)
<unified-attachment-upload
v-model="formData.customerPhotoUrl"
v-model:keys="formData.customerPhotoKeys"
:multiple="true"
accept=".jpg,.jpeg,.png,.gif,.bmp"
:limit="5"
:max-size="10"
tip="支持客户照片上传,最多5张,最大10MB"
/>
4. 数据库
✅ 客户表
ALTER TABLE bz_customer ADD COLUMN customer_photo_keys VARCHAR(1000);
ALTER TABLE bz_customer MODIFY COLUMN customer_photo_url VARCHAR(1000);
待完成的修改
1. 数据库(重要!)
执行SQL脚本:db/update_photo_keys_unified.sql
-- 设备表
ALTER TABLE bz_equipment ADD COLUMN equipment_photo_keys VARCHAR(1000);
ALTER TABLE bz_equipment MODIFY COLUMN equipment_photo_url VARCHAR(1000);
-- 备件表
ALTER TABLE bz_spare_part ADD COLUMN part_image_keys VARCHAR(1000);
ALTER TABLE bz_spare_part MODIFY COLUMN part_image_url VARCHAR(1000);
2. Mapper XML文件
BzEquipmentMapper.xml
需要在以下位置添加 equipment_photo_keys 字段:
<resultMap>中添加映射<sql id="selectBzEquipmentVo">中添加查询字段<insert>中添加插入逻辑<update>中添加更新逻辑
BzSparePartMapper.xml
需要在以下位置添加 part_image_keys 字段:
<resultMap>中添加映射<sql id="selectBzSparePartVo">中添加查询字段<insert>中添加插入逻辑<update>中添加更新逻辑
3. Service实现类
BzEquipmentServiceImpl.java
// 第58行 - 需要修改
OssUtils.convertListToPresignedUrl(list, BzEquipment::getEquipmentPhotoKeys, BzEquipment::setEquipmentPhotoUrl);
// 第252行 - 需要修改
OssUtils.convertListToPresignedUrl(list, BzEquipment::getEquipmentPhotoKeys, BzEquipment::setEquipmentPhotoUrl);
BzSparePartServiceImpl.java
// 第74行 - 需要修改
OssUtils.convertListToPresignedUrl(list, BzSparePart::getPartImageKeys, BzSparePart::setPartImageUrl);
4. 前端表单
设备表单
文件位置:需要查找 ui/src/views/business/equipment 目录下的表单组件
修改为:
<unified-attachment-upload
v-model="formData.equipmentPhotoUrl"
v-model:keys="formData.equipmentPhotoKeys"
:multiple="true"
accept=".jpg,.jpeg,.png,.gif,.bmp"
:limit="10"
:max-size="20"
tip="支持设备照片上传,最多10张,最大20MB"
/>
备件表单
文件位置:需要查找 ui/src/views/business/sparePart 目录下的表单组件
修改为:
<unified-attachment-upload
v-model="formData.partImageUrl"
v-model:keys="formData.partImageKeys"
:multiple="true"
accept=".jpg,.jpeg,.png,.gif,.bmp"
:limit="10"
:max-size="20"
tip="支持备件图片上传,最多10张,最大20MB"
/>
执行步骤
第一步:数据库迁移
# 执行SQL脚本
mysql -u root -p husky_afterservice_db < db/update_photo_keys_unified.sql
第二步:验证数据库
-- 查看新增字段
SELECT
TABLE_NAME,
COLUMN_NAME,
COLUMN_TYPE,
COLUMN_COMMENT
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'husky_afterservice_db'
AND COLUMN_NAME LIKE '%_keys'
ORDER BY TABLE_NAME;
第三步:修改Mapper XML文件
- 修改
BzEquipmentMapper.xml - 修改
BzSparePartMapper.xml
第四步:修改Service实现
- 修改
BzEquipmentServiceImpl.java - 修改
BzSparePartServiceImpl.java
第五步:修改前端表单
- 查找并修改设备表单组件
- 查找并修改备件表单组件
第六步:重启测试
- 重启后端服务
- 清空浏览器缓存
- 测试图片上传功能
- 测试图片预览功能
- 测试编辑功能
测试清单
- 客户照片上传
- 客户照片预览(列表页、详情页)
- 客户照片编辑
- 设备照片上传
- 设备照片预览(列表页、详情页)
- 设备照片编辑
- 备件图片上传
- 备件图片预览(列表页、详情页)
- 备件图片编辑
- 多图片支持测试
- 图片删除功能
- OSS Key正确存储验证
注意事项
- 数据兼容性:执行SQL脚本不会影响现有数据
- 字段长度:所有URL和Keys字段统一为 VARCHAR(1000)
- 逗号分隔:多个URL或Key使用英文逗号分隔
- 预签名URL:URL字段存储的是临时预签名URL,有效期限制
- OSS Key:Keys字段存储的是永久有效的OSS对象Key
- 批量转换:使用
convertListToPresignedUrl方法批量转换 - getter参数:第二个参数必须是
getXxxKeys方法 - setter参数:第三个参数必须是
setXxxUrl方法
常见问题
Q1: 为什么需要两个字段?
A: Keys字段永久有效,适合数据库存储;URL字段是临时的,适合前端展示。
Q2: 如何处理已有数据?
A: 执行SQL脚本后,已有数据的URL字段保留,新增Keys字段为空。需要手动迁移或通过程序转换。
Q3: 上传失败怎么办?
A: 检查OSS配置、文件大小限制、网络连接。
Q4: 如何支持更多文件格式?
A: 修改组件的 accept 属性,例如:accept=".jpg,.png,.pdf,.doc"
参考文档
- UnifiedAttachmentUpload组件:
ui/src/components/UnifiedAttachmentUpload/README.md - OssUtils工具类:
src/main/java/com/husky/common/utils/oss/OssUtils.java - 客户模块实现:参考已完成的客户管理模块
更新日志
- 2025-10-16: 完成客户模块改造
- 2025-10-16: 添加设备和备件实体类Keys字段
- 2025-10-16: 创建统一数据库迁移SQL脚本
- 2025-10-16: 修复客户Service中的批量转换逻辑
作者:聂盼盼 创建时间:2025-10-16 11:13
最后编辑:聂盼盼 更新时间:2025-10-28 19:53
最后编辑:聂盼盼 更新时间:2025-10-28 19:53