291 lines
12 KiB
Markdown
291 lines
12 KiB
Markdown
# Design Document: Float Ball Migration
|
|
|
|
## Overview
|
|
|
|
本设计文档描述悬浮球功能从 PHP 后端迁移到 .NET 10 后端的技术方案。包括数据库表设计、数据迁移脚本、API 接口实现和 Entity Framework 配置。
|
|
|
|
悬浮球是首页显示的可点击浮动图标,支持两种交互方式:
|
|
1. **展示图片** (type=1): 点击后弹出图片弹窗
|
|
2. **跳转页面** (type=2): 点击后跳转到指定页面
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Frontend (UniApp) │
|
|
│ FloatBall.vue Component │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
│
|
|
│ GET /api/getFloatBall
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ HoneyBox.Api Layer │
|
|
│ ConfigController.cs │
|
|
│ [AllowAnonymous] endpoint │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ HoneyBox.Core Layer │
|
|
│ IFloatBallService.cs │
|
|
│ FloatBallService.cs │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ HoneyBox.Model Layer │
|
|
│ FloatBallConfig.cs (Entity) │
|
|
│ FloatBallResponse.cs (DTO) │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ SQL Server │
|
|
│ float_ball_configs table │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## Components and Interfaces
|
|
|
|
### 1. Database Table: float_ball_configs
|
|
|
|
```sql
|
|
CREATE TABLE float_ball_configs (
|
|
id INT IDENTITY(1,1) PRIMARY KEY,
|
|
status TINYINT NOT NULL DEFAULT 0, -- 状态: 0关闭 1开启
|
|
type TINYINT NOT NULL DEFAULT 1, -- 类型: 1展示图片 2跳转页面
|
|
image NVARCHAR(255) NOT NULL DEFAULT '', -- 悬浮球图片URL
|
|
link_url NVARCHAR(255) NOT NULL DEFAULT '', -- 跳转链接
|
|
position_x NVARCHAR(30) NOT NULL DEFAULT '', -- X轴位置
|
|
position_y NVARCHAR(30) NOT NULL DEFAULT '', -- Y轴位置
|
|
width NVARCHAR(30) NOT NULL DEFAULT '', -- 宽度
|
|
height NVARCHAR(30) NOT NULL DEFAULT '', -- 高度
|
|
effect TINYINT NOT NULL DEFAULT 0, -- 特效: 0无 1缩放动画
|
|
title NVARCHAR(255) NULL, -- 标题
|
|
image_details NVARCHAR(255) NULL, -- 详情图片URL
|
|
image_bj NVARCHAR(255) NULL, -- 背景图片URL
|
|
image_details_x NVARCHAR(255) NULL, -- 详情图片X偏移
|
|
image_details_y NVARCHAR(255) NULL, -- 详情图片Y偏移
|
|
image_details_w NVARCHAR(255) NULL, -- 详情图片宽度
|
|
image_details_h NVARCHAR(255) NULL, -- 详情图片高度
|
|
created_at DATETIME2 NOT NULL DEFAULT GETDATE(),
|
|
updated_at DATETIME2 NOT NULL DEFAULT GETDATE()
|
|
);
|
|
```
|
|
|
|
### 2. Entity Class: FloatBallConfig
|
|
|
|
```csharp
|
|
namespace HoneyBox.Model.Entities;
|
|
|
|
public class FloatBallConfig
|
|
{
|
|
public int Id { get; set; }
|
|
public byte Status { get; set; }
|
|
public byte Type { get; set; }
|
|
public string Image { get; set; } = string.Empty;
|
|
public string LinkUrl { get; set; } = string.Empty;
|
|
public string PositionX { get; set; } = string.Empty;
|
|
public string PositionY { get; set; } = string.Empty;
|
|
public string Width { get; set; } = string.Empty;
|
|
public string Height { get; set; } = string.Empty;
|
|
public byte Effect { get; set; }
|
|
public string? Title { get; set; }
|
|
public string? ImageDetails { get; set; }
|
|
public string? ImageBj { get; set; }
|
|
public string? ImageDetailsX { get; set; }
|
|
public string? ImageDetailsY { get; set; }
|
|
public string? ImageDetailsW { get; set; }
|
|
public string? ImageDetailsH { get; set; }
|
|
public DateTime CreatedAt { get; set; }
|
|
public DateTime UpdatedAt { get; set; }
|
|
}
|
|
```
|
|
|
|
### 3. Response DTO: FloatBallResponse
|
|
|
|
```csharp
|
|
namespace HoneyBox.Model.Models.FloatBall;
|
|
|
|
public class FloatBallResponse
|
|
{
|
|
public int Id { get; set; }
|
|
public int Type { get; set; }
|
|
public string Image { get; set; } = string.Empty;
|
|
public string LinkUrl { get; set; } = string.Empty;
|
|
public string PositionX { get; set; } = string.Empty;
|
|
public string PositionY { get; set; } = string.Empty;
|
|
public string Width { get; set; } = string.Empty;
|
|
public string Height { get; set; } = string.Empty;
|
|
public int Effect { get; set; }
|
|
public string? Title { get; set; }
|
|
public string? ImageDetails { get; set; }
|
|
public string? ImageBj { get; set; }
|
|
public string? ImageDetailsX { get; set; }
|
|
public string? ImageDetailsY { get; set; }
|
|
public string? ImageDetailsW { get; set; }
|
|
public string? ImageDetailsH { get; set; }
|
|
}
|
|
```
|
|
|
|
### 4. Service Interface: IFloatBallService
|
|
|
|
```csharp
|
|
namespace HoneyBox.Core.Interfaces;
|
|
|
|
public interface IFloatBallService
|
|
{
|
|
Task<List<FloatBallResponse>> GetEnabledFloatBallsAsync();
|
|
}
|
|
```
|
|
|
|
### 5. API Endpoint
|
|
|
|
```
|
|
GET /api/getFloatBall
|
|
Authorization: None (AllowAnonymous)
|
|
Response: ApiResponse<List<FloatBallResponse>>
|
|
```
|
|
|
|
## Data Models
|
|
|
|
### MySQL Source Table Schema (float_ball_config)
|
|
|
|
| Column | Type | Description |
|
|
|--------|------|-------------|
|
|
| id | int(11) | 主键ID |
|
|
| status | tinyint(1) | 状态: 0关闭 1开启 |
|
|
| type | tinyint(1) | 类型: 1展示图片 2跳转页面 |
|
|
| image | varchar(255) | 悬浮球图片URL |
|
|
| link_url | varchar(255) | 跳转链接 |
|
|
| position_x | varchar(30) | X轴位置 (如: -0%, 10px) |
|
|
| position_y | varchar(30) | Y轴位置 (如: 70vh, 21vh) |
|
|
| width | varchar(30) | 宽度 (如: 150rpx, 52rpx) |
|
|
| height | varchar(30) | 高度 (如: 165rpx, 120rpx) |
|
|
| effect | tinyint(1) | 特效: 0无 1缩放动画 |
|
|
| create_time | int(11) | 创建时间 (Unix时间戳) |
|
|
| update_time | int(11) | 更新时间 (Unix时间戳) |
|
|
| title | varchar(255) | 标题 |
|
|
| image_details | varchar(255) | 详情图片URL |
|
|
| image_bj | varchar(255) | 背景图片URL |
|
|
| image_details_x | varchar(255) | 详情图片X偏移 |
|
|
| image_details_y | varchar(255) | 详情图片Y偏移 |
|
|
| image_details_w | varchar(255) | 详情图片宽度 |
|
|
| image_details_h | varchar(255) | 详情图片高度 |
|
|
|
|
### Data Migration Mapping
|
|
|
|
| MySQL Column | SQL Server Column | Transformation |
|
|
|--------------|-------------------|----------------|
|
|
| id | id | 保持原值 (IDENTITY_INSERT ON) |
|
|
| status | status | 直接映射 |
|
|
| type | type | 直接映射 |
|
|
| image | image | 直接映射 |
|
|
| link_url | link_url | 直接映射 |
|
|
| position_x | position_x | 直接映射 |
|
|
| position_y | position_y | 直接映射 |
|
|
| width | width | 直接映射 |
|
|
| height | height | 直接映射 |
|
|
| effect | effect | 直接映射 |
|
|
| title | title | 直接映射 |
|
|
| image_details | image_details | 直接映射 |
|
|
| image_bj | image_bj | 直接映射 |
|
|
| image_details_x | image_details_x | 直接映射 |
|
|
| image_details_y | image_details_y | 直接映射 |
|
|
| image_details_w | image_details_w | 直接映射 |
|
|
| image_details_h | image_details_h | 直接映射 |
|
|
| create_time | created_at | Unix时间戳 → DATETIME2 |
|
|
| update_time | updated_at | Unix时间戳 → DATETIME2 |
|
|
|
|
## 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: Data Migration Record Count Consistency
|
|
|
|
*For any* migration execution, the number of records in SQL Server `float_ball_configs` table after migration SHALL equal the number of records in MySQL `float_ball_config` table.
|
|
|
|
**Validates: Requirements 2.4**
|
|
|
|
### Property 2: Data Migration ID Preservation
|
|
|
|
*For any* record migrated from MySQL to SQL Server, the `id` value in the target table SHALL equal the `id` value in the source table.
|
|
|
|
**Validates: Requirements 2.3**
|
|
|
|
### Property 3: Timestamp Transformation Validity
|
|
|
|
*For any* Unix timestamp value from MySQL, the transformed DATETIME2 value in SQL Server SHALL represent the same point in time.
|
|
|
|
**Validates: Requirements 2.2**
|
|
|
|
### Property 4: API Returns Only Enabled Configurations
|
|
|
|
*For any* GET request to `/api/getFloatBall`, all returned configurations SHALL have status equal to 1 (enabled) in the database.
|
|
|
|
**Validates: Requirements 3.1, 3.2**
|
|
|
|
### Property 5: API Response Field Completeness
|
|
|
|
*For any* configuration returned by the API, the response SHALL contain all required fields (id, type, image, link_url, position_x, position_y, width, height, effect, title, image_details, image_bj, image_details_x, image_details_y, image_details_w, image_details_h) and SHALL NOT contain status, created_at, updated_at fields.
|
|
|
|
**Validates: Requirements 3.3, 3.4**
|
|
|
|
### Property 6: API Response Format Consistency
|
|
|
|
*For any* successful API response, the format SHALL be `{ "status": 1, "msg": "...", "data": [...] }` with status equal to 1.
|
|
|
|
**Validates: Requirements 5.1, 5.2**
|
|
|
|
### Property 7: Image URL Preservation
|
|
|
|
*For any* configuration with image URLs (image, image_details, image_bj), the API response SHALL return the URLs unchanged from the database values.
|
|
|
|
**Validates: Requirements 5.4**
|
|
|
|
### Property 8: Incremental Migration Idempotence
|
|
|
|
*For any* migration script execution, running the migration twice SHALL result in the same final state (no duplicate records).
|
|
|
|
**Validates: Requirements 2.5**
|
|
|
|
## Error Handling
|
|
|
|
### Migration Script Errors
|
|
|
|
1. **Connection Failure**: Log error and exit with non-zero code
|
|
2. **Single Record Insert Failure**: Log error, continue with remaining records
|
|
3. **Batch Insert Failure**: Fall back to single record inserts
|
|
|
|
### API Errors
|
|
|
|
1. **Database Connection Error**: Return `{ "status": 0, "msg": "获取悬浮球配置失败", "data": null }`
|
|
2. **Unexpected Exception**: Log error, return generic error message
|
|
|
|
## Testing Strategy
|
|
|
|
### Unit Tests
|
|
|
|
- Test FloatBallService.GetEnabledFloatBallsAsync() returns only enabled configs
|
|
- Test response DTO mapping excludes status, created_at, updated_at
|
|
- Test empty result when no enabled configs exist
|
|
|
|
### Property-Based Tests
|
|
|
|
使用 xUnit + FsCheck 进行属性测试:
|
|
|
|
1. **Property 1**: 验证迁移后记录数一致性
|
|
2. **Property 4**: 验证 API 只返回启用的配置
|
|
3. **Property 8**: 验证迁移脚本幂等性
|
|
|
|
### Integration Tests
|
|
|
|
- Test full API endpoint `/api/getFloatBall` returns correct format
|
|
- Test migration script with test database
|
|
|
|
### Test Configuration
|
|
|
|
- Property tests: 最少 100 次迭代
|
|
- 使用 FsCheck 生成随机测试数据
|
|
- 标签格式: **Feature: float-ball-migration, Property {number}: {property_text}**
|