19 KiB
19 KiB
v1.0.5 开发改动文档 - 支持连拍功能
一、需求概述
本次版本主要新增连拍功能,允许用户在一条工作记录中拍摄多张照片,所有照片共享相同的表单信息(位置、部门、工作内容等)。
需求要点
- 页面顶部增加"图片列表"区域,显示所有已拍摄图片缩略图
- 点击缩略图可切换预览
- 底部增加【继续拍照】【删除图片】按钮
- 所有图片统一使用第一张图片的水印信息
- 删除图片需二次确认
- 一条工作记录对应多张图片(不是多条记录)
- 兼容老数据(单图记录)
二、数据库改动(核心)
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脚本
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 老数据迁移脚本
重要:先执行建表脚本,再执行迁移脚本
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:
namespace ZR.Model.Business
{
/// <summary>
/// 工作记录图片
/// </summary>
[SugarTable("cam_workrecord_image")]
public class CamWorkrecordImage
{
/// <summary>
/// 主键
/// </summary>
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
public long Id { get; set; }
/// <summary>
/// 工作记录ID
/// </summary>
public int WorkrecordId { get; set; }
/// <summary>
/// 图片路径
/// </summary>
public string ImageUrl { get; set; }
/// <summary>
/// 排序(1=第一张封面图)
/// </summary>
public int SortOrder { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
/// <summary>
/// 更新时间
/// </summary>
public DateTime UpdateTime { get; set; }
}
}
3.4 DTO改动
CamWorkrecordDto.cs 修改:
public class CamRecordWorkDto
{
public int? Id { get; set; }
public string DeptName { get; set; }
/// <summary>
/// 单张图片Base64(兼容老版本APP)
/// </summary>
public string Image { get; set; }
/// <summary>
/// 多张图片Base64数组(新版本APP使用)
/// </summary>
public List<string> 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<string> Workers { get; set; }
}
/// <summary>
/// 工作记录图片DTO
/// </summary>
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 改动:
[HttpPost]
[Route("/addworkrecord")]
[AllowAnonymous]
public async Task<IActionResult> AddCamWorkRecord([FromBody] CamRecordWorkDto parm)
{
// 1. 参数校验
if (parm.Workers == null || parm.Workers.Count == 0)
return ToResponse(ResultCode.PARAM_ERROR, "请选择工作人员");
// 2. 获取图片列表(兼容新旧版本)
var imageList = new List<string>();
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<CamWorkrecord>().ToCreate(HttpContext);
modal.CreateTime = DateTime.Now;
modal.UpdateTime = DateTime.Now;
// 4. 处理图片并保存到 cam_workrecord_image 表
var savedImageUrls = new List<string>();
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 需要改动:
- 查询详情:返回图片列表
[HttpGet("{Id}")]
public IActionResult GetCamWorkrecord(int Id)
{
var response = _CamWorkrecordService.GetInfo(Id);
var info = response.Adapt<CamWorkrecordDto>();
// 获取图片列表
var images = _CamWorkrecordImageService.GetList(Id);
info.Images = images.Select(x => x.ImageUrl).ToList();
// ... 其他逻辑
return SUCCESS(info);
}
- 导出Excel:支持多图(显示第一张或全部)
// 导出时获取每条记录的所有图片
// 可选方案:只显示第一张,或合并显示所有图片路径
- 删除记录:级联删除图片
// 删除工作记录时,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 列表页改动
显示图片数量或缩略图列表:
<el-table-column prop="imageUrl" label="图片" width="160">
<template #default="scope">
<div class="image-list">
<!-- 显示第一张作为封面 -->
<ImagePreview :src="scope.row.imageUrl" />
<!-- 显示图片数量 -->
<span v-if="scope.row.imageCount > 1" class="image-count">
+{{ scope.row.imageCount - 1 }}
</span>
</div>
</template>
</el-table-column>
4.3 详情页改动
显示所有图片:
<el-form-item label="施工图片">
<div class="image-gallery">
<div v-for="(img, index) in form.images" :key="index" class="image-item">
<ImagePreview :src="img" />
<span class="image-index">{{ index + 1 }}</span>
</div>
</div>
</el-form-item>
4.4 编辑页改动
确认需求:允许增删图片
支持多图上传/管理:
- 显示现有图片列表(带排序序号)
- 支持添加新图片(限制最多15张)
- 支持删除图片(至少保留1张)
- 支持拖拽排序(可选)
UI示例:
<el-form-item label="施工图片">
<div class="image-manager">
<!-- 图片列表 -->
<div v-for="(img, index) in form.images" :key="index" class="image-item">
<ImagePreview :src="img.imageUrl" />
<span class="image-index">{{ index + 1 }}</span>
<el-button
type="danger"
size="small"
icon="delete"
:disabled="form.images.length <= 1"
@click="removeImage(index)">
</el-button>
</div>
<!-- 添加图片按钮 -->
<el-upload
v-if="form.images.length < 15"
:auto-upload="false"
:show-file-list="false"
@change="handleAddImage">
<el-button icon="plus">添加图片</el-button>
</el-upload>
<div class="image-tip">
已上传 {{ form.images.length }}/15 张图片
</div>
</div>
</el-form-item>
后端接口改动:
- 编辑时需要支持:新增图片、删除图片、更新排序
- 可采用"先删后增"策略:删除原有图片记录,重新插入新的图片列表
4.5 导出Excel改动
确认需求:导出本记录的所有图片
实现方案:
- 每条记录可能有多张图片,需要调整Excel布局
- 方案1:多张图片横向排列在同一单元格(推荐)
- 方案2:多张图片纵向排列,合并其他列单元格
代码改动思路:
// 导出时获取每条记录的所有图片
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 数据结构改动
data() {
return {
imageList: [], // 图片列表 [{original: '', watermark: '', id: ''}]
currentIndex: 0, // 当前选中图片索引
maxImageCount: 15, // 最大图片数量限制
// ...其他字段保持不变
}
}
5.3 继续拍照限制
async continueCapture() {
// 检查是否达到最大数量
if (this.imageList.length >= this.maxImageCount) {
uni.showToast({
title: '最多只能拍摄15张图片',
icon: 'none'
})
return
}
// ... 继续拍照逻辑
}
5.4 提交数据改动
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