WorkCamera/.kiro/specs/work-camera-2.0/design.md
2026-01-05 08:49:56 +08:00

481 lines
18 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Design Document
## Overview
随工水印相机 2.0 系统升级设计,主要包含四个核心模块:
1. **图片上传改造** - 将图片存储从服务器本地迁移到腾讯云 COS实现客户端直传
2. **数据导出 API** - 提供分页查询接口供 CS 客户端调用
3. **CS 客户端** - Windows 桌面应用,实现本地 Excel 导出
4. **历史数据迁移** - 将服务器本地图片迁移到 COS
## Architecture
```
┌─────────────────────────────────────────────────────────────────────────┐
│ System Architecture │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────────┐ │
│ │ UniApp │ │ CS Client │ │ 腾讯云 COS │ │
│ │ (Mobile) │ │ (Windows) │ │ (ap-shanghai) │ │
│ └──────┬───────┘ └──────┬───────┘ └────────────┬─────────────┘ │
│ │ │ │ │
│ │ 1.获取预签名URL │ │ │
│ ├────────────────────┼──────────────────────────┤ │
│ │ │ │ │
│ │ 2.直传图片 ────────┼──────────────────────────► │
│ │ │ │ │
│ │ 3.保存记录 │ 4.查询/导出 │ │
│ ├────────────────────┼──────────────────────────┤ │
│ │ │ │ │
│ ▼ ▼ │ │
│ ┌──────────────────────────────────────────────────────┤ │
│ │ .NET API Server │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ CosService │ │ WorkRecord │ │ Migration │ │ │
│ │ │ │ │ Service │ │ Service │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ SQL Server │ │
│ │ Database │ │
│ └──────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
```
## Components and Interfaces
### 1. COS Service (后端)
负责腾讯云 COS 相关操作,包括生成预签名 URL 和临时密钥。
```csharp
public interface ICosService
{
/// <summary>
/// 生成批量上传预签名URL
/// </summary>
/// <param name="request">上传请求参数</param>
/// <returns>预签名URL列表</returns>
CosUploadUrlsResponse GetUploadUrls(CosUploadUrlsRequest request);
/// <summary>
/// 获取临时密钥(用于迁移)
/// </summary>
/// <returns>临时密钥信息</returns>
CosTempCredentials GetTempCredentials();
}
```
### 2. COS Controller (后端)
提供 COS 相关的 HTTP 接口。
```csharp
[Route("api/cos")]
public class CosController : BaseController
{
/// <summary>
/// 获取上传预签名URL
/// POST /api/cos/getUploadUrls
/// </summary>
Task<IActionResult> GetUploadUrls([FromBody] CosUploadUrlsRequest request);
/// <summary>
/// 获取临时密钥
/// GET /api/cos/getTempCredentials
/// </summary>
Task<IActionResult> GetTempCredentials();
}
```
### 3. WorkRecord V3 接口 (后端)
新增支持 COS URL 的工作记录保存接口。
```csharp
/// <summary>
/// 添加工作记录COS直传 v3
/// POST /addworkrecordv3
/// </summary>
Task<IActionResult> AddCamWorkRecordV3([FromBody] CamRecordWorkV3Dto parm);
```
### 4. Export API (后端)
提供数据导出查询接口。
```csharp
[Route("api/workrecord/export")]
public class WorkRecordExportController : BaseController
{
/// <summary>
/// 分页查询工作记录(导出用)
/// GET /api/workrecord/export/list
/// </summary>
Task<IActionResult> GetExportList([FromQuery] WorkRecordExportQueryDto query);
}
```
### 5. Migration API (后端)
提供历史数据迁移相关接口。
```csharp
[Route("api/workrecord/migration")]
public class WorkRecordMigrationController : BaseController
{
/// <summary>
/// 获取待迁移记录列表
/// GET /api/workrecord/migration/list
/// </summary>
Task<IActionResult> GetMigrationList([FromQuery] MigrationQueryDto query);
/// <summary>
/// 更新迁移后的URL
/// POST /api/workrecord/migration/update
/// </summary>
Task<IActionResult> UpdateMigrationUrls([FromBody] MigrationUpdateDto dto);
}
```
### 6. CS Client Architecture
```
┌─────────────────────────────────────────────────────────────────┐
│ CS Client (WinForms) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ MainForm │ │ MigrationForm │ │ LoginForm │ │
│ │ (导出界面) │ │ (迁移界面) │ │ (登录界面) │ │
│ └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Services Layer │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │ │
│ │ │ ApiService │ │ CosService │ │ ExcelService │ │ │
│ │ │ (HTTP调用) │ │ (COS上传) │ │ (Excel生成) │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────────┘ │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
## Data Models
### 1. COS 上传请求/响应 DTO
```csharp
/// <summary>
/// COS上传URL请求
/// </summary>
public class CosUploadUrlsRequest
{
public DateTime RecordTime { get; set; }
public string DeptName { get; set; }
public string Content { get; set; }
public List<string> Workers { get; set; }
public string FileExt { get; set; } = ".jpg";
public int ImageCount { get; set; }
}
/// <summary>
/// COS上传URL响应
/// </summary>
public class CosUploadUrlsResponse
{
public List<CosImageUploadInfo> Images { get; set; }
}
/// <summary>
/// 单张图片上传信息
/// </summary>
public class CosImageUploadInfo
{
public string ImageId { get; set; }
public string FileName { get; set; }
public CosUploadUrls UploadUrls { get; set; }
public string AccessUrl { get; set; }
}
/// <summary>
/// 各分类目录的上传URL
/// </summary>
public class CosUploadUrls
{
public string Daily { get; set; }
public Dictionary<string, string> Workers { get; set; }
public string Content { get; set; }
public string Dept { get; set; }
}
```
### 2. 工作记录 V3 DTO
```csharp
/// <summary>
/// 工作记录V3请求COS直传
/// </summary>
public class CamRecordWorkV3Dto
{
public int? Id { get; set; }
public string DeptName { 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>
/// COS图片URL列表替代Base64
/// </summary>
public List<string> ImageUrls { get; set; }
}
```
### 3. 导出查询 DTO
```csharp
/// <summary>
/// 导出查询请求
/// </summary>
public class WorkRecordExportQueryDto
{
public int PageNum { get; set; } = 1;
public int PageSize { get; set; } = 50;
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public string DeptName { get; set; }
public string WorkerName { get; set; }
public string Content { get; set; }
}
/// <summary>
/// 导出记录响应
/// </summary>
public class WorkRecordExportDto
{
public int Id { get; set; }
public string DeptName { 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 List<string> Workers { get; set; }
public List<string> Images { get; set; }
public DateTime? CreateTime { get; set; }
public DateTime? UpdateTime { get; set; }
}
```
### 4. 迁移相关 DTO
```csharp
/// <summary>
/// 迁移查询请求
/// </summary>
public class MigrationQueryDto
{
public int PageNum { get; set; } = 1;
public int PageSize { get; set; } = 50;
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public int? Status { get; set; } // 0-未迁移 1-已迁移 2-失败
}
/// <summary>
/// 迁移记录响应
/// </summary>
public class MigrationRecordDto
{
public int Id { get; set; }
public DateTime? RecordTime { get; set; }
public string DeptName { get; set; }
public string Content { get; set; }
public int ImageCount { get; set; }
public List<MigrationImageDto> Images { get; set; }
public int MigrationStatus { get; set; }
}
/// <summary>
/// 迁移URL更新请求
/// </summary>
public class MigrationUpdateDto
{
public int RecordId { get; set; }
public List<MigrationUrlPair> ImageUrls { get; set; }
}
public class MigrationUrlPair
{
public string OldUrl { get; set; }
public string NewUrl { get; set; }
}
```
## COS Configuration
腾讯云 COS 配置将存储在 `appsettings.json` 中:
```json
{
"TencentCOS": {
"AppId": "1308826010",
"Region": "ap-shanghai",
"SecretId": "AKIDVyMfzKZdZP8zkNyOdsFuSsBJDB7EScs0",
"SecretKey": "89GWr7JPWYTL8ueHlAYowGZnvzKZjqs9",
"BucketName": "miaoyu",
"DomainUrl": "https://miaoyu-1308826010.cos.ap-shanghai.myqcloud.com",
"MaxSize": 100,
"DurationSecond": 600,
"Prefixes": "workfiles"
}
}
```
## COS Directory Structure
保持与现有本地存储一致的目录结构:
```
/workfiles/{yyyyMM}/{yyyyMMdd}/
├── 当日照片/{timestamp}_{random}.jpg
├── 参与人员/{人员姓名}/{timestamp}_{random}.jpg
├── 工作内容/{工作内容}/{timestamp}_{random}.jpg
└── 部门/{部门名称}/{timestamp}_{random}.jpg
```
## Correctness Properties
*A property is a characteristic or behavior that should hold true across all valid executions of a system-essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.*
### Property 1: Pre-signed URL Generation Completeness
*For any* valid upload request with N images and M workers, the API SHALL return exactly N image entries, each containing:
- 1 daily photo URL
- M worker directory URLs (one per worker)
- 1 content directory URL
- 1 department directory URL
- All URLs following the pattern `/workfiles/{yyyyMM}/{yyyyMMdd}/{category}/{subcategory}/{timestamp}_{random}.{ext}`
**Validates: Requirements 1.1, 1.2, 1.4, 1.5**
### Property 2: COS URL Validation
*For any* URL submitted to the V3 interface, the system SHALL accept only URLs matching the COS domain pattern `https://miaoyu-1308826010.cos.ap-shanghai.myqcloud.com/workfiles/...` and reject all other URLs.
**Validates: Requirements 3.3**
### Property 3: V3 Record Save Integrity
*For any* valid V3 save request with N image URLs, the system SHALL:
- Create exactly one work record in database
- Store all N image URLs in the image table
- Return the created record ID and image count = N
**Validates: Requirements 3.1, 3.4**
### Property 4: Export Pagination Consistency
*For any* export query with total N records and page size P, iterating through all ceil(N/P) pages SHALL return exactly N unique records with no duplicates or missing entries. Page size SHALL be capped at 50 regardless of requested value.
**Validates: Requirements 4.1, 4.2, 4.4**
### Property 5: Export Filter Accuracy
*For any* export query with filters (date range, department, worker, content), all returned records SHALL match ALL specified filter criteria.
**Validates: Requirements 4.3**
### Property 6: Migration List Filter
*For any* migration list query with status filter, all returned records SHALL have the specified migration status (0-unmigrated, 1-migrated, 2-failed).
**Validates: Requirements 10.1, 10.2**
### Property 7: Migration URL Update Integrity
*For any* migration update request with N URL pairs, the system SHALL:
- Validate all new URLs are valid COS URLs
- Update all N URLs atomically (all succeed or all fail)
- Preserve the mapping between old and new URLs
**Validates: Requirements 10.3, 10.4**
## Error Handling
### API Error Responses
| 错误码 | 说明 | 处理方式 |
|--------|------|----------|
| 400 | 参数错误 | 返回具体错误字段 |
| 401 | 未授权 | 要求重新登录 |
| 403 | 无权限 | 提示权限不足 |
| 500 | 服务器错误 | 记录日志,返回友好提示 |
### COS 上传错误处理
1. **预签名 URL 过期** - 客户端重新获取 URL
2. **上传失败** - 客户端重试最多 3 次
3. **部分上传成功** - 记录失败的目录,允许重试
### CS 客户端错误处理
1. **网络超时** - 自动重试,显示重试进度
2. **下载失败** - 跳过失败图片,记录日志
3. **Excel 生成失败** - 保存已下载数据,允许重新生成
## Testing Strategy
### Unit Tests
使用 xUnit 进行单元测试:
1. **CosService Tests**
- 测试预签名 URL 生成逻辑
- 测试目录路径生成
- 测试文件名生成
2. **WorkRecordService Tests**
- 测试 V3 接口数据保存
- 测试查询过滤逻辑
- 测试分页逻辑
3. **MigrationService Tests**
- 测试迁移状态判断
- 测试 URL 更新逻辑
### Property-Based Tests
使用 FsCheck 进行属性测试:
1. **Property 1: Pre-signed URL Generation Completeness**
- 生成随机的上传请求参数
- 验证返回的 URL 数量和结构
2. **Property 4: Pagination Consistency**
- 生成随机数量的测试数据
- 验证分页遍历的完整性
### Integration Tests
1. **COS 集成测试**
- 测试实际上传到 COS
- 测试预签名 URL 有效性
2. **API 集成测试**
- 测试完整的上传流程
- 测试导出 API 响应
### CS Client Tests
1. **API 调用测试**
- Mock API 响应测试
- 错误处理测试
2. **Excel 生成测试**
- 测试 Excel 格式正确性
- 测试图片嵌入功能