251 lines
7.4 KiB
Markdown
251 lines
7.4 KiB
Markdown
# UI组件设计详设文档
|
||
|
||
> **文档版本**: v1.0
|
||
> **撰写人**: UI/UX设计师 & 前端架构师
|
||
> **创建日期**: 2024年9月11日
|
||
|
||
## 1. 设计系统与主题
|
||
|
||
### 1.1 设计语言
|
||
|
||
- **主题**: 暗黑科技风 (Dark/Tech Theme),与原型设计稿保持一致。
|
||
- **主色调**:
|
||
- 背景: `#1A202C` (深灰蓝)
|
||
- 主色: `#00BFFF` (深天蓝,用于按钮、高亮、链接)
|
||
- 辅助色: `#4A5568` (中灰,用于边框、分割线)
|
||
- 强调色: `#FF4500` (橙红,用于警告、错误提示、攻击命中)
|
||
- **字体**:
|
||
- `sans-serif` 系统默认无衬线字体。
|
||
- 使用 `rem` 和 `em` 作为字体单位,以支持可访问性。
|
||
|
||
### 1.2 Design Token
|
||
|
||
所有颜色、字体大小、间距、圆角等样式参数都将通过Design Token进行管理,以`Sass`变量形式实现。
|
||
|
||
```scss
|
||
// src/styles/tokens.scss
|
||
|
||
// Colors
|
||
$color-background: #1A202C;
|
||
$color-primary: #00BFFF;
|
||
$color-secondary: #4A5568;
|
||
$color-accent: #FF4500;
|
||
$color-text-primary: #FFFFFF;
|
||
$color-text-secondary: #A0AEC0;
|
||
|
||
// Spacing
|
||
$spacing-xs: 0.25rem; // 4px
|
||
$spacing-sm: 0.5rem; // 8px
|
||
$spacing-md: 1rem; // 16px
|
||
$spacing-lg: 1.5rem; // 24px
|
||
$spacing-xl: 2rem; // 32px
|
||
|
||
// Border Radius
|
||
$border-radius-sm: 4px;
|
||
$border-radius-md: 8px;
|
||
$border-radius-lg: 16px;
|
||
```
|
||
|
||
## 2. 原子组件 (Atoms)
|
||
|
||
原子组件是UI构成的最小单元,不可再分。
|
||
|
||
### 2.1 `Button` 组件
|
||
|
||
- **功能**: 标准按钮,支持不同变体和状态。
|
||
- **Props**:
|
||
```typescript
|
||
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||
variant?: 'primary' | 'secondary' | 'danger'; // 样式变体
|
||
size?: 'sm' | 'md' | 'lg'; // 尺寸
|
||
isLoading?: boolean; // 加载状态
|
||
leftIcon?: React.ReactNode;
|
||
rightIcon?: React.ReactNode;
|
||
}
|
||
```
|
||
- **样式**:
|
||
- `primary`: 主色背景,白色文字。
|
||
- `secondary`: 辅助色边框,主色文字。
|
||
- `danger`: 强调色背景,白色文字。
|
||
- `disabled`: 降低透明度,禁用鼠标事件。
|
||
- `isLoading`: 显示加载动画,禁用按钮。
|
||
|
||
### 2.2 `Input` 组件
|
||
|
||
- **功能**: 文本输入框。
|
||
- **Props**:
|
||
```typescript
|
||
interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
||
label?: string; // 标签
|
||
errorMessage?: string; // 错误信息
|
||
leftIcon?: React.ReactNode;
|
||
}
|
||
```
|
||
- **样式**:
|
||
- `focus`: 主色边框高亮。
|
||
- `error`: 强调色边框和错误信息。
|
||
|
||
### 2.3 `Spinner` 组件
|
||
|
||
- **功能**: 加载指示器。
|
||
- **Props**:
|
||
```typescript
|
||
interface SpinnerProps {
|
||
size?: 'sm' | 'md' | 'lg'; // 尺寸
|
||
color?: string; // 颜色
|
||
}
|
||
```
|
||
|
||
### 2.4 `Icon` 组件
|
||
|
||
- **功能**: 图标库封装,使用`react-icons`。
|
||
- **Props**:
|
||
```typescript
|
||
import { IconType } from 'react-icons';
|
||
|
||
interface IconProps {
|
||
as: IconType; // 图标组件
|
||
size?: string | number;
|
||
color?: string;
|
||
}
|
||
```
|
||
|
||
## 3. 分子组件 (Molecules)
|
||
|
||
由原子组件组合而成,完成特定功能。
|
||
|
||
### 3.1 `FormField` 组件
|
||
|
||
- **构成**: `Input` + `Label` + `ErrorMessage`
|
||
- **功能**: 完整的表单字段,包含标签和验证逻辑。
|
||
|
||
### 3.2 `PlayerAvatar` 组件
|
||
|
||
- **构成**: `Avatar` + `Text`
|
||
- **功能**: 显示玩家头像和昵称。
|
||
- **Props**:
|
||
```typescript
|
||
interface PlayerAvatarProps {
|
||
player: {
|
||
avatarUrl: string;
|
||
nickname: string;
|
||
isOwner?: boolean; // 是否是房主
|
||
isReady?: boolean; // 是否已准备
|
||
};
|
||
size?: 'md' | 'lg';
|
||
}
|
||
```
|
||
- **样式**:
|
||
- `isReady`: 头像外圈显示主色高亮。
|
||
- `isOwner`: 昵称旁显示皇冠图标。
|
||
|
||
### 3.3 `RoomListItem` 组件
|
||
|
||
- **构成**: `Text` + `Icon` + `Button`
|
||
- **功能**: 在房间列表中显示单个房间的信息。
|
||
- **Props**:
|
||
```typescript
|
||
interface RoomListItemProps {
|
||
room: {
|
||
roomCode: string;
|
||
name: string;
|
||
playerCount: number;
|
||
isLocked: boolean;
|
||
};
|
||
onJoin: (roomCode: string) => void;
|
||
}
|
||
```
|
||
|
||
## 4. 生物组件 (Organisms)
|
||
|
||
由分子和原子组件构成的更复杂的UI部分。
|
||
|
||
### 4.1 `GameBoard` 组件
|
||
|
||
- **功能**: 核心游戏棋盘UI,负责渲染10x10的网格和飞机。
|
||
- **构成**: 多个 `GridCell` 组件。
|
||
- **Props**:
|
||
```typescript
|
||
interface GameBoardProps {
|
||
boardState: BoardState; // 棋盘状态数据
|
||
isMyBoard: boolean; // 是否是自己的棋盘
|
||
onCellClick: (position: { x: number, y: number }) => void; // 单元格点击事件
|
||
placedPlanes?: Plane[]; // 预放置的飞机
|
||
}
|
||
```
|
||
- **`GridCell` 子组件**:
|
||
- 根据单元格状态(`empty`, `plane_part`, `miss`, `hit`, `destroy`)显示不同样式。
|
||
- 在对手棋盘上,`plane_part`状态默认不显示,除非被攻击过。
|
||
- 鼠标悬停在可攻击的单元格上时显示准星光标。
|
||
|
||
### 4.2 `PlanePlacementPanel` 组件
|
||
|
||
- **功能**: 飞机布置阶段的操作面板,允许玩家拖拽或旋转飞机。
|
||
- **构成**: `PlanePreview` 组件 + `Button` (旋转/确认)
|
||
- **Props**:
|
||
```typescript
|
||
interface PlanePlacementPanelProps {
|
||
onPlanesConfirm: (planes: Plane[]) => void;
|
||
}
|
||
```
|
||
- **交互**:
|
||
- 提供3个默认形状的飞机供拖拽到棋盘。
|
||
- 支持点击飞机进行90度旋转。
|
||
- 棋盘上会实时预览飞机位置,并对非法位置(越界、重叠)进行红色高亮提示。
|
||
|
||
### 4.3 `Header` 组件
|
||
|
||
- **功能**: 应用的全局顶部导航栏。
|
||
- **构成**: `Logo` + `UserInfo` + `SettingsButton`
|
||
|
||
## 5. 模板组件 (Templates)
|
||
|
||
定义页面的整体布局结构。
|
||
|
||
### 5.1 `MainLayout` 组件
|
||
|
||
- **功能**: 应用的主布局,包含页头、内容区、页脚。
|
||
- **构成**: `Header` + `children` + `Footer`
|
||
- **插槽(Slots)**: 通过`children` prop 插入页面具体内容。
|
||
|
||
## 6. 页面组件 (Pages)
|
||
|
||
完整的页面,由模板和多个生物/分子组件构成。
|
||
|
||
### 6.1 `HomePage`
|
||
|
||
- **路径**: `/`
|
||
- **功能**: 游戏入口页面,包含"创建房间"和"加入房间"按钮。
|
||
- **组件构成**: `MainLayout`, `Logo`, `Button`。
|
||
|
||
### 6.2 `RoomListPage`
|
||
|
||
- **路径**: `/rooms`
|
||
- **功能**: 显示公开的房间列表,支持刷新和搜索。
|
||
- **组件构成**: `MainLayout`, `RoomListItem`, `Spinner`, `Button`。
|
||
|
||
### 6.3 `RoomWaitingPage`
|
||
|
||
- **路径**: `/room/:roomCode`
|
||
- **功能**: 玩家等待页面,显示双方玩家信息和准备状态。
|
||
- **组件构成**: `MainLayout`, `PlayerAvatar` (x2), `Button` (准备/开始游戏), `ChatBox` (可选)。
|
||
- **逻辑**:
|
||
- 房主显示"开始游戏"按钮,当所有玩家准备好后激活。
|
||
- 其他玩家显示"准备"按钮。
|
||
- 实时监听WebSocket的`ROOM_STATE_UPDATE`事件更新UI。
|
||
|
||
### 6.4 `GamePage`
|
||
|
||
- **路径**: `/game/:gameId`
|
||
- **功能**: 核心游戏对战页面。
|
||
- **组件构成**:
|
||
- `MainLayout`
|
||
- `GameBoard` (我方棋盘)
|
||
- `GameBoard` (敌方棋盘)
|
||
- `GameStatusPanel`: 显示当前回合、倒计时、游戏日志。
|
||
- `PlanePlacementPanel`: 仅在飞机布置阶段显示。
|
||
- **逻辑**:
|
||
- 页面加载时从Zustand Store获取游戏状态。
|
||
- 监听WebSocket的`GAME_STATE_UPDATE`事件更新整个页面。
|
||
- 根据游戏阶段(`placing`, `battling`, `finished`)渲染不同UI。
|
||
- 在`finished`阶段,显示游戏结果弹窗(`GameResultModal`)。 |