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

18 KiB
Raw Blame History

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 和临时密钥。

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 接口。

[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 的工作记录保存接口。

/// <summary>
/// 添加工作记录COS直传 v3
/// POST /addworkrecordv3
/// </summary>
Task<IActionResult> AddCamWorkRecordV3([FromBody] CamRecordWorkV3Dto parm);

4. Export API (后端)

提供数据导出查询接口。

[Route("api/workrecord/export")]
public class WorkRecordExportController : BaseController
{
    /// <summary>
    /// 分页查询工作记录(导出用)
    /// GET /api/workrecord/export/list
    /// </summary>
    Task<IActionResult> GetExportList([FromQuery] WorkRecordExportQueryDto query);
}

5. Migration API (后端)

提供历史数据迁移相关接口。

[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

/// <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

/// <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

/// <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

/// <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 中:

{
  "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 格式正确性
    • 测试图片嵌入功能