HaniBlindBox/.kiro/specs/content-auxiliary-frontend/design.md
2026-01-18 11:18:09 +08:00

573 lines
27 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
本设计文档描述"内容与辅助"模块从老项目PHP ThinkPHP + Layui迁移到新项目ASP.NET Core + Vue 3 + Element Plus的技术设计方案。该模块包含三个子模块单页管理Danye、悬浮球配置FloatBall、福利屋入口WelfareHouse
## Architecture
### 系统架构
```
┌─────────────────────────────────────────────────────────────────┐
│ 前端 (Vue 3 + Element Plus) │
├─────────────────────────────────────────────────────────────────┤
│ views/business/ │
│ ├── danye/ # 单页管理页面 │
│ │ ├── list.vue # 单页列表 │
│ │ └── components/ # 组件 │
│ ├── floatball/ # 悬浮球配置页面 │
│ │ ├── list.vue # 悬浮球列表 │
│ │ └── components/ # 组件 │
│ └── welfarehouse/ # 福利屋入口页面 │
│ ├── list.vue # 福利屋列表 │
│ └── components/ # 组件 │
├─────────────────────────────────────────────────────────────────┤
│ api/business/ │
│ ├── danye.ts # 单页API │
│ ├── floatball.ts # 悬浮球API │
│ └── welfarehouse.ts # 福利屋API │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 后端 (ASP.NET Core) │
├─────────────────────────────────────────────────────────────────┤
│ HoneyBox.Admin.Business/ │
│ ├── Controllers/ │
│ │ ├── DanyeController.cs │
│ │ ├── FloatBallController.cs │
│ │ └── WelfareHouseController.cs │
│ ├── Services/ │
│ │ ├── DanyeService.cs │
│ │ ├── FloatBallService.cs │
│ │ └── WelfareHouseService.cs │
│ └── Models/ │
│ ├── Danye/ │
│ ├── FloatBall/ │
│ └── WelfareHouse/ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 数据库 (SQL Server) │
├─────────────────────────────────────────────────────────────────┤
│ ├── danye # 单页内容表 (已存在) │
│ ├── float_ball_config # 悬浮球配置表 (已存在) │
│ └── welfare_house # 福利屋配置表 (已存在) │
└─────────────────────────────────────────────────────────────────┘
```
### 数据库实体(已存在)
#### Danye 实体
```csharp
public class Danye
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int UpdateTime { get; set; }
public byte Status { get; set; }
public byte IsImageOptimizer { get; set; }
}
```
#### FloatBallConfig 实体
```csharp
public class FloatBallConfig
{
public int Id { get; set; }
public byte Status { get; set; }
public byte Type { get; set; } // 1展示图片 2跳转页面
public string Image { get; set; }
public string LinkUrl { get; set; }
public string PositionX { get; set; }
public string PositionY { get; set; }
public string Width { get; set; }
public string Height { get; set; }
public byte Effect { get; set; } // 0无 1缩放动画
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; }
}
```
#### WelfareHouse 实体
```csharp
public class WelfareHouse
{
public int Id { get; set; }
public string Name { get; set; }
public string Image { get; set; }
public string Url { get; set; }
public int Sort { get; set; }
public byte Status { get; set; }
public int? CreateTime { get; set; }
public int? UpdateTime { get; set; }
}
```
## Components
### 后端组件
#### 1. DanyeController
- `GET /api/business/danye` - 获取单页列表
- `GET /api/business/danye/{id}` - 获取单页详情
- `PUT /api/business/danye/{id}` - 更新单页内容
- `PUT /api/business/danye/{id}/image-optimizer` - 切换图片优化状态
#### 2. FloatBallController
- `GET /api/business/floatball` - 获取悬浮球列表(分页)
- `GET /api/business/floatball/{id}` - 获取悬浮球详情
- `POST /api/business/floatball` - 新增悬浮球
- `PUT /api/business/floatball/{id}` - 更新悬浮球
- `DELETE /api/business/floatball/{id}` - 删除悬浮球
- `PUT /api/business/floatball/{id}/status` - 切换状态
#### 3. WelfareHouseController
- `GET /api/business/welfarehouse` - 获取福利屋列表(分页)
- `GET /api/business/welfarehouse/{id}` - 获取福利屋详情
- `POST /api/business/welfarehouse` - 新增福利屋入口
- `PUT /api/business/welfarehouse/{id}` - 更新福利屋入口
- `DELETE /api/business/welfarehouse/{id}` - 删除福利屋入口
- `PUT /api/business/welfarehouse/{id}/status` - 切换状态
### 前端组件
#### 1. 单页管理模块
- `DanyeList.vue` - 单页列表页面
- `DanyeTable.vue` - 单页表格组件
- `DanyeFormDialog.vue` - 单页编辑弹窗(含富文本编辑器)
#### 2. 悬浮球配置模块
- `FloatBallList.vue` - 悬浮球列表页面
- `FloatBallTable.vue` - 悬浮球表格组件
- `FloatBallFormDialog.vue` - 悬浮球表单弹窗
#### 3. 福利屋入口模块
- `WelfareHouseList.vue` - 福利屋列表页面
- `WelfareHouseTable.vue` - 福利屋表格组件
- `WelfareHouseFormDialog.vue` - 福利屋表单弹窗
## Data Models
### 后端 Models
#### Danye Models
```csharp
// 列表响应
public class DanyeResponse
{
public int Id { get; set; }
public string Title { get; set; }
public bool IsImageOptimizer { get; set; }
public DateTime UpdateTime { get; set; }
}
// 详情响应
public class DanyeDetailResponse
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public bool IsImageOptimizer { get; set; }
}
// 更新请求
public class DanyeUpdateRequest
{
public string? Title { get; set; }
public string Content { get; set; }
}
```
#### FloatBall Models
```csharp
// 列表请求
public class FloatBallListRequest
{
public int Page { get; set; } = 1;
public int PageSize { get; set; } = 10;
}
// 响应
public class FloatBallResponse
{
public int Id { get; set; }
public string? Title { get; set; }
public int Type { get; set; }
public string Image { get; set; }
public string? ImageBj { get; set; }
public string? ImageDetails { get; set; }
public string LinkUrl { get; set; }
public string PositionX { get; set; }
public string PositionY { get; set; }
public string Width { get; set; }
public string Height { get; set; }
public string? ImageDetailsX { get; set; }
public string? ImageDetailsY { get; set; }
public string? ImageDetailsW { get; set; }
public string? ImageDetailsH { get; set; }
public int Effect { get; set; }
public int Status { get; set; }
public DateTime CreatedAt { get; set; }
}
// 创建/更新请求
public class FloatBallCreateRequest
{
public string? Title { get; set; }
public int Type { get; set; }
public string Image { get; set; }
public string? ImageBj { get; set; }
public string? ImageDetails { get; set; }
public string? LinkUrl { get; set; }
public string PositionX { get; set; }
public string PositionY { get; set; }
public string Width { get; set; }
public string Height { get; set; }
public string? ImageDetailsX { get; set; }
public string? ImageDetailsY { get; set; }
public string? ImageDetailsW { get; set; }
public string? ImageDetailsH { get; set; }
public int Effect { get; set; }
public int Status { get; set; } = 1;
}
```
#### WelfareHouse Models
```csharp
// 列表请求
public class WelfareHouseListRequest
{
public int Page { get; set; } = 1;
public int PageSize { get; set; } = 10;
}
// 响应
public class WelfareHouseResponse
{
public int Id { get; set; }
public string Name { get; set; }
public string Image { get; set; }
public string Url { get; set; }
public int Sort { get; set; }
public int Status { get; set; }
public DateTime? CreateTime { get; set; }
}
// 创建/更新请求
public class WelfareHouseCreateRequest
{
public string Name { get; set; }
public string Image { get; set; }
public string Url { get; set; }
public int Sort { get; set; }
public int Status { get; set; } = 1;
}
```
### 前端 TypeScript 接口
```typescript
// Danye
interface DanyeResponse {
id: number
title: string
isImageOptimizer: boolean
updateTime: string
}
interface DanyeDetailResponse {
id: number
title: string
content: string
isImageOptimizer: boolean
}
interface DanyeUpdateRequest {
title?: string
content: string
}
// FloatBall
interface FloatBallListRequest {
page: number
pageSize: number
}
interface FloatBallResponse {
id: number
title?: string
type: number
image: string
imageBj?: string
imageDetails?: string
linkUrl: string
positionX: string
positionY: string
width: string
height: string
imageDetailsX?: string
imageDetailsY?: string
imageDetailsW?: string
imageDetailsH?: string
effect: number
status: number
createdAt: string
}
interface FloatBallCreateRequest {
title?: string
type: number
image: string
imageBj?: string
imageDetails?: string
linkUrl?: string
positionX: string
positionY: string
width: string
height: string
imageDetailsX?: string
imageDetailsY?: string
imageDetailsW?: string
imageDetailsH?: string
effect: number
status?: number
}
// WelfareHouse
interface WelfareHouseListRequest {
page: number
pageSize: number
}
interface WelfareHouseResponse {
id: number
name: string
image: string
url: string
sort: number
status: number
createTime?: string
}
interface WelfareHouseCreateRequest {
name: string
image: string
url: string
sort: number
status?: number
}
```
## API Design
### 单页管理 API
| 方法 | 路径 | 描述 | 请求体 | 响应 |
|------|------|------|--------|------|
| GET | /api/business/danye | 获取单页列表 | - | `ApiResponse<List<DanyeResponse>>` |
| GET | /api/business/danye/{id} | 获取单页详情 | - | `ApiResponse<DanyeDetailResponse>` |
| PUT | /api/business/danye/{id} | 更新单页内容 | `DanyeUpdateRequest` | `ApiResponse<bool>` |
| PUT | /api/business/danye/{id}/image-optimizer | 切换图片优化 | `{ isImageOptimizer: bool }` | `ApiResponse<bool>` |
### 悬浮球配置 API
| 方法 | 路径 | 描述 | 请求体 | 响应 |
|------|------|------|--------|------|
| GET | /api/business/floatball | 获取悬浮球列表 | Query: page, pageSize | `PagedResponse<FloatBallResponse>` |
| GET | /api/business/floatball/{id} | 获取悬浮球详情 | - | `ApiResponse<FloatBallResponse>` |
| POST | /api/business/floatball | 新增悬浮球 | `FloatBallCreateRequest` | `ApiResponse<int>` |
| PUT | /api/business/floatball/{id} | 更新悬浮球 | `FloatBallCreateRequest` | `ApiResponse<bool>` |
| DELETE | /api/business/floatball/{id} | 删除悬浮球 | - | `ApiResponse<bool>` |
| PUT | /api/business/floatball/{id}/status | 切换状态 | `{ status: int }` | `ApiResponse<bool>` |
### 福利屋入口 API
| 方法 | 路径 | 描述 | 请求体 | 响应 |
|------|------|------|--------|------|
| GET | /api/business/welfarehouse | 获取福利屋列表 | Query: page, pageSize | `PagedResponse<WelfareHouseResponse>` |
| GET | /api/business/welfarehouse/{id} | 获取福利屋详情 | - | `ApiResponse<WelfareHouseResponse>` |
| POST | /api/business/welfarehouse | 新增福利屋入口 | `WelfareHouseCreateRequest` | `ApiResponse<int>` |
| PUT | /api/business/welfarehouse/{id} | 更新福利屋入口 | `WelfareHouseCreateRequest` | `ApiResponse<bool>` |
| DELETE | /api/business/welfarehouse/{id} | 删除福利屋入口 | - | `ApiResponse<bool>` |
| PUT | /api/business/welfarehouse/{id}/status | 切换状态 | `{ status: int }` | `ApiResponse<bool>` |
## UI Design
### 单页管理页面
```
┌─────────────────────────────────────────────────────────────────┐
│ 单页管理 │
├─────────────────────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ ID │ 标题 │ 图片优化 │ 更新时间 │ 操作 │ │
│ ├────┼────────────────────────┼─────────┼───────────┼───────┤ │
│ │ 1 │ 关于我们 │ [开关] │ 2026-01-18│ [编辑]│ │
│ │ 2 │ 用户协议 │ [开关] │ 2026-01-18│ [编辑]│ │
│ │ 3 │ 隐私政策 │ [开关] │ 2026-01-18│ [编辑]│ │
│ └─────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
### 单页编辑弹窗
```
┌─────────────────────────────────────────────────────────────────┐
│ 编辑单页 [X] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 标题: [关于我们________________] (ID 2-20 不可编辑) │
│ │
│ 内容: │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ [B] [I] [U] [图片] [链接] ... ││
│ ├─────────────────────────────────────────────────────────────┤│
│ │ ││
│ │ 富文本编辑区域 ││
│ │ ││
│ └─────────────────────────────────────────────────────────────┘│
│ │
│ [取消] [保存] │
└─────────────────────────────────────────────────────────────────┘
```
### 悬浮球列表页面
```
┌─────────────────────────────────────────────────────────────────┐
│ 悬浮球配置 [+ 新增] │
├─────────────────────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ ID │ 标题 │ 图片 │ 背景图 │ 详情图 │ 类型 │ 链接 │ 位置 │ ... │ │
│ ├────┼─────┼─────┼───────┼───────┼─────┼─────┼─────┼─────┤ │
│ │ 1 │ 活动 │ [img]│ [img] │ [img] │ 跳转 │ /act│ 10,20│ ... │ │
│ │ 2 │ 客服 │ [img]│ - │ - │ 展示 │ - │ 10,80│ ... │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ 共 2 条 < 1 > │
└─────────────────────────────────────────────────────────────────┘
```
### 悬浮球表单弹窗
```
┌─────────────────────────────────────────────────────────────────┐
│ 新增悬浮球 [X] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 标题: [____________________] │
│ │
│ 类型: (●) 展示图片 ( ) 跳转页面 │
│ │
│ 悬浮球图片: [上传] [预览] │
│ 背景图片: [上传] [预览] │
│ 详情图片: [上传] [预览] │
│ │
│ 跳转链接: [____________________] (类型为跳转时显示) │
│ │
│ 位置设置: │
│ X: [____] Y: [____] │
│ │
│ 尺寸设置: │
│ 宽: [____] 高: [____] │
│ │
│ 详情图位置: │
│ X: [____] Y: [____] 宽: [____] 高: [____] │
│ │
│ 特效: [无特效 ▼] │
│ 状态: [开关] │
│ │
│ [取消] [保存] │
└─────────────────────────────────────────────────────────────────┘
```
### 福利屋入口列表页面
```
┌─────────────────────────────────────────────────────────────────┐
│ 福利屋入口 [+ 新增] │
├─────────────────────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ ID │ 名称 │ 图片 │ 链接 │ 排序 │ 状态 │ 创建时间 │ 操作│
│ ├────┼─────────┼──────┼──────────┼─────┼─────┼─────────┼─────┤ │
│ │ 1 │ 签到有礼 │ [img] │ /sign │ 1 │ [开关]│ 01-18 │ [编辑][删除]│
│ │ 2 │ 新人福利 │ [img] │ /newbie │ 2 │ [开关]│ 01-18 │ [编辑][删除]│
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ 共 2 条 < 1 > │
└─────────────────────────────────────────────────────────────────┘
```
### 福利屋入口表单弹窗
```
┌─────────────────────────────────────────────────────────────────┐
│ 新增福利屋入口 [X] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 名称: [____________________] * │
│ │
│ 图片: [上传] [预览] * │
│ │
│ 跳转链接: [____________________] * │
│ │
│ 排序: [____] * │
│ │
│ 状态: [开关] │
│ │
│ [取消] [保存] │
└─────────────────────────────────────────────────────────────────┘
```
## Security Considerations
1. **权限控制**: 所有 API 需要验证管理员登录状态和权限
2. **输入验证**: 后端对所有输入进行验证,防止 XSS 和 SQL 注入
3. **富文本安全**: 富文本内容需要进行 HTML 净化处理
4. **图片上传**: 验证图片类型和大小,防止恶意文件上传
## Performance Considerations
1. **分页加载**: 悬浮球和福利屋列表使用分页加载
2. **图片懒加载**: 表格中的图片使用懒加载
3. **富文本编辑器**: 按需加载富文本编辑器组件
## Testing Strategy
1. **单元测试**: 后端 Service 层单元测试
2. **API 测试**: 使用 Swagger 测试 API 接口
3. **前端组件测试**: Vue 组件单元测试
4. **属性测试**: 验证搜索、分页、表单验证等通用属性
## Dependencies
### 后端依赖
- Entity Framework Core (已有)
- Mapster (已有)
### 前端依赖
- Element Plus (已有)
- WangEditor 或 TinyMCE (富文本编辑器,需确认项目中使用的编辑器)
- Vue Router (已有)
## References
- Requirements: `.kiro/specs/content-auxiliary-frontend/requirements.md`
- PHP 参考代码: `server/php/app/admin/controller/Danye.php`
- PHP 参考代码: `server/php/app/admin/controller/FloatBall.php`
- PHP 参考代码: `server/php/app/admin/controller/WelfareHouse.php`
- 实体定义: `server/HoneyBox/src/HoneyBox.Model/Entities/Danye.cs`
- 实体定义: `server/HoneyBox/src/HoneyBox.Model/Entities/FloatBallConfig.cs`
- 实体定义: `server/HoneyBox/src/HoneyBox.Model/Entities/WelfareHouse.cs`