diff --git a/.kiro/specs/designated-prize-winner/design.md b/.kiro/specs/designated-prize-winner/design.md
new file mode 100644
index 00000000..918b3dec
--- /dev/null
+++ b/.kiro/specs/designated-prize-winner/design.md
@@ -0,0 +1,354 @@
+# Design Document: 指定用户中奖功能
+
+## Overview
+
+本设计文档描述了"指定用户中奖"功能的技术实现方案。该功能允许后台管理员为盒子中的特定奖品指定中奖用户,使得该奖品只能被指定用户抽中(无限赏)或优先被指定用户抽中(有限赏带兜底)。
+
+核心设计原则:
+- 不修改奖品本身的概率配置
+- 有限赏保证"每抽必中"机制(兜底)
+- 无限赏严格保护指定奖品
+- 最小化对现有抽奖流程的侵入
+
+## Architecture
+
+```mermaid
+graph TB
+ subgraph "后台管理层"
+ AdminAPI[后台管理 API]
+ DesignatedPrizeService[DesignatedPrizeService]
+ end
+
+ subgraph "抽奖核心层"
+ LotteryEngine[LotteryEngine]
+ InventoryManager[InventoryManager]
+ PrizePoolFilter[奖品池过滤器]
+ end
+
+ subgraph "数据层"
+ DbContext[HoneyBoxDbContext]
+ DesignatedPrizeEntity[GoodsDesignatedPrize]
+ GoodsItemEntity[GoodsItem]
+ end
+
+ AdminAPI --> DesignatedPrizeService
+ DesignatedPrizeService --> DbContext
+
+ LotteryEngine --> PrizePoolFilter
+ LotteryEngine --> InventoryManager
+ PrizePoolFilter --> DbContext
+
+ DbContext --> DesignatedPrizeEntity
+ DbContext --> GoodsItemEntity
+```
+
+## Components and Interfaces
+
+### 1. 数据实体:GoodsDesignatedPrize
+
+```csharp
+namespace HoneyBox.Model.Entities;
+
+///
+/// 指定中奖配置实体
+///
+public class GoodsDesignatedPrize
+{
+ public int Id { get; set; }
+ public int GoodsId { get; set; }
+ public int GoodsItemId { get; set; }
+ public int UserId { get; set; }
+ public bool IsActive { get; set; } = true;
+ public string? Remark { get; set; }
+ public DateTime CreatedAt { get; set; }
+ public DateTime? UpdatedAt { get; set; }
+
+ // 导航属性
+ public virtual Good? Goods { get; set; }
+ public virtual GoodsItem? GoodsItem { get; set; }
+ public virtual User? User { get; set; }
+}
+```
+
+### 2. 抽奖引擎接口扩展:ILotteryEngine
+
+```csharp
+public interface ILotteryEngine
+{
+ // 现有方法保持不变
+ Task DrawAsync(LotteryDrawRequest request);
+ Task DrawInfiniteAsync(LotteryDrawRequest request);
+
+ // 内部使用,不暴露新接口
+}
+```
+
+### 3. 指定中奖服务接口:IDesignatedPrizeService
+
+```csharp
+namespace HoneyBox.Admin.Business.Services.Interfaces;
+
+public interface IDesignatedPrizeService
+{
+ Task> GetByGoodsIdAsync(int goodsId);
+ Task CreateAsync(CreateDesignatedPrizeRequest request);
+ Task UpdateAsync(int id, UpdateDesignatedPrizeRequest request);
+ Task DeleteAsync(int id);
+}
+```
+
+### 4. 后台管理 API 控制器
+
+```csharp
+[ApiController]
+[Route("api/admin/goods/{goodsId}/designated-prizes")]
+public class DesignatedPrizeController : BusinessControllerBase
+{
+ [HttpGet]
+ public Task>> GetList(int goodsId);
+
+ [HttpPost]
+ public Task> Create(int goodsId, CreateDesignatedPrizeRequest request);
+
+ [HttpPut("{id}")]
+ public Task> Update(int goodsId, int id, UpdateDesignatedPrizeRequest request);
+
+ [HttpDelete("{id}")]
+ public Task Delete(int goodsId, int id);
+}
+```
+
+## Data Models
+
+### 数据库表设计
+
+```sql
+CREATE TABLE goods_designated_prizes (
+ id INT PRIMARY KEY IDENTITY(1,1),
+ goods_id INT NOT NULL,
+ goods_item_id INT NOT NULL,
+ user_id INT NOT NULL,
+ is_active BIT NOT NULL DEFAULT 1,
+ remark NVARCHAR(200),
+ created_at DATETIME2 NOT NULL DEFAULT GETDATE(),
+ updated_at DATETIME2,
+
+ INDEX IX_designated_goods_id (goods_id),
+ INDEX IX_designated_user_id (user_id),
+ INDEX IX_designated_goods_item (goods_item_id),
+ CONSTRAINT UQ_goods_item_user UNIQUE (goods_id, goods_item_id)
+);
+```
+
+### DTO 模型
+
+```csharp
+// 查询响应
+public class DesignatedPrizeDto
+{
+ public int Id { get; set; }
+ public int GoodsId { get; set; }
+ public int GoodsItemId { get; set; }
+ public string? GoodsItemTitle { get; set; }
+ public string? GoodsItemImgUrl { get; set; }
+ public int UserId { get; set; }
+ public string? UserNickname { get; set; }
+ public string? UserPhone { get; set; }
+ public bool IsActive { get; set; }
+ public string? Remark { get; set; }
+ public DateTime CreatedAt { get; set; }
+}
+
+// 创建请求
+public class CreateDesignatedPrizeRequest
+{
+ public int GoodsItemId { get; set; }
+ public int UserId { get; set; }
+ public string? Remark { get; set; }
+}
+
+// 更新请求
+public class UpdateDesignatedPrizeRequest
+{
+ public int? UserId { get; set; }
+ public bool? IsActive { get; set; }
+ public string? Remark { get; set; }
+}
+```
+
+### 抽奖引擎内部数据结构
+
+```csharp
+// 指定中奖配置缓存结构
+// Key: GoodsItemId, Value: UserId
+private Dictionary _designatedPrizes;
+```
+
+## 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: Unique Constraint Enforcement
+*For any* goods and goods_item combination, attempting to create a second designated prize configuration SHALL result in an error, ensuring only one user can be designated per prize.
+**Validates: Requirements 1.2, 4.5**
+
+### Property 2: Active Configuration Filtering
+*For any* query to get designated prize configurations, the result SHALL only contain configurations where is_active is true, regardless of how many inactive configurations exist.
+**Validates: Requirements 1.3**
+
+### Property 3: Designated User Prize Pool Inclusion
+*For any* designated user drawing from either finite or infinite lottery, their prize pool SHALL include all their designated prizes (where they are the designated user and is_active is true).
+**Validates: Requirements 2.3, 3.4**
+
+### Property 4: Non-Designated User Prize Pool Exclusion (Finite Lottery)
+*For any* non-designated user drawing from a finite lottery with normal prizes available, their prize pool SHALL NOT contain any designated prizes.
+**Validates: Requirements 2.4**
+
+### Property 5: Non-Designated User Prize Pool Exclusion (Infinite Lottery - Strict)
+*For any* non-designated user drawing from an infinite lottery, their prize pool SHALL NEVER contain designated prizes, even when no normal prizes exist.
+**Validates: Requirements 3.3, 3.5**
+
+### Property 6: Finite Lottery Fallback Mechanism
+*For any* finite lottery where only designated prizes remain (normal prize pool is empty), a non-designated user SHALL be able to draw from all remaining prizes (fallback mechanism).
+**Validates: Requirements 2.5**
+
+### Property 7: Probability Calculation Invariance
+*For any* prize pool (filtered or unfiltered), the probability calculation method SHALL remain unchanged - probabilities are calculated based on stock (finite) or real_pro (infinite) of the filtered pool, and the sum of probabilities SHALL equal 100%.
+**Validates: Requirements 5.1, 5.3**
+
+### Property 8: Prize Data Immutability
+*For any* designated prize configuration operation (create, update, delete), the underlying prize's stock, real_pro, and other probability-related fields SHALL remain unchanged.
+**Validates: Requirements 5.2**
+
+### Property 9: Admin CRUD Validation
+*For any* admin create operation, the system SHALL validate that goods_id, goods_item_id, and user_id all reference existing records; invalid references SHALL result in an error.
+**Validates: Requirements 4.1**
+
+## Error Handling
+
+### 抽奖引擎错误处理
+
+| 场景 | 处理方式 | 日志级别 |
+|------|----------|----------|
+| 指定中奖配置查询失败 | 降级为无配置模式,继续抽奖 | Warning |
+| 有限赏兜底机制触发 | 记录日志,允许抽奖继续 | Warning |
+| 无限赏奖品池为空(全是指定奖品) | 返回"暂无可抽奖品"错误 | Warning |
+| 数据库连接异常 | 返回"系统繁忙"错误 | Error |
+
+### 后台管理 API 错误处理
+
+| 场景 | HTTP 状态码 | 错误消息 |
+|------|-------------|----------|
+| 盒子不存在 | 404 | "盒子不存在" |
+| 奖品不存在 | 404 | "奖品不存在" |
+| 用户不存在 | 404 | "用户不存在" |
+| 重复配置 | 400 | "该奖品已配置指定用户" |
+| 配置不存在 | 404 | "配置不存在" |
+| 权限不足 | 403 | "无权限操作" |
+
+### 错误处理代码示例
+
+```csharp
+// 抽奖引擎中的降级处理
+private async Task> GetDesignatedPrizesAsync(int goodsId)
+{
+ try
+ {
+ return await _dbContext.GoodsDesignatedPrizes
+ .Where(dp => dp.GoodsId == goodsId && dp.IsActive)
+ .ToDictionaryAsync(dp => dp.GoodsItemId, dp => dp.UserId);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogWarning(ex, "Failed to query designated prizes for goods {GoodsId}, falling back to no configuration", goodsId);
+ return new Dictionary();
+ }
+}
+```
+
+## Testing Strategy
+
+### 测试框架选择
+
+- **单元测试框架**: xUnit
+- **属性测试框架**: FsCheck (C# 属性测试库)
+- **Mock 框架**: Moq
+- **集成测试**: Microsoft.AspNetCore.Mvc.Testing
+
+### 单元测试覆盖
+
+1. **GoodsDesignatedPrize 实体测试**
+ - 字段默认值验证
+ - 导航属性关联
+
+2. **DesignatedPrizeService 测试**
+ - CRUD 操作正确性
+ - 验证逻辑(存在性检查)
+ - 唯一约束处理
+
+3. **LotteryEngine 奖品池过滤测试**
+ - 有限赏过滤逻辑(带兜底)
+ - 无限赏过滤逻辑(严格)
+ - 边界情况(空池、全指定等)
+
+### 属性测试配置
+
+每个属性测试运行 **100 次迭代**,使用 FsCheck 生成随机测试数据。
+
+```csharp
+// 属性测试示例配置
+[Property(MaxTest = 100)]
+public Property DesignatedUserSeesTheirPrizes()
+{
+ // Feature: designated-prize-winner, Property 3: Designated User Prize Pool Inclusion
+ return Prop.ForAll(
+ Arb.From(), // userId
+ Arb.From>(), // prizePool
+ Arb.From>(), // designatedPrizes
+ (userId, prizePool, designatedPrizes) =>
+ {
+ // Test implementation
+ });
+}
+```
+
+### 测试数据生成策略
+
+```csharp
+// 奖品池生成器
+public static Arbitrary> GoodsItemListArbitrary()
+{
+ return Gen.ListOf(Gen.Fresh(() => new GoodsItem
+ {
+ Id = Gen.Choose(1, 1000).Sample(0, 1).First(),
+ SurplusStock = Gen.Choose(0, 100).Sample(0, 1).First(),
+ RealPro = Gen.Choose(0, 100).Sample(0, 1).First()
+ })).ToArbitrary();
+}
+
+// 指定中奖配置生成器
+public static Arbitrary> DesignatedPrizesArbitrary()
+{
+ return Gen.DictionaryOf(
+ Gen.Choose(1, 1000), // GoodsItemId
+ Gen.Choose(1, 10000) // UserId
+ ).ToArbitrary();
+}
+```
+
+### 集成测试场景
+
+1. **有限赏完整流程测试**
+ - 指定用户抽中指定奖品
+ - 普通用户抽不到指定奖品
+ - 兜底机制触发场景
+
+2. **无限赏完整流程测试**
+ - 指定用户抽中指定奖品
+ - 普通用户永远抽不到指定奖品
+
+3. **后台管理 API 测试**
+ - 完整 CRUD 流程
+ - 并发创建重复配置
+ - 权限验证
+
diff --git a/.kiro/specs/designated-prize-winner/requirements.md b/.kiro/specs/designated-prize-winner/requirements.md
new file mode 100644
index 00000000..ef22435d
--- /dev/null
+++ b/.kiro/specs/designated-prize-winner/requirements.md
@@ -0,0 +1,76 @@
+# Requirements Document
+
+## Introduction
+
+指定用户中奖功能允许后台管理员为每个盒子配置"指定用户中奖"规则,使某个奖品只能由指定用户抽中。该功能不修改奖品本身的概率,指定用户仍需按概率抽奖,但非指定用户无法抽中该奖品。
+
+## Glossary
+
+- **Goods**: 盒子/商品,包含多个奖品的抽奖容器
+- **GoodsItem**: 奖品,盒子中的单个可抽取物品
+- **DesignatedPrize**: 指定中奖配置,将特定奖品指定给特定用户
+- **LotteryEngine**: 抽奖引擎,负责执行抽奖逻辑的核心服务
+- **FiniteLottery**: 有限赏抽奖,基于库存概率的抽奖模式(一番赏、福袋等),抽完即止
+- **InfiniteLottery**: 无限赏抽奖,基于固定概率的抽奖模式(无限赏、领主赏等),无限池
+- **PrizePool**: 奖品池,当前可抽取的奖品集合
+- **FallbackMechanism**: 兜底机制,当普通奖品池为空时允许普通用户抽取指定奖品
+
+## Requirements
+
+### Requirement 1: 指定中奖配置数据管理
+
+**User Story:** As a 后台管理员, I want to 为盒子中的奖品配置指定中奖用户, so that 特定奖品只能被指定用户抽中。
+
+#### Acceptance Criteria
+
+1. THE GoodsDesignatedPrize Entity SHALL store goods_id, goods_item_id, user_id, is_active, remark, created_at, and updated_at fields
+2. WHEN a designated prize configuration is created, THE System SHALL enforce that one prize can only be designated to one user per goods (unique constraint on goods_id + goods_item_id)
+3. WHEN a designated prize configuration is queried, THE System SHALL only return active configurations (is_active = true)
+4. THE System SHALL support enabling and disabling designated prize configurations via the is_active field
+
+### Requirement 2: 有限赏抽奖流程改造(带兜底机制)
+
+**User Story:** As a 用户, I want to 在有限赏抽奖时遵循指定中奖规则, so that 指定奖品优先给指定用户,但保证每抽必中。
+
+#### Acceptance Criteria
+
+1. WHEN a user draws from a finite lottery, THE LotteryEngine SHALL query designated prize configurations for the goods
+2. WHEN designated prize configurations exist, THE LotteryEngine SHALL separate the prize pool into normal prizes and designated prizes
+3. WHEN the current user is a designated user for any prize, THE LotteryEngine SHALL include that user's designated prizes in their prize pool
+4. WHEN the current user is not a designated user, THE LotteryEngine SHALL exclude designated prizes from their prize pool
+5. IF the normal prize pool is empty (only designated prizes remain), THEN THE LotteryEngine SHALL allow the user to draw from all prizes (fallback mechanism)
+6. WHEN the fallback mechanism is triggered, THE LotteryEngine SHALL log a warning for operational tracking
+
+### Requirement 3: 无限赏抽奖流程改造(严格过滤)
+
+**User Story:** As a 用户, I want to 在无限赏抽奖时遵循指定中奖规则, so that 指定奖品只能被指定用户抽中。
+
+#### Acceptance Criteria
+
+1. WHEN a user draws from an infinite lottery, THE LotteryEngine SHALL query designated prize configurations for the goods
+2. WHEN designated prize configurations exist, THE LotteryEngine SHALL strictly filter the prize pool
+3. WHEN a prize has a designated user configuration and the current user is not the designated user, THE LotteryEngine SHALL remove that prize from the pool
+4. WHEN a prize has a designated user configuration and the current user is the designated user, THE LotteryEngine SHALL keep that prize in the pool
+5. THE InfiniteLottery SHALL NOT have a fallback mechanism (designated prizes are strictly protected)
+
+### Requirement 4: 后台管理 API
+
+**User Story:** As a 后台管理员, I want to 通过 API 管理指定中奖配置, so that 我可以灵活配置和调整指定中奖规则。
+
+#### Acceptance Criteria
+
+1. WHEN an admin creates a designated prize configuration, THE System SHALL validate that the goods_id, goods_item_id, and user_id exist
+2. WHEN an admin queries designated prize configurations for a goods, THE System SHALL return all configurations with user information
+3. WHEN an admin updates a designated prize configuration, THE System SHALL update the is_active, user_id, or remark fields
+4. WHEN an admin deletes a designated prize configuration, THE System SHALL remove the configuration from the database
+5. IF a duplicate configuration is attempted (same goods_id and goods_item_id), THEN THE System SHALL return an error message
+
+### Requirement 5: 概率保持不变
+
+**User Story:** As a 产品经理, I want to 确保指定中奖不改变奖品概率, so that 抽奖公平性得到保证。
+
+#### Acceptance Criteria
+
+1. WHEN calculating prize probabilities, THE LotteryEngine SHALL use the original probability calculation method
+2. THE DesignatedPrize configuration SHALL NOT modify the prize's stock, real_pro, or any probability-related fields
+3. WHEN a designated user draws, THE LotteryEngine SHALL calculate probabilities based on the filtered prize pool
diff --git a/.kiro/specs/designated-prize-winner/tasks.md b/.kiro/specs/designated-prize-winner/tasks.md
new file mode 100644
index 00000000..9179f850
--- /dev/null
+++ b/.kiro/specs/designated-prize-winner/tasks.md
@@ -0,0 +1,151 @@
+# Implementation Plan: 指定用户中奖功能
+
+## Overview
+
+本实现计划将"指定用户中奖"功能分解为可执行的编码任务。实现顺序为:数据层 → 抽奖核心层 → 后台管理层,确保每个步骤都能独立验证。
+
+## Tasks
+
+- [-] 1. 数据层实现
+ - [ ] 1.1 创建 GoodsDesignatedPrize 实体类
+ - 在 `HoneyBox.Model/Entities/` 目录创建 `GoodsDesignatedPrize.cs`
+ - 包含 Id, GoodsId, GoodsItemId, UserId, IsActive, Remark, CreatedAt, UpdatedAt 字段
+ - 添加导航属性 Goods, GoodsItem, User
+ - _Requirements: 1.1_
+
+ - [ ] 1.2 更新 HoneyBoxDbContext
+ - 添加 `DbSet GoodsDesignatedPrizes` 属性
+ - 在 `OnModelCreating` 中配置实体映射
+ - 配置唯一约束 (goods_id, goods_item_id)
+ - 配置索引 (goods_id, user_id, goods_item_id)
+ - _Requirements: 1.1, 1.2_
+
+ - [ ] 1.3 创建数据库迁移 SQL 脚本
+ - 在 `server/HoneyBox/scripts/` 目录创建 `create_goods_designated_prizes.sql`
+ - 包含建表语句、索引、唯一约束
+ - _Requirements: 1.1, 1.2_
+
+- [ ] 2. 抽奖引擎核心改造
+ - [ ] 2.1 添加指定中奖配置查询方法
+ - 在 `LotteryEngine.cs` 中添加 `GetDesignatedPrizesAsync(int goodsId)` 私有方法
+ - 返回 `Dictionary` (GoodsItemId → UserId)
+ - 只查询 is_active = true 的配置
+ - 添加异常降级处理(查询失败返回空字典)
+ - _Requirements: 2.1, 3.1, 1.3_
+
+ - [ ] 2.2 实现有限赏奖品池过滤方法(带兜底)
+ - 添加 `FilterPrizePoolWithFallback(prizePool, userId, designatedPrizes)` 私有方法
+ - 分离普通奖品和指定奖品
+ - 指定用户:返回普通奖品 + 自己的指定奖品
+ - 普通用户:优先返回普通奖品池
+ - 兜底:普通奖品池为空时返回全部奖品池
+ - 兜底触发时记录 Warning 日志
+ - _Requirements: 2.2, 2.3, 2.4, 2.5, 2.6_
+
+ - [ ] 2.3 编写有限赏过滤方法的属性测试
+ - **Property 3: Designated User Prize Pool Inclusion**
+ - **Property 4: Non-Designated User Prize Pool Exclusion (Finite)**
+ - **Property 6: Finite Lottery Fallback Mechanism**
+ - **Validates: Requirements 2.3, 2.4, 2.5**
+
+ - [ ] 2.4 实现无限赏奖品池过滤方法(严格)
+ - 添加 `FilterPrizePoolStrict(prizePool, userId, designatedPrizes)` 私有方法
+ - 移除所有非当前用户的指定奖品
+ - 保留当前用户的指定奖品
+ - 无兜底机制
+ - _Requirements: 3.2, 3.3, 3.4, 3.5_
+
+ - [ ] 2.5 编写无限赏过滤方法的属性测试
+ - **Property 5: Non-Designated User Prize Pool Exclusion (Infinite - Strict)**
+ - **Validates: Requirements 3.3, 3.5**
+
+ - [ ] 2.6 改造 DrawAsync 方法(有限赏)
+ - 在获取奖品池后调用 `GetDesignatedPrizesAsync`
+ - 如果有配置,调用 `FilterPrizePoolWithFallback` 过滤奖品池
+ - 保持后续概率计算和抽奖逻辑不变
+ - _Requirements: 2.1, 2.2, 5.1, 5.3_
+
+ - [ ] 2.7 改造 DrawInfiniteAsync 方法(无限赏)
+ - 在获取奖品池后调用 `GetDesignatedPrizesAsync`
+ - 如果有配置,调用 `FilterPrizePoolStrict` 过滤奖品池
+ - 保持后续概率计算和抽奖逻辑不变
+ - _Requirements: 3.1, 3.2, 5.1, 5.3_
+
+ - [ ] 2.8 编写概率计算不变性属性测试
+ - **Property 7: Probability Calculation Invariance**
+ - **Validates: Requirements 5.1, 5.3**
+
+- [ ] 3. Checkpoint - 核心功能验证
+ - 确保所有测试通过,如有问题请询问用户
+
+- [ ] 4. 后台管理服务层实现
+ - [ ] 4.1 创建 DTO 模型
+ - 在 `HoneyBox.Admin.Business/Models/DesignatedPrize/` 目录创建:
+ - `DesignatedPrizeDto.cs` - 查询响应
+ - `CreateDesignatedPrizeRequest.cs` - 创建请求
+ - `UpdateDesignatedPrizeRequest.cs` - 更新请求
+ - _Requirements: 4.2_
+
+ - [ ] 4.2 创建 IDesignatedPrizeService 接口
+ - 在 `HoneyBox.Admin.Business/Services/Interfaces/` 目录创建接口
+ - 定义 GetByGoodsIdAsync, CreateAsync, UpdateAsync, DeleteAsync 方法
+ - _Requirements: 4.1, 4.2, 4.3, 4.4_
+
+ - [ ] 4.3 实现 DesignatedPrizeService 服务
+ - 在 `HoneyBox.Admin.Business/Services/` 目录创建实现类
+ - 实现 GetByGoodsIdAsync:查询配置列表,关联用户和奖品信息
+ - 实现 CreateAsync:验证存在性,检查唯一约束,创建配置
+ - 实现 UpdateAsync:更新 is_active, user_id, remark 字段
+ - 实现 DeleteAsync:删除配置
+ - _Requirements: 4.1, 4.2, 4.3, 4.4, 4.5_
+
+ - [ ] 4.4 编写服务层单元测试
+ - 测试 CRUD 操作正确性
+ - 测试验证逻辑(存在性检查)
+ - 测试唯一约束处理
+ - _Requirements: 4.1, 4.5_
+
+ - [ ] 4.5 编写唯一约束属性测试
+ - **Property 1: Unique Constraint Enforcement**
+ - **Validates: Requirements 1.2, 4.5**
+
+- [ ] 5. 后台管理 API 层实现
+ - [ ] 5.1 创建 DesignatedPrizeController 控制器
+ - 在 `HoneyBox.Admin.Business/Controllers/` 目录创建控制器
+ - 路由:`api/admin/goods/{goodsId}/designated-prizes`
+ - 实现 GET(列表)、POST(创建)、PUT(更新)、DELETE(删除)端点
+ - 添加权限验证
+ - _Requirements: 4.1, 4.2, 4.3, 4.4_
+
+ - [ ] 5.2 注册服务到依赖注入容器
+ - 在 `ServiceCollectionExtensions.cs` 中注册 IDesignatedPrizeService
+ - _Requirements: 4.1_
+
+ - [ ] 5.3 编写 API 集成测试
+ - 测试完整 CRUD 流程
+ - 测试错误响应(404, 400)
+ - _Requirements: 4.1, 4.2, 4.3, 4.4, 4.5_
+
+- [ ] 6. Checkpoint - 后台管理功能验证
+ - 确保所有测试通过,如有问题请询问用户
+
+- [ ] 7. 集成测试和文档
+ - [ ] 7.1 编写端到端集成测试
+ - 有限赏完整流程:配置指定中奖 → 指定用户抽奖 → 验证结果
+ - 无限赏完整流程:配置指定中奖 → 普通用户抽奖 → 验证无法抽中
+ - 兜底机制测试:只剩指定奖品时普通用户抽奖
+ - _Requirements: 2.3, 2.4, 2.5, 3.3, 3.4, 3.5_
+
+ - [ ] 7.2 编写奖品数据不可变性属性测试
+ - **Property 8: Prize Data Immutability**
+ - **Validates: Requirements 5.2**
+
+- [ ] 8. Final Checkpoint - 完整功能验证
+ - 确保所有测试通过,如有问题请询问用户
+
+## Notes
+
+- 每个任务都引用了具体的需求条款以确保可追溯性
+- 检查点用于增量验证,确保每个阶段的正确性
+- 属性测试验证通用正确性属性,单元测试验证具体示例和边界情况
+- 所有测试任务均为必需,确保全面的测试覆盖