# v1.0.5 开发改动文档 - 支持连拍功能 ## 一、需求概述 本次版本主要新增**连拍功能**,允许用户在**一条工作记录**中拍摄**多张照片**,所有照片共享相同的表单信息(位置、部门、工作内容等)。 ### 需求要点 1. 页面顶部增加"图片列表"区域,显示所有已拍摄图片缩略图 2. 点击缩略图可切换预览 3. 底部增加【继续拍照】【删除图片】按钮 4. 所有图片统一使用第一张图片的水印信息 5. 删除图片需二次确认 6. **一条工作记录对应多张图片**(不是多条记录) 7. 兼容老数据(单图记录) --- ## 二、数据库改动(核心) ### 2.1 当前表结构 **cam_workrecord(工作记录表)** | 字段名 | 类型 | 说明 | |--------|------|------| | Id | int (PK, 自增) | 主键 | | RecordTime | datetime | 拍照时间 | | Address | nvarchar(max) | 地址 | | Longitude | nvarchar(100) | 经度 | | Latitude | nvarchar(100) | 纬度 | | Content | nvarchar(max) | 工作内容 | | Remarks | nvarchar(max) | 备注 | | DeptName | nvarchar(100) | 部门名称 | | StatusName | nvarchar(100) | 状态 | | **ImageUrl** | **nvarchar(300)** | **图片路径(单张,将废弃)** | | CreateTime | datetime | 创建时间 | | UpdateTime | datetime | 更新时间 | **cam_worker(施工人员表)** | 字段名 | 类型 | 说明 | |--------|------|------| | Id | bigint (PK, 自增) | 主键 | | WorkrecordId | int (FK) | 关联工作记录ID | | WorkerName | nvarchar(100) | 人员姓名 | | CreateTime | datetime | 创建时间 | | UpdateTime | datetime | 更新时间 | ### 2.2 新增表结构 **cam_workrecord_image(新增:工作记录图片表)** | 字段名 | 类型 | 说明 | |--------|------|------| | Id | bigint (PK, 自增) | 主键 | | WorkrecordId | int (FK) | 关联工作记录ID | | ImageUrl | nvarchar(500) | 图片路径 | | SortOrder | int | 排序(1=第一张,作为封面) | | CreateTime | datetime | 创建时间 | | UpdateTime | datetime | 更新时间 | ### 2.3 建表SQL脚本 ```sql USE [WatermarkCamera] GO -- 创建工作记录图片表 CREATE TABLE [dbo].[cam_workrecord_image]( [Id] [bigint] IDENTITY(1,1) NOT NULL, [WorkrecordId] [int] NOT NULL, [ImageUrl] [nvarchar](500) NOT NULL, [SortOrder] [int] NOT NULL DEFAULT 1, [CreateTime] [datetime] NOT NULL DEFAULT (getdate()), [UpdateTime] [datetime] NOT NULL DEFAULT (getdate()), CONSTRAINT [PK_cam_workrecord_image] PRIMARY KEY CLUSTERED ([Id] ASC) ) ON [PRIMARY] GO -- 添加外键约束 ALTER TABLE [dbo].[cam_workrecord_image] ADD CONSTRAINT [FK_cam_workrecord_image_workrecord] FOREIGN KEY ([WorkrecordId]) REFERENCES [dbo].[cam_workrecord]([Id]) ON DELETE CASCADE GO -- 添加索引 CREATE NONCLUSTERED INDEX [IX_cam_workrecord_image_WorkrecordId] ON [dbo].[cam_workrecord_image] ([WorkrecordId] ASC) GO -- 添加字段说明 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'主键', @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'cam_workrecord_image', @level2type=N'COLUMN',@level2name=N'Id' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'工作记录ID', @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'cam_workrecord_image', @level2type=N'COLUMN',@level2name=N'WorkrecordId' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'图片路径', @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'cam_workrecord_image', @level2type=N'COLUMN',@level2name=N'ImageUrl' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'排序(1=第一张封面图)', @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'cam_workrecord_image', @level2type=N'COLUMN',@level2name=N'SortOrder' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'创建时间', @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'cam_workrecord_image', @level2type=N'COLUMN',@level2name=N'CreateTime' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'更新时间', @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'cam_workrecord_image', @level2type=N'COLUMN',@level2name=N'UpdateTime' GO ``` ### 2.4 老数据迁移脚本 > **重要**:先执行建表脚本,再执行迁移脚本 ```sql USE [WatermarkCamera] GO -- 迁移老数据:将 cam_workrecord.ImageUrl 迁移到 cam_workrecord_image 表 INSERT INTO [dbo].[cam_workrecord_image] ([WorkrecordId], [ImageUrl], [SortOrder], [CreateTime], [UpdateTime]) SELECT [Id] AS WorkrecordId, [ImageUrl], 1 AS SortOrder, -- 老数据都是第一张(封面图) ISNULL([CreateTime], GETDATE()), ISNULL([UpdateTime], GETDATE()) FROM [dbo].[cam_workrecord] WHERE [ImageUrl] IS NOT NULL AND [ImageUrl] <> '' GO -- 验证迁移结果 SELECT '迁移前 cam_workrecord 有图片记录数' AS [说明], COUNT(*) AS [数量] FROM [dbo].[cam_workrecord] WHERE [ImageUrl] IS NOT NULL AND [ImageUrl] <> '' UNION ALL SELECT '迁移后 cam_workrecord_image 记录数' AS [说明], COUNT(*) AS [数量] FROM [dbo].[cam_workrecord_image] GO -- 注意:暂不删除 cam_workrecord.ImageUrl 字段,保持兼容性 -- 后续版本可考虑废弃该字段 ``` ### 2.5 数据结构示意 **迁移后数据示例:** cam_workrecord: | Id | Content | DeptName | ImageUrl(保留兼容) | |----|---------|----------|---------------------| | 101 | 混凝土浇筑 | 建筑部 | /workfiles/.../img1.jpg | cam_workrecord_image: | Id | WorkrecordId | ImageUrl | SortOrder | |----|--------------|----------|-----------| | 1 | 101 | /workfiles/.../img1.jpg | 1 | **新增连拍数据示例:** cam_workrecord: | Id | Content | DeptName | ImageUrl(封面图) | |----|---------|----------|-------------------| | 102 | 模板搭建 | 建筑部 | /workfiles/.../img2.jpg | cam_workrecord_image: | Id | WorkrecordId | ImageUrl | SortOrder | |----|--------------|----------|-----------| | 2 | 102 | /workfiles/.../img2.jpg | 1 | | 3 | 102 | /workfiles/.../img3.jpg | 2 | | 4 | 102 | /workfiles/.../img4.jpg | 3 | --- ## 三、后端改动 ### 3.1 改动文件清单 | 文件路径 | 改动说明 | |----------|----------| | `ZR.Model/Business/CamWorkrecordImage.cs` | **新增**:图片实体类 | | `ZR.Model/Business/Dto/CamWorkrecordDto.cs` | 修改:DTO新增图片列表字段 | | `ZR.Service/Business/CamWorkrecordImageService.cs` | **新增**:图片服务类 | | `ZR.Admin.WebApi/Controllers/CommonController.cs` | 修改:接口支持多图 | | `ZR.Admin.WebApi/Controllers/Business/CamWorkrecordController.cs` | 修改:后台接口支持多图、导出Excel | ### 3.2 接口策略 > **重要说明**:原有接口需要改动,但要**保持入参兼容**! > > 原因:老版本APP传单张图片,新版本APP传多张图片,接口需要同时支持。 | 接口 | 用途 | 改动 | |------|------|------| | `/addworkrecord` | 单图/多图提交 | **改动**:支持多图,同时兼容单图 | | `/addworkrecords` | 多图批量提交(可选) | **新增**(可选) | ### 3.3 实体类改动 **新增 CamWorkrecordImage.cs:** ```csharp namespace ZR.Model.Business { /// /// 工作记录图片 /// [SugarTable("cam_workrecord_image")] public class CamWorkrecordImage { /// /// 主键 /// [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] public long Id { get; set; } /// /// 工作记录ID /// public int WorkrecordId { get; set; } /// /// 图片路径 /// public string ImageUrl { get; set; } /// /// 排序(1=第一张封面图) /// public int SortOrder { get; set; } /// /// 创建时间 /// public DateTime CreateTime { get; set; } /// /// 更新时间 /// public DateTime UpdateTime { get; set; } } } ``` ### 3.4 DTO改动 **CamWorkrecordDto.cs 修改:** ```csharp public class CamRecordWorkDto { public int? Id { get; set; } public string DeptName { get; set; } /// /// 单张图片Base64(兼容老版本APP) /// public string Image { get; set; } /// /// 多张图片Base64数组(新版本APP使用) /// public List Images { get; set; } public string ImageUrl { get; set; } public DateTime? RecordTime { get; set; } public string Longitude { get; set; } public string Latitude { get; set; } public string Address { get; set; } public string Content { get; set; } public string StatusName { get; set; } public string Remarks { get; set; } public List Workers { get; set; } } /// /// 工作记录图片DTO /// public class CamWorkrecordImageDto { public long Id { get; set; } public int WorkrecordId { get; set; } public string ImageUrl { get; set; } public int SortOrder { get; set; } } ``` ### 3.5 接口改动逻辑 **CommonController.cs - AddCamWorkRecord 改动:** ```csharp [HttpPost] [Route("/addworkrecord")] [AllowAnonymous] public async Task AddCamWorkRecord([FromBody] CamRecordWorkDto parm) { // 1. 参数校验 if (parm.Workers == null || parm.Workers.Count == 0) return ToResponse(ResultCode.PARAM_ERROR, "请选择工作人员"); // 2. 获取图片列表(兼容新旧版本) var imageList = new List(); if (parm.Images != null && parm.Images.Count > 0) { // 新版本APP:多张图片 imageList = parm.Images; } else if (!string.IsNullOrEmpty(parm.Image)) { // 老版本APP:单张图片 imageList.Add(parm.Image); } else if (string.IsNullOrEmpty(parm.ImageUrl)) { return ToResponse(ResultCode.PARAM_ERROR, "请上传图片"); } // 3. 保存工作记录(只保存一条) var modal = parm.Adapt().ToCreate(HttpContext); modal.CreateTime = DateTime.Now; modal.UpdateTime = DateTime.Now; // 4. 处理图片并保存到 cam_workrecord_image 表 var savedImageUrls = new List(); int sortOrder = 1; foreach (var imageBase64 in imageList) { var imageUrl = await SaveImageFile(imageBase64, parm); savedImageUrls.Add(imageUrl); // 保存图片记录 var imageRecord = new CamWorkrecordImage { WorkrecordId = modal.Id, ImageUrl = imageUrl, SortOrder = sortOrder++, CreateTime = DateTime.Now, UpdateTime = DateTime.Now }; await _CamWorkrecordImageService.InsertAsync(imageRecord); } // 5. 更新主表的 ImageUrl(封面图,兼容老逻辑) if (savedImageUrls.Count > 0) { modal.ImageUrl = savedImageUrls[0]; await _CamWorkrecordService.UpdateAsync(modal); } // 6. 保存施工人员 // ... 原有逻辑 return SUCCESS(new { id = modal.Id, imageCount = savedImageUrls.Count }); } ``` ### 3.6 后台接口改动 **CamWorkrecordController.cs 需要改动:** 1. **查询详情**:返回图片列表 ```csharp [HttpGet("{Id}")] public IActionResult GetCamWorkrecord(int Id) { var response = _CamWorkrecordService.GetInfo(Id); var info = response.Adapt(); // 获取图片列表 var images = _CamWorkrecordImageService.GetList(Id); info.Images = images.Select(x => x.ImageUrl).ToList(); // ... 其他逻辑 return SUCCESS(info); } ``` 2. **导出Excel**:支持多图(显示第一张或全部) ```csharp // 导出时获取每条记录的所有图片 // 可选方案:只显示第一张,或合并显示所有图片路径 ``` 3. **删除记录**:级联删除图片 ```csharp // 删除工作记录时,cam_workrecord_image 会自动级联删除(外键约束) ``` ### 3.7 兼容性说明 | 场景 | 处理方式 | |------|----------| | 老版本APP传 `Image` 字段 | 兼容,转为单元素数组处理 | | 新版本APP传 `Images` 数组 | 正常处理多图 | | 老数据查询 | 从 `cam_workrecord_image` 表读取(已迁移) | | 新数据查询 | 从 `cam_workrecord_image` 表读取 | | `ImageUrl` 字段 | 保留作为封面图,兼容老代码 | --- ## 四、后台管理改动 ### 4.1 改动文件 | 文件路径 | 改动说明 | |----------|----------| | `ZR.Vue/src/views/business/CamWorkrecord.vue` | 列表/详情显示多图 | | `ZR.Vue/src/api/business/camworkrecord.js` | API调整(可选) | ### 4.2 列表页改动 **显示图片数量或缩略图列表:** ```html ``` ### 4.3 详情页改动 **显示所有图片:** ```html ``` ### 4.4 编辑页改动 > **确认需求**:允许增删图片 **支持多图上传/管理:** - 显示现有图片列表(带排序序号) - 支持添加新图片(限制最多15张) - 支持删除图片(至少保留1张) - 支持拖拽排序(可选) **UI示例:** ```html
{{ index + 1 }}
添加图片
已上传 {{ form.images.length }}/15 张图片
``` **后端接口改动:** - 编辑时需要支持:新增图片、删除图片、更新排序 - 可采用"先删后增"策略:删除原有图片记录,重新插入新的图片列表 ### 4.5 导出Excel改动 > **确认需求**:导出本记录的所有图片 **实现方案:** - 每条记录可能有多张图片,需要调整Excel布局 - 方案1:多张图片横向排列在同一单元格(推荐) - 方案2:多张图片纵向排列,合并其他列单元格 **代码改动思路:** ```csharp // 导出时获取每条记录的所有图片 var images = _CamWorkrecordImageService.GetListByWorkrecordId(item.Id); // 计算需要的列宽或行高 int imageCount = images.Count; int imageWidth = 100; // 单张图片宽度 int totalWidth = imageWidth * Math.Min(imageCount, 5); // 最多显示5张,超出换行 // 将多张图片绘制到Excel单元格中 foreach (var img in images) { // 绘制图片... } ``` **注意事项:** - 图片过多时Excel文件会很大,建议压缩图片质量 - 考虑增加"图片数量"列,方便查看 --- ## 五、前端APP改动 ### 5.1 改动文件 | 文件路径 | 改动说明 | |----------|----------| | `uniapp/WorkCameraf/pages/index/index.vue` | 主要改动,UI和逻辑 | | `uniapp/WorkCameraf/common/utils.js` | 水印处理调整 | | `uniapp/WorkCameraf/common/server.js` | 接口调用参数调整 | ### 5.2 数据结构改动 ```javascript data() { return { imageList: [], // 图片列表 [{original: '', watermark: '', id: ''}] currentIndex: 0, // 当前选中图片索引 maxImageCount: 15, // 最大图片数量限制 // ...其他字段保持不变 } } ``` ### 5.3 继续拍照限制 ```javascript async continueCapture() { // 检查是否达到最大数量 if (this.imageList.length >= this.maxImageCount) { uni.showToast({ title: '最多只能拍摄15张图片', icon: 'none' }) return } // ... 继续拍照逻辑 } ``` ### 5.4 提交数据改动 ```javascript async submitData() { const images = this.imageList.map(item => item.watermark) const params = { // ... 其他字段 Images: images, // 新增:多张图片数组 // Image: xxx, // 不再使用单张字段 } await addWatermarkRecord(params) } ``` --- ## 六、开发任务清单 ### 6.1 数据库任务 - [ ] 1. 执行建表脚本(cam_workrecord_image) - [ ] 2. 执行老数据迁移脚本 - [ ] 3. 验证迁移结果 ### 6.2 后端任务 - [ ] 1. 新增 `CamWorkrecordImage` 实体类 - [ ] 2. 新增 `ICamWorkrecordImageService` 服务接口和实现 - [ ] 3. 修改 `CamRecordWorkDto`,新增 `Images` 字段 - [ ] 4. 修改 `/addworkrecord` 接口,支持多图(兼容单图) - [ ] 5. 修改查询接口,返回图片列表 - [ ] 6. 修改删除接口,确保级联删除图片 - [ ] 7. 修改导出Excel,处理多图场景 - [ ] 8. 接口测试 ### 6.3 后台前端任务 - [ ] 1. 列表页:显示图片数量或缩略图 - [ ] 2. 详情页:显示所有图片 - [ ] 3. 编辑页:支持多图管理 - [ ] 4. 测试验证 ### 6.4 APP前端任务 - [ ] 1. 修改数据结构,支持图片列表 - [ ] 2. 添加图片列表UI组件 - [ ] 3. 实现图片切换功能 - [ ] 4. 实现继续拍照功能 - [ ] 5. 实现删除图片功能(含二次确认) - [ ] 6. 修改提交逻辑,传 `Images` 数组 - [ ] 7. 样式调整和优化 - [ ] 8. H5端测试 - [ ] 9. APP端测试 --- ## 七、需求确认事项 | 序号 | 问题 | 确认结果 | 状态 | |------|------|----------|------| | 1 | 连拍最多支持几张图片? | **最多15张** | ✅ 已确认 | | 2 | 后台导出Excel是否需要导出所有图片? | **导出本记录的所有图片** | ✅ 已确认 | | 3 | 后台编辑时是否允许增删图片? | **允许增删图片** | ✅ 已确认 | | 4 | 是否需要删除 `cam_workrecord.ImageUrl` 字段? | **保留兼容,需写迁移脚本** | ✅ 已确认 | | 5 | 图片文件存储路径是否需要调整? | **保持现有结构** | ✅ 已确认 | --- ## 八、风险评估 | 风险项 | 风险等级 | 应对措施 | |--------|----------|----------| | 老数据迁移失败 | 高 | 迁移前备份数据库,验证迁移结果 | | 老版本APP不兼容 | 中 | 接口保持入参兼容,支持单图和多图 | | 多图上传超时 | 中 | 前端压缩,限制图片数量和大小 | | 后台显示异常 | 中 | 兼容处理无图片或单图场景 | --- ## 九、版本计划 - 数据库迁移:上线前执行 - 开发周期:待定 - 测试周期:待定 - 上线时间:待定 --- **文档版本**:v2.0 **编写日期**:2025-12-27 **编写人**:Claude AI Assistant