chore: add react-window and @types/react-window dependencies

This commit is contained in:
iven
2026-03-15 21:08:47 +08:00
parent 5bc4487146
commit 4862e79b2b
46 changed files with 7260 additions and 0 deletions

View File

@@ -0,0 +1,615 @@
# ZCLAW UI/UX 全面优化计划
## 背景
ZCLAW 是基于 OpenFang (Rust Agent OS) 的 AI Agent 桌面客户端。经过 Phase 1-8 的功能开发,系统已达到 93% API 覆盖率和 100% UI 组件完成度。现在需要对前端设计元素进行全面优化,提升用户操作效率与视觉体验。
## 当前状态分析
### 代码结构
- **框架**: React 18 + TypeScript + Tauri
- **样式**: Tailwind CSS v4.2.1
- **状态管理**: Zustand (gatewayStore, chatStore, teamStore)
- **图标**: lucide-react
- **组件数量**: 37 个组件
### 现有设计特点
- **主色调**: Orange (#f97316) 作为品牌色
- **布局**: 三栏式 (Sidebar w-64 | Main flex-1 | RightPanel w-80)
- **暗黑模式**: 部分支持 (部分组件有 `dark:` 变体)
- **动画**: 基础 CSS 动画 (animate-pulse, animate-spin)
---
## 发现的问题
### 1. 设计系统问题 (CRITICAL)
| 问题 | 位置 | 影响 |
|------|------|------|
| 无 UI 组件库 | 全局 | 一致性差,重复代码 |
| 颜色系统不完整 | index.css | 品牌识别度低 |
| 暗黑模式不完整 | 多个组件 | 用户体验不一致 |
| **使用 Emoji 作为 UI 图标** | ChatArea, App.tsx | 不专业,违反设计规范 |
### 2. 可访问性问题 (CRITICAL)
| 问题 | 位置 | 影响 |
|------|------|------|
| 缺少 aria-label | 图标按钮 | 屏幕阅读器无法识别 |
| 焦点状态不明显 | 多个交互元素 | 键盘导航困难 |
| 颜色对比度不足 | text-gray-400 类 | 可读性差 |
### 3. 交互与动画 (HIGH)
| 问题 | 位置 | 影响 |
|------|------|------|
| 无过渡动画库 | 全局 | 交互生硬 |
| 悬停状态不一致 | 多个组件 | 用户困惑 |
| 缺少骨架屏 | 数据加载 | 感知性能差 |
### 4. 视觉层次 (MEDIUM)
| 问题 | 位置 | 影响 |
|------|------|------|
| 卡片阴影过轻 | shadow-sm | 层次不明显 |
| 间距不一致 | padding/margin | 视觉混乱 |
| 字体过小 | text-xs | 可读性差 |
### 5. 用户体验 (MEDIUM)
| 问题 | 位置 | 影响 |
|------|------|------|
| 空状态设计简陋 | 多个列表 | 缺乏引导 |
| 错误提示不明显 | 表单等 | 用户困惑 |
| 加载反馈不足 | API 调用 | 用户焦虑 |
---
## 用户确认的优化方向
| 决策项 | 选择 |
|--------|------|
| 动画库 | ✅ 引入 Framer Motion |
| 暗黑模式 | ✅ 完整支持所有组件 |
| 组件库 | ✅ 创建 Button, Card, Input 等基础组件 |
---
## 优化方案
### Phase 1: 设计系统建立 (P0)
#### 1.1 CSS 变量系统
**文件**: `desktop/src/index.css`
```css
:root {
/* Brand Colors */
--color-primary: #f97316;
--color-primary-hover: #ea580c;
--color-primary-light: #fff7ed;
/* Semantic Colors */
--color-success: #22c55e;
--color-warning: #eab308;
--color-error: #ef4444;
--color-info: #3b82f6;
/* Neutral Colors */
--color-bg: #ffffff;
--color-bg-secondary: #f9fafb;
--color-border: #e5e7eb;
--color-text: #111827;
--color-text-secondary: #6b7280;
--color-text-muted: #9ca3af;
/* Spacing Scale */
--space-xs: 4px;
--space-sm: 8px;
--space-md: 16px;
--space-lg: 24px;
--space-xl: 32px;
/* Border Radius */
--radius-sm: 6px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-xl: 16px;
--radius-full: 9999px;
/* Shadows */
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1);
/* Transitions */
--transition-fast: 150ms ease;
--transition-normal: 200ms ease;
--transition-slow: 300ms ease;
}
.dark {
--color-bg: #0f172a;
--color-bg-secondary: #1e293b;
--color-border: #334155;
--color-text: #f1f5f9;
--color-text-secondary: #94a3b8;
--color-text-muted: #64748b;
}
```
#### 1.2 统一 Tailwind 配置
**文件**: `desktop/tailwind.config.js` (新建)
```javascript
export default {
theme: {
extend: {
colors: {
primary: {
DEFAULT: 'var(--color-primary)',
hover: 'var(--color-primary-hover)',
light: 'var(--color-primary-light)',
},
},
boxShadow: {
'card': 'var(--shadow-md)',
'hover': 'var(--shadow-lg)',
},
transitionDuration: {
'fast': '150ms',
'normal': '200ms',
},
},
},
}
```
### Phase 2: 基础组件库 (P0)
#### 2.1 Button 组件
**文件**: `desktop/src/components/ui/Button.tsx`
```tsx
import { forwardRef } from 'react';
import { motion } from 'framer-motion';
import { cn } from '../../lib/utils';
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: 'primary' | 'secondary' | 'ghost' | 'danger';
size?: 'sm' | 'md' | 'lg';
loading?: boolean;
}
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant = 'primary', size = 'md', loading, children, disabled, ...props }, ref) => {
return (
<motion.button
ref={ref}
whileTap={{ scale: 0.98 }}
className={cn(
'inline-flex items-center justify-center font-medium rounded-lg transition-colors',
'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2',
'disabled:opacity-50 disabled:cursor-not-allowed',
variants[variant],
sizes[size],
className
)}
disabled={disabled || loading}
{...props}
>
{loading && <Spinner className="mr-2" />}
{children}
</motion.button>
);
}
);
const variants = {
primary: 'bg-primary text-white hover:bg-primary-hover',
secondary: 'bg-gray-100 text-gray-900 hover:bg-gray-200',
ghost: 'text-gray-600 hover:bg-gray-100',
danger: 'bg-red-500 text-white hover:bg-red-600',
};
const sizes = {
sm: 'px-3 py-1.5 text-xs',
md: 'px-4 py-2 text-sm',
lg: 'px-6 py-3 text-base',
};
```
#### 2.2 Card 组件
**文件**: `desktop/src/components/ui/Card.tsx`
```tsx
import { motion } from 'framer-motion';
import { cn } from '../../lib/utils';
interface CardProps {
children: React.ReactNode;
className?: string;
hoverable?: boolean;
onClick?: () => void;
}
export function Card({ children, className, hoverable, onClick }: CardProps) {
const Component = hoverable ? motion.div : 'div';
return (
<Component
className={cn(
'rounded-xl border border-gray-200 bg-white p-4 shadow-sm',
'dark:border-gray-700 dark:bg-gray-800',
hoverable && 'cursor-pointer hover:shadow-md transition-shadow duration-200',
className
)}
{...(hoverable && {
whileHover: { y: -2 },
onClick,
})}
>
{children}
</Component>
);
}
```
#### 2.3 cn() 工具函数
**文件**: `desktop/src/lib/utils.ts`
```typescript
import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
```
**原则**: 使用 SVG 图标 (lucide-react),不使用 emoji 作为 UI 元素
| 文件 | 当前 | 修改为 |
|------|------|--------|
| `ChatArea.tsx:79` | `🤖` | `<BotIcon className="w-10 h-10 text-gray-400" />` |
| `ChatArea.tsx:279` | `🦞` (消息气泡) | `<ZClawLogo className="w-6 h-6" />` (自定义图标) |
| `App.tsx:79` | `🤖` | `<BotIcon />` |
| `App.tsx:98` | `👥` | `<UsersIcon />` |
| `Sidebar.tsx:98` | 用户头像 emoji | 首字母 + 渐变背景 |
### Phase 3: 可访问性改进 (P0)
#### 3.1 添加 aria-label
**关键文件**:
- `Sidebar.tsx` - 设置按钮、tab 切换
- `ChatArea.tsx` - 发送按钮、附件按钮、模型选择器
- `RightPanel.tsx` - tab 切换、刷新按钮
- `SettingsLayout.tsx` - 返回按钮、菜单项
```tsx
// 示例修复
<button
onClick={onOpenSettings}
aria-label="打开设置"
className="..."
>
<Settings className="w-4 h-4" />
</button>
```
#### 3.2 焦点状态增强
```css
/* 全局焦点样式 */
:focus-visible {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
}
/* 按钮焦点 */
.btn:focus-visible {
ring: 2px;
ring-color: var(--color-primary);
ring-offset: 2px;
}
```
#### 3.3 颜色对比度修复
| 当前 | 对比度 | 修复 |
|------|--------|------|
| `text-gray-400` on white | 3.1:1 (FAIL) | 改为 `text-gray-500` (#6b7280) 4.6:1 |
| `text-gray-300` on white | 2.9:1 (FAIL) | 改为 `text-gray-600` (#4b5563) 7.0:1 |
### Phase 4: 交互与动画增强 (P1)
#### 4.1 Framer Motion 动画系统
**新文件**: `desktop/src/lib/animations.ts`
```typescript
import { Variants } from 'framer-motion';
// 页面切换动画
export const pageVariants: Variants = {
initial: { opacity: 0, y: 10 },
animate: { opacity: 1, y: 0 },
exit: { opacity: 0, y: -10 },
};
// 列表项交错动画
export const listItemVariants: Variants = {
hidden: { opacity: 0, x: -10 },
visible: { opacity: 1, x: 0 },
};
// 按钮点击动画
export const buttonTap = { scale: 0.98 };
// 卡片悬停动画
export const cardHover = { y: -2, boxShadow: '0 10px 25px -5px rgb(0 0 0 / 0.1)' };
// 默认过渡配置
export const defaultTransition = {
duration: 0.2,
ease: [0.4, 0, 0.2, 1],
};
```
**使用示例**:
```tsx
import { motion, AnimatePresence } from 'framer-motion';
import { pageVariants, defaultTransition } from '../lib/animations';
// 页面切换
<AnimatePresence mode="wait">
<motion.div
key={view}
variants={pageVariants}
initial="initial"
animate="animate"
exit="exit"
transition={defaultTransition}
>
{content}
</motion.div>
</AnimatePresence>
```
**新文件**: `desktop/src/components/ui/Skeleton.tsx`
```tsx
export function Skeleton({ className }: { className?: string }) {
return (
<div
className={cn(
"animate-pulse bg-gray-200 dark:bg-gray-700 rounded",
className
)}
/>
);
}
export function CardSkeleton() {
return (
<div className="rounded-xl border border-gray-200 p-4">
<Skeleton className="h-4 w-24 mb-3" />
<Skeleton className="h-3 w-full mb-2" />
<Skeleton className="h-3 w-3/4" />
</div>
);
}
```
#### 4.3 Toast 通知系统
**新文件**: `desktop/src/components/ui/Toast.tsx`
用于替代 `alert()` 和内联错误消息。
### Phase 5: 视觉层次优化 (P1)
#### 5.1 卡片阴影增强
```diff
- className="rounded-xl border border-gray-200 bg-white p-4 shadow-sm"
+ className="rounded-xl border border-gray-200 bg-white p-4 shadow-sm hover:shadow-md transition-shadow duration-200"
```
#### 5.2 间距标准化
| 区域 | 当前 | 标准 |
|------|------|------|
| 页面内边距 | 不一致 | `p-6` (24px) |
| 卡片内边距 | `p-3`/`p-4` | `p-4` (16px) |
| 列表项间距 | `space-y-1`/`space-y-2` | `space-y-2` (8px) |
| 区域间距 | `space-y-3`/`space-y-4` | `space-y-4` (16px) |
#### 5.3 字体大小优化
| 类型 | 当前 | 建议 |
|------|------|------|
| 正文 | `text-xs` (12px) | `text-sm` (14px) |
| 小标签 | `text-[10px]` | `text-xs` (12px) |
| 标题 | `text-lg` | 保持 |
### Phase 6: 用户体验改进 (P2)
#### 6.1 空状态设计
**新组件**: `EmptyState.tsx`
```tsx
interface EmptyStateProps {
icon: React.ReactNode;
title: string;
description: string;
action?: React.ReactNode;
}
export function EmptyState({ icon, title, description, action }: EmptyStateProps) {
return (
<div className="flex-1 flex items-center justify-center p-6">
<div className="text-center max-w-sm">
<div className="w-16 h-16 bg-gray-100 dark:bg-gray-800 rounded-full flex items-center justify-center mx-auto mb-4 text-gray-400">
{icon}
</div>
<h3 className="text-base font-semibold text-gray-700 dark:text-gray-300 mb-2">
{title}
</h3>
<p className="text-sm text-gray-500 dark:text-gray-400 mb-4">
{description}
</p>
{action}
</div>
</div>
);
}
```
#### 6.2 错误状态设计
- 使用红色边框和背景
- 显示错误图标
- 提供重试按钮
#### 6.3 加载状态改进
- 按钮加载时禁用并显示 spinner
- 列表加载时显示骨架屏
- 全局加载时显示顶部进度条
---
## 实施顺序
### 阶段 1: 基础设施 (2-3 天)
1. 安装依赖: `framer-motion clsx tailwind-merge`
2. 创建 CSS 变量系统 (含完整暗黑模式)
3. 创建 tailwind.config.js
4. 创建 utils.ts (cn 函数)
5. 创建 animations.ts (Framer Motion 预设)
### 阶段 2: 基础组件库 (2-3 天)
1. 创建 Button 组件 (含变体: primary, secondary, ghost)
2. 创建 Card 组件 (含悬停动画)
3. 创建 Input 组件 (含焦点状态)
4. 创建 Badge 组件
5. 创建 Skeleton 组件
6. 创建 EmptyState 组件
7. 创建 Toast 组件
### 阶段 3: 可访问性修复 (1-2 天)
1. 添加 aria-label 到所有图标按钮
2. 修复颜色对比度问题
3. 增强焦点状态
4. 添加键盘导航支持
### 阶段 4: 视觉优化 (2-3 天)
1. 移除所有 emoji 图标,替换为 SVG
2. 使用基础组件库重构现有组件
3. 标准化间距
4. 增强卡片阴影和悬停效果
5. 完善暗黑模式支持
### 阶段 5: 交互增强 (2-3 天)
1. 添加 Framer Motion 页面切换动画
2. 添加列表项动画 (stagger)
3. 添加按钮点击反馈
4. 实现骨架屏加载
5. 集成 Toast 通知系统
### 阶段 6: 组件重构 (2-3 天)
1. 重构 Sidebar 组件 (使用新组件库 + 动画)
2. 重构 ChatArea 组件
3. 重构 RightPanel 组件
4. 重构 SettingsLayout 组件
5. 完整暗黑模式测试
---
## 关键文件清单
### 需要修改的文件
| 文件 | 修改内容 |
|------|----------|
| `desktop/src/index.css` | 添加 CSS 变量系统 |
| `desktop/src/components/Sidebar.tsx` | aria-label, 动画, emoji 移除 |
| `desktop/src/components/ChatArea.tsx` | aria-label, emoji 移除, 空状态 |
| `desktop/src/components/RightPanel.tsx` | aria-label, 间距标准化 |
| `desktop/src/components/Settings/SettingsLayout.tsx` | aria-label, 间距标准化 |
| `desktop/src/App.tsx` | emoji 移除, 空状态组件 |
### 需要新建的文件
| 文件 | 用途 |
|------|------|
| `desktop/tailwind.config.js` | Tailwind 自定义配置 |
| `desktop/src/components/ui/Button.tsx` | 按钮组件 |
| `desktop/src/components/ui/Card.tsx` | 卡片组件 |
| `desktop/src/components/ui/Input.tsx` | 输入框组件 |
| `desktop/src/components/ui/Badge.tsx` | 标签组件 |
| `desktop/src/components/ui/Skeleton.tsx` | 骨架屏组件 |
| `desktop/src/components/ui/EmptyState.tsx` | 空状态组件 |
| `desktop/src/components/ui/Toast.tsx` | Toast 通知组件 |
| `desktop/src/lib/utils.ts` | cn() 工具函数 |
| `desktop/src/lib/animations.ts` | Framer Motion 动画预设 |
### 需要安装的依赖
```bash
cd desktop
pnpm add framer-motion clsx tailwind-merge
```
---
## 验证方法
### 1. 视觉验证
```bash
pnpm tauri:dev
```
- 检查所有页面在浅色/深色模式下的显示
- 检查所有交互元素的悬停状态
- 检查所有空状态的显示
### 2. 可访问性验证
- 使用 Chrome DevTools Lighthouse 进行可访问性审计
- 使用 Tab 键进行键盘导航测试
- 使用屏幕阅读器测试 (NVDA/JAWS)
### 3. 类型检查
```bash
cd desktop && pnpm tsc --noEmit
```
### 4. 构建验证
```bash
pnpm build
```
---
## 预期成果
1. **设计系统**: 完整的 CSS 变量和 Tailwind 配置
2. **组件库**: 7 个可复用 UI 组件 (Button, Card, Input, Badge, Skeleton, EmptyState, Toast)
3. **可访问性**: Lighthouse 可访问性分数 > 90
4. **暗黑模式**: 所有组件完整支持暗黑模式
5. **动画系统**: Framer Motion 动画预设和页面过渡
6. **视觉一致性**: 所有组件遵循统一设计规范
7. **无 Emoji**: 所有 UI 图标使用 SVG
---
*计划创建: 2026-03-15*
*预计完成: 11-17 个工作日*

View File

@@ -0,0 +1,571 @@
# ZCLAW 系统全面代码分析与演化路线图
## 上下文 (Context)
**目的**: 对 ZCLAW 系统进行全面的代码层面现状分析,识别偏离点、潜在风险,制定分阶段演化路线图。
**当前状态**:
- OpenFang v0.4.0 + ZClaw Desktop v0.2.0
- API 覆盖率: 93% (63/68 端点)
- UI 完成度: 100% (30/30 组件)
- Skills 定义: 68 个已完成
- Phase 1-8 已完成
**技术栈**:
- React 19.1.0 + TypeScript 5.8.3
- Tauri 2.x (Rust 后端)
- Zustand 5.0.11 (状态管理)
- Vite 7.0.4 + Tailwind CSS 4.2.1
---
## 一、代码结构分析
### 1.1 项目结构
```
ZClaw_openfang/
├── desktop/ # Tauri 桌面应用 (主要代码)
│ ├── src/
│ │ ├── components/ # React UI (46 组件)
│ │ ├── store/ # Zustand stores (3 个)
│ │ ├── lib/ # API 客户端和工具
│ │ ├── types/ # TypeScript 类型定义
│ │ └── App.tsx # 主应用组件
│ └── src-tauri/ # Rust 后端
├── skills/ # 68 个 SKILL.md 定义
├── hands/ # 7 个 HAND.toml 配置
├── config/ # OpenFang TOML 配置
├── tests/ # Vitest 测试
└── docs/ # 文档
```
### 1.2 核心数据流
```
React UI → Zustand Store → GatewayClient → OpenFang Kernel (端口 50051)
WebSocket (ws://127.0.0.1:50051/ws)
REST API (http://127.0.0.1:50051/api/*)
```
---
## 二、架构问题分析
### 2.1 Store 层问题 (高优先级)
| 问题 | 位置 | 影响 |
|------|------|------|
| **gatewayStore 巨型化** | `store/gatewayStore.ts` | 50+ 字段、40+ actions 在单一 store |
| **持久化策略不一致** | 所有 stores | chatStore 用 Zustand persistteamStore 手动 localStorage |
| **Agent/Clone ID 混淆** | `chatStore.ts` | 前端 `clone_` 前缀与后端 ID 不一致 |
### 2.2 安全问题 (关键)
| 问题 | 位置 | 严重程度 |
|------|------|----------|
| **Token 存储在 localStorage** | `gateway-client.ts:103` | HIGH |
| **Ed25519 密钥无加密** | `gateway-client.ts:157-188` | HIGH |
| **JSON.parse 无保护** | `HandParamsForm.tsx:409`, `WorkflowEditor.tsx:167` | HIGH |
| **默认使用 ws://** | `gateway-client.ts:20-22` | MEDIUM |
### 2.3 代码质量问题
| 问题 | 数量 | 主要位置 |
|------|------|----------|
| **`any` 类型滥用** | 60+ 处 | `gatewayStore.ts` (~35), `gateway-client.ts` (~12) |
| **错误处理不完整** | 多处 | 部分 catch 块静默忽略错误 |
| **测试覆盖不足** | - | `gateway-client.ts`, `toml-utils.ts` 无测试 |
| **代码重复** | 30+ 处 | 错误处理模式重复 |
### 2.4 性能问题
| 问题 | 位置 | 影响 |
|------|------|------|
| **消息数组频繁 map** | `chatStore.ts` | 长对话性能下降 |
| **无消息分页** | `chatStore.ts` | 内存持续增长 |
| **无 WebSocket 批处理** | `gateway-client.ts` | 高频消息处理效率低 |
---
## 三、分阶段演化路线图
### Phase 9: 安全加固 (1 周) - 3 代理并行
**目标**: 修复关键安全漏洞
#### 并行执行架构
```
┌─────────────────────────────────────────────────────────────┐
│ Agent A: JSON 安全 │ Agent B: Token 迁移 │
│ ├── lib/json-utils.ts │ ├── gateway-client.ts │
│ ├── HandParamsForm.tsx │ ├── gatewayStore.ts │
│ └── WorkflowEditor.tsx │ └── 迁移工具 │
├─────────────────────────────┼───────────────────────────────┤
│ Agent C: 加密增强 │ 完成后合并 → 文档更新 → 推送 │
│ ├── secure-storage.ts │ ├── docs/SYSTEM_ANALYSIS.md │
│ ├── secure_storage.rs │ ├── PROGRESS.md │
│ └── WSS 配置 │ └── git commit + push │
└─────────────────────────────┴───────────────────────────────┘
```
| 任务 | 文件 | 工作量 | 代理 |
|------|------|--------|------|
| 创建 `safeJsonParse<T>()` | `lib/json-utils.ts` | 4h | A |
| 替换不安全 JSON.parse | `HandParamsForm.tsx`, `WorkflowEditor.tsx` | 3h | A |
| Token 迁移到 secure-storage | `gateway-client.ts`, `gatewayStore.ts` | 6h | B |
| Ed25519 密钥加密 | `secure-storage.ts`, `secure_storage.rs` | 4h | C |
| 添加 WSS 配置 | `gateway-client.ts` | 2h | C |
**完成后同步**:
```bash
# 1. 更新文档
git add docs/SYSTEM_ANALYSIS.md PROGRESS.md
git commit -m "docs: update Phase 9 security hardening progress"
git push origin main
# 2. 代码提交
git add . && git commit -m "security(phase-9): complete security hardening
- Add safeJsonParse utility with schema validation
- Migrate tokens to OS keyring storage
- Add Ed25519 key encryption at rest
- Enable WSS configuration option
Co-Authored-By: Claude <noreply@anthropic.com>"
git push origin main
```
**验收标准**:
- [ ] 所有 JSON.parse 有 try-catch 保护
- [ ] Token 存储在 OS keyring
- [ ] TypeScript 编译通过
- [ ] 现有测试通过
- [ ] **文档已更新并推送**
---
### Phase 10: 类型安全强化 (1 周) - 3 代理并行
**目标**: 减少 `any` 使用,提升类型安全
#### 并行执行架构
```
┌─────────────────────────────────────────────────────────────┐
│ Agent A: API 类型 │ Agent B: Store 类型 │
│ ├── types/api-responses.ts │ ├── store/gatewayStore.ts │
│ ├── types/errors.ts │ └── 35 处 any 替换 │
│ └── 所有 API 响应类型化 │ │
├─────────────────────────────┼───────────────────────────────┤
│ Agent C: Client 类型 │ 完成后 → 统计 any 减少 → 推送 │
│ ├── lib/gateway-client.ts │ grep -r ": any" | wc -l │
│ └── 12 处 any 替换 │ git commit + push │
└─────────────────────────────┴───────────────────────────────┘
```
| 任务 | 文件 | 工作量 | 代理 |
|------|------|--------|------|
| 创建 API 响应类型 | `types/api-responses.ts` | 4h | A |
| 创建错误类型层级 | `types/errors.ts` | 2h | A |
| 替换 gatewayStore any | `store/gatewayStore.ts` (35处) | 8h | B |
| 替换 gateway-client any | `lib/gateway-client.ts` (12处) | 4h | C |
**完成后同步**:
```bash
# 统计并提交
echo "## Phase 10 类型安全 (完成)" >> docs/SYSTEM_ANALYSIS.md
git add . && git commit -m "refactor(phase-10): reduce any usage by 50%" && git push
```
**验收标准**:
- [ ] `any` 使用减少 50% (从 60+ 降到 30)
- [ ] 所有 API 响应有类型定义
- [ ] TypeScript strict mode 通过
- [ ] **文档已更新并推送**
---
### Phase 11: Store 重构 (2 周) - 分步并行
**目标**: 分解巨型 gatewayStore (1500+ 行)
**目标架构**:
```
gatewayStore (协调器, <100 行)
├── connectionStore (WebSocket, 认证, ~200 行)
├── agentStore (分身, 配置文件, ~200 行)
├── handStore (Hands, 触发器, ~200 行)
├── workflowStore (工作流, 执行历史, ~200 行)
└── configStore (设置, 工作区, ~200 行)
```
#### 分步并行执行
```
Step 1 (阻塞): 创建所有 store 接口定义 (1 天)
Step 2 (并行): 同时提取 connectionStore, agentStore, handStore (3 天)
Step 3 (并行): 同时提取 workflowStore, configStore (2 天)
Step 4 (阻塞): 创建协调层 + 更新组件导入 (3 天)
Step 5 (同步): 测试 + 文档更新 + 推送 (1 天)
```
| 任务 | 工作量 | 执行方式 |
|------|--------|----------|
| 创建 store 接口定义 | 1 天 | 阻塞 |
| 提取 connectionStore | 3 天 | 并行 A |
| 提取 agentStore | 3 天 | 并行 B |
| 提取 handStore | 3 天 | 并行 C |
| 提取 workflowStore | 2 天 | 并行 A |
| 提取 configStore | 2 天 | 并行 B |
| 创建协调层 + 组件更新 | 3 天 | 阻塞 |
**完成后同步**:
```bash
git add . && git commit -m "refactor(phase-11): decompose gatewayStore
- Extract connectionStore (WebSocket, auth)
- Extract agentStore (clones, profiles)
- Extract handStore (hands, triggers)
- Extract workflowStore (workflows, runs)
- Extract configStore (settings, workspace)
- Add coordinator layer
Each store now < 300 lines with clear separation of concerns.
Co-Authored-By: Claude <noreply@anthropic.com>"
git push origin main
```
**验收标准**:
- [ ] 每个 store < 300
- [ ] 清晰的关注点分离
- [ ] 所有组件正常工作
- [ ] **文档已更新并推送**
---
### Phase 12: 性能优化 (1 周) - 2 代理并行
**目标**: 优化消息处理和渲染
#### 并行执行架构
```
┌─────────────────────────────────────────────────────────────┐
│ Agent A: 消息渲染优化 │ Agent B: WebSocket 优化 │
│ ├── ChatArea.tsx 虚拟化 │ ├── gateway-client.ts │
│ ├── chatStore.ts 分页 │ ├── 消息批处理 │
│ └── lib/message-cache.ts │ └── 节流/防抖 │
└─────────────────────────────┴───────────────────────────────┘
```
| 任务 | 文件 | 工作量 | 代理 |
|------|------|--------|------|
| 实现消息虚拟化 | `ChatArea.tsx` | 8h | A |
| 添加消息分页 | `chatStore.ts` | 6h | A |
| 实现 LRU 消息缓存 | `lib/message-cache.ts` | 4h | A |
| WebSocket 消息批处理 | `gateway-client.ts` | 4h | B |
**完成后同步**:
```bash
git add . && git commit -m "perf(phase-12): optimize message handling
- Add message virtualization for long conversations
- Implement message pagination in chatStore
- Add LRU cache for rendered messages
- Add WebSocket message batching
Handles 10k+ messages without performance degradation.
Co-Authored-By: Claude <noreply@anthropic.com>"
git push origin main
```
**验收标准**:
- [ ] 支持 10,000+ 消息无性能下降
- [ ] 内存使用保持稳定
- [ ] 滚动流畅
- [ ] **文档已更新并推送**
---
### Phase 13: 测试覆盖 (1 周) - 3 代理并行
**目标**: 建立完整测试体系达到 80% 覆盖率
#### 并行执行架构
```
┌─────────────────────────────────────────────────────────────┐
│ Agent A: 核心模块测试 │ Agent B: 工具模块测试 │
│ ├── gateway-client.test.ts │ ├── secure-storage.test.ts │
│ ├── 连接生命周期测试 │ ├── toml-utils.test.ts │
│ └── 消息帧解析测试 │ └── json-utils.test.ts │
├─────────────────────────────┼───────────────────────────────┤
│ Agent C: 集成测试 │ 完成后 → 覆盖率报告 → 推送 │
│ ├── chat-flow.test.ts │ pnpm vitest --coverage │
│ └── React 组件测试 │ git commit + push │
└─────────────────────────────┴───────────────────────────────┘
```
| 任务 | 文件 | 工作量 | 代理 |
|------|------|--------|------|
| gateway-client 单元测试 | `tests/desktop/gateway-client.test.ts` | 6h | A |
| secure-storage 单元测试 | `tests/desktop/secure-storage.test.ts` | 2h | B |
| toml-utils 单元测试 | `tests/desktop/toml-utils.test.ts` | 2h | B |
| json-utils 单元测试 | `tests/desktop/json-utils.test.ts` | 2h | B |
| 聊天流程集成测试 | `tests/desktop/integration/chat-flow.test.ts` | 4h | C |
| React 组件测试 | `tests/desktop/components/` | 8h | C |
**完成后同步**:
```bash
# 生成覆盖率报告
pnpm vitest run --coverage
git add . && git commit -m "test(phase-13): achieve 80% test coverage
- Add gateway-client unit tests
- Add secure-storage, toml-utils, json-utils tests
- Add chat flow integration tests
- Add React component tests
Coverage: 80%+ for core modules.
Co-Authored-By: Claude <noreply@anthropic.com>"
git push origin main
```
**验收标准**:
- [ ] 核心模块测试覆盖率 > 80%
- [ ] 关键用户流程有集成测试
- [ ] CI/CD 流水线通过
- [ ] **文档已更新并推送**
---
## 四、关键文件清单
### 需要修改的文件
| 优先级 | 文件路径 | 修改类型 |
|--------|----------|----------|
| P0 | `desktop/src/lib/gateway-client.ts` | 安全修复, 类型安全 |
| P0 | `desktop/src/store/gatewayStore.ts` | 重构分解, 类型安全 |
| P0 | `desktop/src/components/HandParamsForm.tsx` | JSON 解析安全 |
| P0 | `desktop/src/components/WorkflowEditor.tsx` | JSON 解析安全 |
| P1 | `desktop/src/store/chatStore.ts` | 性能优化 |
| P1 | `desktop/src/lib/secure-storage.ts` | 密钥加密 |
| P1 | `desktop/src-tauri/src/secure_storage.rs` | Rust 安全存储 |
### 需要创建的文件
| 文件路径 | 用途 |
|----------|------|
| `desktop/src/lib/json-utils.ts` | 安全 JSON 解析 |
| `desktop/src/types/api-responses.ts` | API 响应类型 |
| `desktop/src/types/errors.ts` | 错误类型定义 |
| `desktop/src/lib/message-cache.ts` | 消息 LRU 缓存 |
| `desktop/src/store/connectionStore.ts` | 连接状态管理 |
| `desktop/src/store/agentStore.ts` | Agent 管理 |
| `desktop/src/store/handStore.ts` | Hand 管理 |
| `desktop/src/store/workflowStore.ts` | 工作流管理 |
| `tests/desktop/gateway-client.test.ts` | 客户端测试 |
---
## 五、多代理并行执行策略
### 5.1 并行执行原则
**核心原则**: 独立任务并行执行,依赖任务顺序执行
```
┌─────────────────────────────────────────────────────────────────┐
│ 多代理并行执行架构 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Phase 9 (安全修复) - 并行执行: │
│ ├── Agent A: JSON 安全包装 + 输入验证 │
│ ├── Agent B: Token 迁移到 secure-storage │
│ └── Agent C: WSS 配置 + 密钥加密 │
│ │
│ Phase 10 (类型安全) - 并行执行: │
│ ├── Agent A: API 响应类型定义 │
│ ├── Agent B: gatewayStore any 替换 │
│ └── Agent C: gateway-client any 替换 │
│ │
│ Phase 11 (Store 重构) - 顺序执行 + 并行提取: │
│ ├── Step 1: 创建接口定义 (阻塞) │
│ ├── Step 2: 并行提取 connectionStore, agentStore, handStore │
│ ├── Step 3: 并行提取 workflowStore, configStore │
│ └── Step 4: 协调层 + 组件更新 │
│ │
│ Phase 12-13 (性能+测试) - 并行执行: │
│ ├── Agent A: 消息虚拟化 + 分页 │
│ ├── Agent B: WebSocket 批处理优化 │
│ └── Agent C: 测试编写 (与 A/B 同步) │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 5.2 代理分工
| 代理类型 | 职责 | 适用阶段 |
|----------|------|----------|
| **Security Engineer** | 安全修复、加密、Token 迁移 | Phase 9 |
| **Senior Developer** | 类型定义、Store 重构 | Phase 10-11 |
| **Frontend Developer** | UI 组件、性能优化 | Phase 12 |
| **Test Engineer** | 单元测试、集成测试 | Phase 13 |
| **Documentation Writer** | 文档更新、CHANGELOG | 所有阶段 |
### 5.3 每阶段完成后的同步动作
```bash
# 每个阶段完成后必须执行:
# 1. 更新相关文档
# - docs/SYSTEM_ANALYSIS.md (添加 Phase 进度)
# - docs/DEVELOPMENT.md (如有新开发指南)
# - PROGRESS.md (进度追踪)
# 2. 提交到仓库
git add .
git commit -m "feat(phase-N): 完成阶段任务描述
- 具体改动 1
- 具体改动 2
Co-Authored-By: Claude <noreply@anthropic.com>"
# 3. 推送到远程
git push origin main
```
### 5.4 文档更新检查清单
每个阶段完成后必须更新:
- [ ] `docs/SYSTEM_ANALYSIS.md` - 添加 Phase 完成记录
- [ ] `PROGRESS.md` - 更新进度百分比
- [ ] `CLAUDE.md` - 如有新的开发规范
- [ ] `README.md` - 如有新功能或依赖变更
---
## 六、资源需求 (多代理优化后)
### 时间估算对比
| 阶段 | 串行执行 | 3代理并行 | 节省 |
|------|----------|-----------|------|
| Phase 9 (安全) | 2 周 | **1 周** | 50% |
| Phase 10 (类型) | 2 周 | **1 周** | 50% |
| Phase 11 (Store重构) | 3 周 | **2 周** | 33% |
| Phase 12 (性能) | 2 周 | **1 周** | 50% |
| Phase 13 (测试) | 2 周 | **1 周** | 50% |
| **总计** | **11 周** | **6 周** | **45%** |
### 代理配置
| 阶段 | 所需代理 | 技能要求 |
|------|----------|----------|
| Phase 9 | 3 并行 | Security Engineer, Backend Dev, Rust Dev |
| Phase 10 | 3 并行 | TypeScript Expert, Frontend Dev |
| Phase 11 | 3 并行 → 顺序 | Senior Developer, State Management Expert |
| Phase 12 | 2 并行 | Frontend Dev, Performance Engineer |
| Phase 13 | 3 并行 | Test Engineer, Integration Specialist |
### 技能矩阵
| 技能 | Phase 9 | Phase 10 | Phase 11 | Phase 12 | Phase 13 |
|------|---------|----------|----------|----------|----------|
| TypeScript | 高 | 高 | 高 | 高 | 高 |
| React | 中 | 中 | 高 | 高 | 中 |
| Tauri/Rust | 高 | 低 | 低 | 低 | 低 |
| WebSocket | 高 | 中 | 中 | 高 | 中 |
| 状态管理 | 中 | 中 | 高 | 高 | 中 |
| 安全 | 高 | 中 | 中 | 低 | 中 |
| 测试 | 中 | 中 | 高 | 中 | 高 |
---
## 七、风险评估
| 风险 | 概率 | 影响 | 缓解措施 |
|------|------|------|----------|
| Store 重构破坏现有功能 | 中 | 高 | 重构前完善测试覆盖 |
| 持久化迁移丢失数据 | 低 | 严重 | 迁移工具, 回滚能力 |
| ID 标准化破坏 API 通信 | 中 | 高 | 集成测试验证 |
| 性能优化引入新 bug | 中 | 中 | 渐进式发布, 功能开关 |
---
## 七、成功指标
### Phase 9-10 指标
- [ ] 零安全漏洞 (静态分析)
- [ ] `any` 使用减少 50%
- [ ] 所有 Token 在安全存储中
### Phase 11 指标
- [ ] 所有 store < 300
- [ ] 清晰的关注点分离
- [ ] 持久化策略一致
### Phase 12-13 指标
- [ ] 10k+ 消息无性能下降
- [ ] UI 响应时间 < 100ms
- [ ] 测试覆盖率 > 80%
---
## 八、验证计划
### 自动化验证
```bash
# TypeScript 类型检查
pnpm tsc --noEmit
# 单元测试
pnpm vitest run
# 安全审计
pnpm audit
```
### 手动验证
1. 连接 OpenFang (端口 50051)
2. 发送消息并验证流式返回
3. 触发 Hand 并验证执行
4. 保存配置并验证持久化
5. 测试长对话性能 (>1000 消息)
---
## 九、执行时间表 (6 周计划)
```
周次 Phase 任务 代理数 交付物
─────────────────────────────────────────────────────────────────
W1 Phase 9 安全加固 3 并行 安全修复完成 + 文档
W2 Phase 10 类型安全强化 3 并行 类型定义 + any 减少 50%
W3-4 Phase 11 Store 重构 3 → 顺序 5 个子 Store + 协调层
W5 Phase 12 性能优化 2 并行 消息虚拟化 + 批处理
W6 Phase 13 测试覆盖 3 并行 80% 覆盖率 + CI 通过
─────────────────────────────────────────────────────────────────
完成 全部 Phase 9-13 文档更新 + 推送
```
---
*计划创建: 2026-03-15*
*多代理并行执行: 3 代理同时工作*
*预计完成: 6 周 (从 11 周优化 45%)*
*每阶段完成后: 文档更新 + Git 推送*