Skip to content

Commit e038b4d

Browse files
refactor: implement new application layout with a trade drawer, chart tabs, and mobile view management.
1 parent 4edd013 commit e038b4d

26 files changed

Lines changed: 1754 additions & 646 deletions
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Plan-07: 布局重构 (方案 B 浮动操作栏)
2+
3+
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
4+
5+
**目标 (Goal):** 将 3 栏布局重构为图表全屏 + 浮动操作栏 + Drawer 交易面板,提升看图和操作体验。
6+
7+
**架构设计 (Architecture):**
8+
```
9+
重构前 重构后
10+
┌────────────┬──────┬───────┐ ┌─────────────────────────────────┐
11+
│ K线图 │订单簿│交易面板│ →→→ │ K线图 (全宽) [FloatPnL] │
12+
│ (57%) │(13%)│ (30%) │ ├─────────────────────────────────┤
13+
│ │ │Y轴滚动│ │ [做多] [做空] │
14+
└───────────┴─────┴───────┘ └─────────────────────────────────┘
15+
点击按钮 → Drawer 滑入
16+
```
17+
18+
**技术栈:** React 18 + Tailwind CSS 4 + Mobile-First + localStorage
19+
20+
---
21+
22+
## 计划结构
23+
24+
| Phase | 文档 | 内容 |
25+
|-------|------|------|
26+
| 0 | [Phase-0](./Plan-07-LayoutRefactor/Phase-0-Preparation.md) | 准备工作 |
27+
| 1 | [Phase-1](./Plan-07-LayoutRefactor/Phase-1-CoreLayout.md) | 核心布局 |
28+
| 2 | [Phase-2](./Plan-07-LayoutRefactor/Phase-2-FloatingComponents.md) | 浮动组件 |
29+
| 3 | [Phase-3](./Plan-07-LayoutRefactor/Phase-3-TradeDrawer.md) | Drawer 交易面板 |
30+
| 4 | [Phase-4](./Plan-07-LayoutRefactor/Phase-4-Interactions.md) | 交互优化 |
31+
32+
---
33+
34+
## 已确认决策
35+
36+
| 项目 | 决策 |
37+
|------|------|
38+
| Drawer 方向 | 移动端底部 / 桌面端右侧 |
39+
| 浮动卡片 | 盈亏百分比 + 金额 |
40+
| 快捷按钮 | 等宽平铺 |
41+
| 订单簿 | Tab 切换 |
42+
| 固定模式 | localStorage 持久化 |
43+
| LIVE 模式 | 完全按 MOCK 显示 |
44+
| 无持仓 | 显示"暂无持仓" |
45+
| 快捷键 | B/S/Esc |
46+
47+
---
48+
49+
## 验收标准
50+
51+
1. ✅ 移动端图表全屏
52+
2. ✅ 底部按钮始终可点击
53+
3. ✅ 持仓摘要浮动右下角
54+
4. ✅ Drawer 滑入时图表仍可见
55+
5. ✅ 键盘快捷键生效
56+
6.`npm run build` 无错误
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Phase 0: 准备工作
2+
3+
> **预计耗时:** 30 分钟
4+
5+
---
6+
7+
## Task 0.1: 创建功能分支
8+
9+
**操作:**
10+
```bash
11+
git checkout -b feat/layout-refactor-plan07
12+
```
13+
14+
**验证:** `git branch` 显示当前在新分支
15+
16+
---
17+
18+
## Task 0.2: 备份现有布局代码
19+
20+
**文件:** `/src/App.tsx`
21+
22+
**操作:** 复制当前 App.tsx 的核心布局结构作为参考 (无需实际文件)
23+
24+
**验证:** 理解现有 3 栏布局结构
25+
26+
---
27+
28+
## Task 0.3: 创建组件目录结构
29+
30+
**操作:**
31+
```bash
32+
mkdir -p src/components/Layout/FloatingPnL
33+
mkdir -p src/components/Layout/QuickTradeBar
34+
mkdir -p src/components/Layout/TradeDrawer
35+
mkdir -p src/components/Layout/ChartTabs
36+
```
37+
38+
**验证:** 目录已创建
39+
40+
---
41+
42+
## Task 0.4: 添加 localStorage Hook
43+
44+
**文件:** 创建 `/src/hooks/useLocalStorage.ts`
45+
46+
```typescript
47+
import { useState, useEffect, useCallback } from 'react';
48+
49+
export function useLocalStorage<T>(key: string, initialValue: T) {
50+
const [storedValue, setStoredValue] = useState<T>(() => {
51+
try {
52+
const item = localStorage.getItem(key);
53+
return item ? JSON.parse(item) : initialValue;
54+
} catch {
55+
return initialValue;
56+
}
57+
});
58+
59+
const setValue = useCallback((value: T | ((val: T) => T)) => {
60+
setStoredValue((prev) => {
61+
const valueToStore = value instanceof Function ? value(prev) : value;
62+
localStorage.setItem(key, JSON.stringify(valueToStore));
63+
return valueToStore;
64+
});
65+
}, [key]);
66+
67+
return [storedValue, setValue] as const;
68+
}
69+
```
70+
71+
**验证:** `npx tsc --noEmit` 无错误
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# Phase 1: 核心布局重构
2+
3+
> **预计耗时:** 2-3 小时
4+
5+
---
6+
7+
## 架构变化
8+
9+
```
10+
重构前: 重构后:
11+
┌─────────────────────────────┐ ┌─────────────────────────────┐
12+
│ Header │ │ Header │
13+
├────────┬──────┬─────────────┤ ├─────────────────────────────┤
14+
│ Chart │Order │ TradePanel │ │ ChartTabs (全宽) │
15+
│ │Book │ (滚动) │ │ [图表] [订单簿] [深度] │
16+
├────────┴──────┴─────────────┤ ├─────────────────────────────┤
17+
│ StatsPanel │ │ StatsPanel │
18+
└─────────────────────────────┘ ├─────────────────────────────┤
19+
│ QuickTradeBar [做多] [做空] │
20+
└─────────────────────────────┘
21+
```
22+
23+
---
24+
25+
## Task 1.1: 创建 ChartTabs 组件
26+
27+
**文件:** 创建 `/src/components/Layout/ChartTabs/index.tsx`
28+
29+
```tsx
30+
import { memo, useState, type ReactNode } from 'react';
31+
32+
type TabType = 'chart' | 'orderbook' | 'depth';
33+
34+
interface ChartTabsProps {
35+
chartContent: ReactNode;
36+
orderBookContent: ReactNode;
37+
depthContent: ReactNode;
38+
}
39+
40+
const TABS: { id: TabType; label: string; icon: string }[] = [
41+
{ id: 'chart', label: '图表', icon: '📈' },
42+
{ id: 'orderbook', label: '订单簿', icon: '📊' },
43+
{ id: 'depth', label: '深度', icon: '📉' },
44+
];
45+
46+
function ChartTabs({ chartContent, orderBookContent, depthContent }: ChartTabsProps) {
47+
const [activeTab, setActiveTab] = useState<TabType>('chart');
48+
49+
return (
50+
<div className="flex flex-col h-full">
51+
{/* Tab 切换栏 */}
52+
<div className="flex border-b border-border-dark bg-bg-surface shrink-0">
53+
{TABS.map((tab) => (
54+
<button
55+
key={tab.id}
56+
onClick={() => setActiveTab(tab.id)}
57+
className={`
58+
flex-1 py-2 text-xs font-medium transition-colors
59+
${activeTab === tab.id
60+
? 'text-white border-b-2 border-success'
61+
: 'text-gray-500 hover:text-gray-300'
62+
}
63+
`}
64+
>
65+
<span className="mr-1">{tab.icon}</span>
66+
{tab.label}
67+
</button>
68+
))}
69+
</div>
70+
71+
{/* 内容区域 */}
72+
<div className="flex-1 min-h-0">
73+
{activeTab === 'chart' && chartContent}
74+
{activeTab === 'orderbook' && orderBookContent}
75+
{activeTab === 'depth' && depthContent}
76+
</div>
77+
</div>
78+
);
79+
}
80+
81+
export default memo(ChartTabs);
82+
```
83+
84+
**验证:** `npx tsc --noEmit` 无错误
85+
86+
---
87+
88+
## Task 1.2: 修改 App.tsx 主布局
89+
90+
**文件:** 修改 `/src/App.tsx`
91+
92+
**操作:** 将 3 栏布局改为 2 区域布局 (ChartTabs + Bottom)
93+
94+
```tsx
95+
// 核心布局变化:
96+
<div className="flex flex-col h-screen">
97+
<Header />
98+
99+
{/* 主内容区 - 全宽 */}
100+
<main className="flex-1 min-h-0 relative">
101+
<ChartTabs
102+
chartContent={<KLineChart />}
103+
orderBookContent={<OrderBook />}
104+
depthContent={<DepthChart />}
105+
/>
106+
</main>
107+
108+
<StatsPanel />
109+
110+
{/* 底部快捷操作栏 (Phase 2 添加) */}
111+
{/* <QuickTradeBar /> */}
112+
</div>
113+
```
114+
115+
**验证:**
116+
- `npm run build` 无错误
117+
- 浏览器访问,图表全宽显示
118+
119+
---
120+
121+
## Task 1.3: 移除原有订单簿独立栏
122+
123+
**文件:** 修改 `/src/App.tsx`
124+
125+
**操作:** 删除原有 `<section>` 包裹的 OrderBook 独立区域
126+
127+
**验证:** 订单簿只在 Tab 中显示
128+
129+
---
130+
131+
## Task 1.4: 移除原有右侧 TradePanel
132+
133+
**文件:** 修改 `/src/App.tsx`
134+
135+
**操作:**
136+
- 删除桌面端右侧固定 TradePanel
137+
- 删除移动端底部 TradePanel
138+
- 保留 TradePanel 组件本身 (后续在 Drawer 中使用)
139+
140+
**验证:**
141+
- `npm run build` 无错误
142+
- 页面只显示 Header + ChartTabs + StatsPanel

0 commit comments

Comments
 (0)