HaniBlindBox/.kiro/specs/image-upload-feature/design.md
2026-01-19 15:05:52 +08:00

296 lines
10 KiB
Markdown
Raw 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
本设计文档描述图片上传功能的技术实现方案。系统采用策略模式实现多存储提供者支持,后端使用 ASP.NET Core 实现上传接口,前端使用 Vue 3 + Element Plus 实现上传组件。
## Architecture
```
┌─────────────────────────────────────────────────────────────────┐
│ Frontend (Vue 3) │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ ImageUpload │ │ Business Pages │ │
│ │ Component │◄───│ (10 pages) │ │
│ └────────┬────────┘ └─────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ upload.ts API │ │
│ └────────┬────────┘ │
└───────────┼─────────────────────────────────────────────────────┘
│ HTTP POST /api/admin/upload/image
┌───────────────────────────────────────────────────────────────────┐
│ Backend (ASP.NET Core) │
│ ┌─────────────────┐ │
│ │ UploadController│ │
│ └────────┬────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ IUploadService │◄───│ UploadService │ │
│ └─────────────────┘ └────────┬────────┘ │
│ │ │
│ ┌──────────────────────┼──────────────────────┐ │
│ ▼ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐ │
│ │ IStorageProvider│ │LocalStorage │ │TencentCos │ │
│ │ (Interface) │◄───│Provider │ │Provider │ │
│ └─────────────────┘ └─────────────────┘ └──────────────┘ │
└───────────────────────────────────────────────────────────────────┘
```
## Components and Interfaces
### Backend Components
#### 1. IStorageProvider 接口
```csharp
public interface IStorageProvider
{
/// <summary>
/// 存储类型标识
/// </summary>
string StorageType { get; }
/// <summary>
/// 上传文件
/// </summary>
Task<UploadResult> UploadAsync(Stream fileStream, string fileName, string contentType);
/// <summary>
/// 删除文件
/// </summary>
Task<bool> DeleteAsync(string fileUrl);
}
```
#### 2. LocalStorageProvider 本地存储
```csharp
public class LocalStorageProvider : IStorageProvider
{
public string StorageType => "1";
// 保存到 wwwroot/uploads/{yyyy}/{MM}/{dd}/{filename}
// 返回 /uploads/{yyyy}/{MM}/{dd}/{filename}
}
```
#### 3. TencentCosProvider 腾讯云COS存储
```csharp
public class TencentCosProvider : IStorageProvider
{
public string StorageType => "3";
// 使用腾讯云COS SDK上传
// 返回 {Domain}/uploads/{yyyy}/{MM}/{dd}/{filename}
}
```
#### 4. IUploadService 上传服务接口
```csharp
public interface IUploadService
{
/// <summary>
/// 上传图片
/// </summary>
Task<UploadResponse> UploadImageAsync(IFormFile file);
/// <summary>
/// 批量上传图片
/// </summary>
Task<List<UploadResponse>> UploadImagesAsync(List<IFormFile> files);
}
```
#### 5. UploadService 上传服务实现
```csharp
public class UploadService : IUploadService
{
// 根据配置选择存储提供者
// 验证文件格式和大小
// 生成唯一文件名
// 调用存储提供者上传
}
```
#### 6. UploadController 上传控制器
```csharp
[Route("api/admin/upload")]
public class UploadController : BusinessControllerBase
{
[HttpPost("image")]
public async Task<IActionResult> UploadImage(IFormFile file);
[HttpPost("images")]
public async Task<IActionResult> UploadImages(List<IFormFile> files);
}
```
### Frontend Components
#### 1. ImageUpload 组件 (已创建)
位置: `src/components/ImageUpload/index.vue`
Props:
- `modelValue`: string - 图片URL (v-model)
- `disabled`: boolean - 是否禁用
- `placeholder`: string - 占位文字
- `showUrlInput`: boolean - 是否显示URL输入框
- `accept`: string - 接受的文件类型
- `maxSize`: number - 最大文件大小(MB)
- `tip`: string - 提示文字
Events:
- `update:modelValue` - URL变化
- `change` - 图片变化
- `upload-success` - 上传成功
- `upload-error` - 上传失败
#### 2. upload.ts API (已创建)
位置: `src/api/upload.ts`
```typescript
export function uploadFile(file: File, onProgress?: (percent: number) => void): Promise<ApiResponse<UploadResponse>>
export function uploadFiles(files: File[], onProgress?: (percent: number) => void): Promise<ApiResponse<UploadResponse[]>>
```
## Data Models
### Backend Models
```csharp
/// <summary>
/// 上传响应
/// </summary>
public class UploadResponse
{
/// <summary>
/// 文件URL
/// </summary>
public string Url { get; set; } = string.Empty;
/// <summary>
/// 文件名
/// </summary>
public string FileName { get; set; } = string.Empty;
/// <summary>
/// 文件大小(字节)
/// </summary>
public long FileSize { get; set; }
}
/// <summary>
/// 上传结果(内部使用)
/// </summary>
public class UploadResult
{
public bool Success { get; set; }
public string? Url { get; set; }
public string? ErrorMessage { get; set; }
}
```
### 上传配置 (已存在)
```csharp
public class UploadSetting
{
public string? Type { get; set; } // 1=本地, 3=腾讯云
public string? Bucket { get; set; } // COS Bucket名称
public string? Region { get; set; } // COS 地域
public string? AccessKeyId { get; set; } // COS SecretId
public string? AccessKeySecret { get; set; } // COS SecretKey
public string? Domain { get; set; } // 访问域名
}
```
## 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: 文件格式验证
*For any* 上传的文件,如果文件扩展名不在允许列表(jpg, jpeg, png, gif, webp)中THE Upload_Service SHALL 返回格式错误。
**Validates: Requirements 1.2, 1.4**
### Property 2: 文件大小验证
*For any* 上传的文件如果文件大小超过10MBTHE Upload_Service SHALL 返回大小超限错误。
**Validates: Requirements 1.3**
### Property 3: 文件名唯一性
*For any* 两次上传操作,即使上传相同的文件,生成的文件名 SHALL 不同。
**Validates: Requirements 1.5**
### Property 4: 存储策略一致性
*For any* 上传操作返回的URL格式 SHALL 与当前配置的存储类型一致:
- 本地存储: URL以 `/uploads/` 开头
- 腾讯云COS: URL以配置的 Domain 开头
**Validates: Requirements 2.3, 3.3**
### Property 5: 上传成功返回有效URL
*For any* 成功的上传操作返回的URL SHALL 是可访问的有效图片地址。
**Validates: Requirements 1.1**
## Error Handling
| 错误场景 | 错误码 | 错误信息 |
|---------|--------|---------|
| 文件为空 | 400 | 请选择要上传的文件 |
| 文件格式不支持 | 400 | 只支持 jpg、jpeg、png、gif、webp 格式的图片 |
| 文件大小超限 | 400 | 文件大小不能超过10MB |
| 存储配置无效 | 500 | 存储配置无效,请检查上传配置 |
| COS上传失败 | 500 | 上传到云存储失败: {具体错误} |
| 本地存储失败 | 500 | 保存文件失败: {具体错误} |
## Testing Strategy
### 单元测试
1. **UploadService 测试**
- 测试文件格式验证
- 测试文件大小验证
- 测试文件名生成唯一性
- 测试存储提供者选择逻辑
2. **LocalStorageProvider 测试**
- 测试目录创建
- 测试文件保存
- 测试URL生成
3. **TencentCosProvider 测试**
- 测试配置读取
- 测试上传逻辑使用Mock
### 集成测试
1. **API 集成测试**
- 测试上传接口完整流程
- 测试错误响应格式
### 前端测试
1. **ImageUpload 组件测试**
- 测试文件选择
- 测试上传进度显示
- 测试v-model绑定