HaniBlindBox/.kiro/specs/admin-bugfix/design.md
2026-01-20 20:31:51 +08:00

339 lines
11 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
本设计文档描述后台管理系统 9 个未修复 BUG 的技术修复方案。BUG 分布在统计报表、商品管理、营销活动和内容管理四个模块,主要涉及后端接口修复和少量前端调整。
## Architecture
### 受影响模块架构
```
┌─────────────────────────────────────────────────────────────────┐
│ 前端 (Vue 3 + Element Plus) │
├─────────────────────────────────────────────────────────────────┤
│ views/business/ │
│ ├── statistics/ # 统计报表 (cs100_2, cs100_3) │
│ ├── goods/ # 商品管理 (cs100_4, cs100_5, cs100_6) │
│ ├── marketing/ # 营销活动 (cs100_11, cs100_13, cs100_14) │
│ └── danye/ # 内容管理 (cs100_15) │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 后端 (ASP.NET Core) │
├─────────────────────────────────────────────────────────────────┤
│ HoneyBox.Admin.Business/ │
│ ├── Controllers/ │
│ │ ├── StatisticsController.cs # 统计报表接口 │
│ │ ├── GoodsController.cs # 商品管理接口 │
│ │ ├── MarketingController.cs # 营销活动接口 │
│ │ └── DanyeController.cs # 单页管理接口 │
│ └── Services/ │
│ ├── StatisticsService.cs │
│ ├── GoodsService.cs │
│ ├── MarketingService.cs │
│ └── DanyeService.cs │
└─────────────────────────────────────────────────────────────────┘
```
## Bug Analysis & Solutions
### 1. 统计报表模块 (cs100_2, cs100_3)
#### 问题分析
- 用户盈亏统计和用户邀请统计按用户ID搜索时返回"请求失败"
- 可能原因:
1. 用户ID参数类型不匹配前端传string后端期望int
2. 查询条件构建错误
3. 空值处理异常
#### 修复方案
```csharp
// StatisticsService.cs
public async Task<PagedResult<UserProfitStatsResponse>> GetUserProfitStatsAsync(
UserProfitStatsRequest request)
{
var query = _dbContext.UserProfitStats.AsQueryable();
// 修复正确处理用户ID搜索
if (!string.IsNullOrEmpty(request.UserId))
{
if (int.TryParse(request.UserId, out var userId))
{
query = query.Where(x => x.UserId == userId);
}
}
// ... 分页逻辑
}
```
### 2. 商品管理模块 - 盒子类型搜索 (cs100_4)
#### 问题分析
- 盒子类型为"全部"时搜索无结果
- 可能原因:
1. "全部"选项传递了错误的值如0被当作有效类型过滤
2. 后端未正确处理"全部"情况
#### 修复方案
```csharp
// GoodsService.cs
public async Task<PagedResult<BoxResponse>> GetBoxListAsync(BoxListRequest request)
{
var query = _dbContext.Boxes.AsQueryable();
// 修复当类型为0或null时不添加类型过滤条件
if (request.Type.HasValue && request.Type.Value > 0)
{
query = query.Where(x => x.Type == request.Type.Value);
}
// ... 其他过滤和分页逻辑
}
```
### 3. 商品管理模块 - 自动下架配置 (cs100_5)
#### 问题分析
- 开启"自动下架配置"后无法设置参数
- 可能原因:
1. 前端表单联动逻辑问题
2. 后端未返回自动下架相关字段
3. 保存接口未处理这些字段
#### 修复方案
**前端修复:**
```vue
<!-- GoodsFormDialog.vue -->
<template>
<el-form-item label="自动下架配置">
<el-switch v-model="form.autoDelistEnabled" />
</el-form-item>
<!-- 修复:确保联动显示 -->
<template v-if="form.autoDelistEnabled">
<el-form-item label="下架时间">
<el-date-picker v-model="form.autoDelistTime" type="datetime" />
</el-form-item>
<el-form-item label="下架条件">
<el-input v-model="form.autoDelistCondition" />
</el-form-item>
</template>
</template>
```
**后端修复:**
```csharp
// BoxResponse.cs - 确保返回自动下架字段
public class BoxResponse
{
// ... 其他字段
public bool AutoDelistEnabled { get; set; }
public DateTime? AutoDelistTime { get; set; }
public string? AutoDelistCondition { get; set; }
}
```
### 4. 商品管理模块 - 奖品等级分类显示 (cs100_6)
#### 问题分析
- 奖品等级显示"0级",分类显示"未知"
- 可能原因:
1. 未进行关联查询获取等级和分类名称
2. DTO映射时字段未正确赋值
#### 修复方案
```csharp
// GoodsService.cs
public async Task<PagedResult<PrizeResponse>> GetPrizeListAsync(PrizeListRequest request)
{
var query = from p in _dbContext.Prizes
join l in _dbContext.PrizeLevels on p.LevelId equals l.Id into levels
from level in levels.DefaultIfEmpty()
join c in _dbContext.PrizeCategories on p.CategoryId equals c.Id into categories
from category in categories.DefaultIfEmpty()
select new PrizeResponse
{
Id = p.Id,
Name = p.Name,
LevelId = p.LevelId,
LevelName = level != null ? level.Name : "未设置", // 修复
CategoryId = p.CategoryId,
CategoryName = category != null ? category.Name : "未设置", // 修复
// ... 其他字段
};
// ... 分页逻辑
}
```
### 5. 营销活动模块 - 领取记录搜索 (cs100_11)
#### 问题分析
- 按用户ID搜索领取记录时返回"请求失败"
- 与统计报表模块问题类似
#### 修复方案
```csharp
// MarketingService.cs
public async Task<PagedResult<ClaimRecordResponse>> GetClaimRecordsAsync(
ClaimRecordRequest request)
{
var query = _dbContext.ClaimRecords.AsQueryable();
// 修复正确处理用户ID搜索
if (!string.IsNullOrEmpty(request.UserId))
{
if (int.TryParse(request.UserId, out var userId))
{
query = query.Where(x => x.UserId == userId);
}
}
// ... 分页逻辑
}
```
### 6. 营销活动模块 - 周榜/月榜记录 (cs100_13, cs100_14)
#### 问题分析
- 访问周榜/月榜页面时返回"服务器内部错误"
- 可能原因:
1. 日期范围计算错误
2. 数据聚合查询异常
3. 空数据处理异常
#### 修复方案
```csharp
// MarketingService.cs
public async Task<List<RankRecordResponse>> GetWeeklyRankAsync(RankRequest request)
{
try
{
// 修复:正确计算周起止日期
var startOfWeek = GetStartOfWeek(request.Date ?? DateTime.Now);
var endOfWeek = startOfWeek.AddDays(7);
var query = _dbContext.RankRecords
.Where(x => x.RecordDate >= startOfWeek && x.RecordDate < endOfWeek)
.OrderByDescending(x => x.Score);
// 修复:处理空数据情况
var result = await query.ToListAsync();
return result ?? new List<RankRecordResponse>();
}
catch (Exception ex)
{
_logger.LogError(ex, "获取周榜数据失败");
throw new BusinessException("获取周榜数据失败,请稍后重试");
}
}
private DateTime GetStartOfWeek(DateTime date)
{
var diff = (7 + (date.DayOfWeek - DayOfWeek.Monday)) % 7;
return date.AddDays(-diff).Date;
}
```
### 7. 内容管理模块 - 单页文章显示 (cs100_15)
#### 问题分析
- 文章内容显示原始HTML代码而非渲染内容
- 原因:前端使用 `{{ content }}` 而非 `v-html`
#### 修复方案
```vue
<!-- DanyeFormDialog.vue 或详情组件 -->
<template>
<!-- 修复前 -->
<!-- <div>{{ article.content }}</div> -->
<!-- 修复后使用 v-html 渲染 -->
<div class="article-content" v-html="sanitizedContent"></div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import DOMPurify from 'dompurify'
const props = defineProps<{
article: { content: string }
}>()
// 安全处理HTML内容
const sanitizedContent = computed(() => {
return DOMPurify.sanitize(props.article.content)
})
</script>
<style scoped>
.article-content {
/* 确保样式正确渲染 */
line-height: 1.6;
}
.article-content img {
max-width: 100%;
}
</style>
```
## API Changes
### 统计报表 API 修复
| 方法 | 路径 | 修复内容 |
|------|------|----------|
| GET | /api/business/statistics/user-profit | 修复用户ID参数处理 |
| GET | /api/business/statistics/user-invite | 修复用户ID参数处理 |
### 商品管理 API 修复
| 方法 | 路径 | 修复内容 |
|------|------|----------|
| GET | /api/business/goods/boxes | 修复类型"全部"过滤逻辑 |
| GET | /api/business/goods/boxes/{id} | 添加自动下架字段返回 |
| PUT | /api/business/goods/boxes/{id} | 处理自动下架字段保存 |
| GET | /api/business/goods/prizes | 修复等级/分类关联查询 |
### 营销活动 API 修复
| 方法 | 路径 | 修复内容 |
|------|------|----------|
| GET | /api/business/marketing/claim-records | 修复用户ID参数处理 |
| GET | /api/business/marketing/weekly-rank | 修复日期计算和异常处理 |
| GET | /api/business/marketing/monthly-rank | 修复日期计算和异常处理 |
## Testing Strategy
### 单元测试
- 测试用户ID参数解析逻辑
- 测试类型过滤条件构建
- 测试日期范围计算
- 测试关联查询结果映射
### 集成测试
- 测试各搜索接口正常返回
- 测试空数据情况处理
- 测试边界条件无效ID、特殊日期等
### 前端测试
- 测试表单联动显示
- 测试HTML内容渲染
- 测试XSS防护
## Security Considerations
1. **XSS防护**: 单页文章内容使用 DOMPurify 进行净化
2. **参数验证**: 所有搜索参数进行类型验证
3. **异常处理**: 统一异常处理,不暴露内部错误信息
## References
- BUG汇总清单: `docs/后台管理bug整理/BUG汇总清单.md`
- 各BUG详细文档: `docs/后台管理bug整理/BUG-*.md`