# 海洋项目管理系统 - 前端技术架构文档

## 1. 前端技术栈

### 1.1 核心框架
- **React 18**: 用于构建用户界面的JavaScript库
- **React Router 6**: 客户端路由管理
- **Vite**: 现代化的前端构建工具（替代Create React App）

### 1.2 UI组件库
- **Ant Design 5**: 企业级UI组件库
- **@ant-design/icons**: Ant Design图标库

### 1.3 HTTP客户端
- **Axios**: HTTP请求库

### 1.4 状态管理
- **React Context API**: 轻量级状态管理
- **useReducer Hook**: 复杂状态逻辑

### 1.5 表单处理
- **Ant Design Form**: 表单组件和验证
- **react-hook-form**: 表单状态管理（可选）

### 1.6 工具库
- **dayjs**: 日期处理（轻量级替代moment.js）
- **lodash**: 工具函数库
- **classnames**: 条件类名处理

### 1.7 开发工具
- **ESLint**: 代码质量检查
- **Prettier**: 代码格式化
- **Vitest**: 单元测试框架
- **React Testing Library**: 组件测试
- **TypeScript**: 类型检查（可选，当前使用JavaScript）

### 1.8 构建和部署
- **Vite**: 开发服务器和构建工具
- **Docker**: 容器化部署（生产环境）

## 2. 前端目录结构

```
frontend/
├── src/                          # 源代码目录
│   ├── assets/                   # 静态资源
│   │   ├── images/              # 图片
│   │   ├── fonts/               # 字体文件
│   │   └── styles/              # 全局样式
│   │       ├── global.css       # 全局CSS
│   │       ├── variables.css    # CSS变量
│   │       └── mixins.css        # CSS mixins
│   ├── components/              # 可复用组件
│   │   ├── Layout/              # 布局组件
│   │   │   ├── Layout.jsx       # 主布局
│   │   │   ├── Header.jsx       # 顶部导航
│   │   │   └── Sidebar.jsx      # 侧边栏
│   │   ├── Common/              # 通用组件
│   │   │   ├── Button.jsx       # 按钮组件
│   │   │   ├── Input.jsx        # 输入框组件
│   │   │   ├── Select.jsx       # 选择框组件
│   │   │   ├── Table.jsx        # 表格组件
│   │   │   ├── Modal.jsx        # 弹窗组件
│   │   │   ├── Form.jsx         # 表单组件
│   │   │   ├── Card.jsx         # 卡片组件
│   │   │   └── Tag.jsx          # 标签组件
│   │   ├── Business/            # 业务组件
│   │   │   ├── ProjectCard.jsx  # 项目卡片
│   │   │   ├── StatCard.jsx     # 统计卡片
│   │   │   └── UserAvatar.jsx   # 用户头像
│   │   └── index.js             # 组件导出
│   ├── pages/                    # 页面组件
│   │   ├── Login/               # 登录页
│   │   │   └── Login.jsx
│   │   ├── Dashboard/           # 仪表盘
│   │   │   └── Dashboard.jsx
│   │   ├── Projects/            # 项目管理
│   │   │   ├── ProjectList.jsx  # 项目列表
│   │   │   ├── ProjectForm.jsx  # 项目表单
│   │   │   ├── ProjectDetail.jsx # 项目详情
│   │   │   └── ProjectStatistics.jsx # 项目统计
│   │   ├── Users/                # 用户管理（仅管理员）
│   │   │   ├── UserList.jsx     # 用户列表
│   │   │   ├── UserForm.jsx     # 用户表单
│   │   │   └── UserResetPassword.jsx # 重置密码
│   │   └── Statistics/           # 统计分析
│   │       └── Statistics.jsx
│   ├── contexts/                 # Context上下文
│   │   ├── AuthContext.jsx      # 认证上下文
│   │   └── ThemeContext.jsx     # 主题上下文（可选）
│   ├── hooks/                    # 自定义Hooks
│   │   ├── useAuth.js           # 认证Hook
│   │   ├── useApi.js            # API调用Hook
│   │   ├── usePermission.js     # 权限检查Hook
│   │   ├── useTable.js          # 表格Hook
│   │   ├── useForm.js           # 表单Hook
│   │   └── useDebounce.js       # 防抖Hook
│   ├── services/                 # API服务
│   │   ├── api.js               # Axios配置
│   │   ├── auth.js              # 认证API
│   │   ├── user.js              # 用户API
│   │   ├── project.js           # 项目API
│   │   └── statistics.js        # 统计API
│   ├── utils/                    # 工具函数
│   │   ├── request.js           # 请求封装
│   │   ├── storage.js           # 本地存储
│   │   ├── auth.js              # 认证工具
│   │   ├── format.js            # 格式化函数
│   │   ├── validation.js        # 验证函数
│   │   └── constants.js         # 常量定义
│   ├── config/                   # 配置文件
│   │   ├── routes.js            # 路由配置
│   │   ├── menu.js              # 菜单配置
│   │   ├── colors.js            # 颜色配置
│   │   └── app.config.js        # 应用配置
│   ├── router/                   # 路由相关
│   │   ├── index.jsx            # 路由配置
│   │   ├── PrivateRoute.jsx     # 路由守卫
│   │   └── routes.js            # 路由定义
│   ├── styles/                   # 样式文件
│   │   └── index.css            # 主样式文件
│   ├── App.jsx                   # 根组件
│   └── main.jsx                  # 应用入口
├── tests/                        # 测试目录
│   ├── components/              # 组件测试
│   ├── pages/                   # 页面测试
│   ├── hooks/                   # Hooks测试
│   └── utils/                   # 工具测试
├── public/                       # 公共资源
│   ├── favicon.ico              # 网站图标
│   ├── logo.png                 # Logo
│   └── robots.txt               # 爬虫配置
├── docs/                         # 前端文档
│   ├── frontend-architecture.md  # 前端技术架构（本文档）
│   ├── component-design.md      # 组件设计文档
│   ├── api-service.md           # API服务封装
│   ├── state-management.md      # 状态管理设计
│   ├── routing-design.md        # 路由设计文档
│   └── development-guide.md      # 开发指南
├── .env                          # 环境变量
├── .env.development              # 开发环境变量
├── .env.production               # 生产环境变量
├── .eslintrc.js                 # ESLint配置
├── .prettierrc                  # Prettier配置
├── package.json                  # 项目依赖
├── vite.config.js               # Vite配置
├── index.html                   # HTML模板
├── WORKSTANDARDS.md             # 前端工作规范
└── README.md                    # 前端说明文档
```

## 3. 组件架构

### 3.1 组件层级

```
App
├── AuthProvider (认证上下文)
├── Router (路由)
│   ├── PrivateRoute (路由守卫)
│   ├── Login (登录页)
│   └── Layout (主布局)
│       ├── Header (顶部导航)
│       ├── Sidebar (侧边栏)
│       └── Content (内容区)
│           ├── Dashboard (仪表盘)
│           ├── ProjectList (项目列表)
│           ├── ProjectForm (项目表单)
│           ├── ProjectDetail (项目详情)
│           ├── UserList (用户列表)
│           ├── UserForm (用户表单)
│           └── Statistics (统计页)
```

### 3.2 组件设计原则

#### 3.2.1 单一职责原则
- 每个组件只负责一个功能
- 避免组件过大，合理拆分

#### 3.2.2 组件复用性
- 提取可复用的通用组件到 `components/Common/`
- 提取业务相关组件到 `components/Business/`

#### 3.2.3 组件分类
- **布局组件**: Layout, Header, Sidebar
- **通用组件**: Button, Input, Form, Modal, Table
- **业务组件**: ProjectCard, StatCard, UserAvatar
- **页面组件**: Login, Dashboard, ProjectList等

#### 3.2.4 组件Props规范
```jsx
// 推荐的Props定义方式
const MyComponent = ({
  title,            // 必填props
  value,            // 可选props
  onChange,         // 事件回调
  className,         // 样式类名
  style,            // 内联样式
  children,         // 子元素
}) => {
  return <div>{title}</div>;
};

MyComponent.propTypes = {
  title: PropTypes.string.isRequired,
  value: PropTypes.string,
  onChange: PropTypes.func,
  className: PropTypes.string,
  style: PropTypes.object,
  children: PropTypes.node,
};

MyComponent.defaultProps = {
  value: '',
  onChange: () => {},
  className: '',
  style: {},
};
```

## 4. 状态管理

### 4.1 Context API方案

#### 4.1.1 AuthContext（认证上下文）
```javascript
// contexts/AuthContext.jsx
const AuthContext = createContext();

export const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(null);
  const [token, setToken] = useState(null);
  const [loading, setLoading] = useState(true);

  // 登录
  const login = async (username, password) => {
    // 登录逻辑
  };

  // 登出
  const logout = () => {
    // 登出逻辑
  };

  // 检查登录状态
  const checkAuth = async () => {
    // 检查逻辑
  };

  return (
    <AuthContext.Provider
      value={{
        user,
        token,
        loading,
        login,
        logout,
        checkAuth,
        isAuthenticated: !!user,
      }}
    >
      {children}
    </AuthContext.Provider>
  );
};
```

#### 4.1.2 ThemeContext（主题上下文，可选）
```javascript
// contexts/ThemeContext.jsx
const ThemeContext = createContext();

export const ThemeProvider = ({ children }) => {
  const [theme, setTheme] = useState('light');

  const toggleTheme = () => {
    setTheme(prev => prev === 'light' ? 'dark' : 'light');
  };

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
};
```

### 4.2 本地状态管理
- 使用 `useState` 管理组件内部状态
- 使用 `useReducer` 管理复杂的状态逻辑

### 4.3 表单状态管理
- 使用 Ant Design Form 组件
- 使用 `react-hook-form`（可选）

## 5. 路由设计

### 5.1 路由配置

```javascript
// router/routes.js
const routes = [
  {
    path: '/login',
    element: <Login />,
    meta: { title: '登录', requiresAuth: false },
  },
  {
    path: '/',
    element: <Layout />,
    meta: { title: '主页', requiresAuth: true },
    children: [
      {
        path: '/dashboard',
        element: <Dashboard />,
        meta: { title: '仪表盘', icon: 'DashboardOutlined' },
      },
      {
        path: '/projects',
        element: <ProjectList />,
        meta: { title: '项目管理', icon: 'FileTextOutlined' },
      },
      {
        path: '/projects/create',
        element: <ProjectForm />,
        meta: { title: '创建项目' },
      },
      {
        path: '/projects/:id',
        element: <ProjectDetail />,
        meta: { title: '项目详情' },
      },
      {
        path: '/projects/:id/edit',
        element: <ProjectForm />,
        meta: { title: '编辑项目' },
      },
      {
        path: '/users',
        element: <UserList />,
        meta: { title: '用户管理', icon: 'UserOutlined', requiresRole: ['admin'] },
      },
      {
        path: '/users/create',
        element: <UserForm />,
        meta: { title: '创建用户', requiresRole: ['admin'] },
      },
      {
        path: '/statistics',
        element: <Statistics />,
        meta: { title: '统计分析', icon: 'BarChartOutlined' },
      },
    ],
  },
];
```

### 5.2 路由守卫

```javascript
// router/PrivateRoute.jsx
const PrivateRoute = ({ children, requiresAuth, requiresRole }) => {
  const { isAuthenticated, user } = useAuth();
  const navigate = useNavigate();

  if (requiresAuth && !isAuthenticated) {
    return <Navigate to="/login" replace />;
  }

  if (requiresRole && !requiresRole.includes(user?.role)) {
    return <Navigate to="/403" replace />;
  }

  return children;
};
```

## 6. API服务封装

### 6.1 Axios配置

```javascript
// services/api.js
import axios from 'axios';
import { message } from 'antd';

const api = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL || 'http://localhost:5000/api/v1',
  timeout: 10000,
  headers: {
    'Content-Type': 'application/json',
  },
});

// 请求拦截器
api.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem('token');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// 响应拦截器
api.interceptors.response.use(
  (response) => {
    return response.data;
  },
  (error) => {
    if (error.response) {
      const { status, data } = error.response;

      switch (status) {
        case 401:
          message.error('登录已过期，请重新登录');
          localStorage.removeItem('token');
          window.location.href = '/login';
          break;
        case 403:
          message.error('权限不足');
          break;
        case 404:
          message.error('请求的资源不存在');
          break;
        case 500:
          message.error('服务器错误');
          break;
        default:
          message.error(data.message || '请求失败');
      }
    } else {
      message.error('网络错误，请检查网络连接');
    }

    return Promise.reject(error);
  }
);

export default api;
```

### 6.2 API模块化

```javascript
// services/project.js
import api from './api';

export const projectAPI = {
  // 获取项目列表
  getList: (params) => api.get('/projects', { params }),

  // 获取项目详情
  getDetail: (id) => api.get(`/projects/${id}`),

  // 创建项目
  create: (data) => api.post('/projects', data),

  // 更新项目
  update: (id, data) => api.put(`/projects/${id}`, data),

  // 删除项目
  delete: (id) => api.delete(`/projects/${id}`),

  // 获取统计信息
  getStatistics: (params) => api.get('/projects/statistics', { params }),

  // 获取分组统计
  getGroupStatistics: (params) => api.get('/projects/statistics/group', { params }),

  // 获取时间维度统计
  getTimelineStatistics: (params) => api.get('/projects/statistics/timeline', { params }),
};
```

## 7. 权限控制

### 7.1 路由级权限
- 使用 `PrivateRoute` 组件检查认证状态
- 使用 `requiresRole` 属性检查角色权限

### 7.2 组件级权限
```javascript
// hooks/usePermission.js
export const usePermission = () => {
  const { user } = useAuth();

  const hasRole = (roles) => {
    if (!user) return false;
    return roles.includes(user.role);
  };

  const canEdit = (resource, createdBy) => {
    if (!user) return false;
    if (user.role === 'admin') return true;
    if (user.role === 'market' && createdBy === user.id) return true;
    return false;
  };

  return { hasRole, canEdit };
};
```

### 7.3 按钮级权限
```javascript
// 组件中使用
const { hasRole } = usePermission();

{hasRole(['admin', 'market']) && (
  <Button type="primary">创建项目</Button>
)}
```

## 8. 性能优化

### 8.1 代码分割
```javascript
import { lazy, Suspense } from 'react';

const ProjectList = lazy(() => import('./pages/Projects/ProjectList'));
const ProjectDetail = lazy(() => import('./pages/Projects/ProjectDetail'));

<Suspense fallback={<Spin />}>
  <ProjectList />
</Suspense>
```

### 8.2 图片优化
- 使用懒加载
- 压缩图片文件
- 使用WebP格式

### 8.3 请求优化
- 防抖处理搜索请求
- 取消重复请求
- 使用缓存策略

### 8.4 渲染优化
- 使用 `React.memo` 避免不必要的重渲染
- 使用 `useMemo` 缓存计算结果
- 使用 `useCallback` 缓存函数引用

## 9. 前端安全

### 9.1 XSS防护
- React自动转义HTML
- 避免使用 `dangerouslySetInnerHTML`
- 输入验证和过滤

### 9.2 CSRF防护
- 使用Cookie SameSite属性
- 添加CSRF Token（可选）

### 9.3 敏感信息保护
- Token存储在LocalStorage（可改为HttpOnly Cookie）
- 不在URL中传递敏感信息
- 使用HTTPS（生产环境）

### 9.4 内容安全策略（CSP）
- 设置CSP头部
- 限制外部资源加载

## 10. 开发规范

### 10.1 代码风格
- 使用ESLint进行代码检查
- 使用Prettier进行代码格式化
- 遵循Airbnb JavaScript风格指南

### 10.2 命名规范
- 组件名使用PascalCase（如 `ProjectList`）
- 函数和变量使用camelCase（如 `getUserById`）
- 常量使用UPPER_SNAKE_CASE（如 `API_BASE_URL`）
- CSS类名使用kebab-case（如 `project-card`）

### 10.3 注释规范
```javascript
/**
 * 获取项目列表
 * @param {Object} params - 查询参数
 * @param {number} params.page - 页码
 * @param {number} params.pageSize - 每页数量
 * @returns {Promise} 项目列表数据
 */
const getProjectList = async (params) => {
  // 实现代码
};
```

### 10.4 Git提交规范
```
[frontend] feat: 添加项目列表页面
[frontend] fix: 修复登录bug
[frontend] style: 优化代码格式
[frontend] refactor: 重构API服务
[frontend] test: 添加组件测试
[frontend] docs: 更新文档
[frontend] chore: 更新依赖
```

## 11. 测试策略

### 11.1 单元测试
- 测试工具函数和自定义Hooks
- 使用Vitest测试框架

### 11.2 组件测试
- 测试组件渲染和交互
- 使用React Testing Library

### 11.3 集成测试
- 测试页面和路由
- 测试API调用

### 11.4 E2E测试（可选）
- 测试完整用户流程
- 使用Playwright

## 12. 部署方案

### 12.1 开发环境
```bash
npm run dev
# 访问 http://localhost:3000
```

### 12.2 生产构建
```bash
npm run build
# 生成 dist 目录
```

### 12.3 Docker部署
```dockerfile
# Dockerfile
FROM node:18-alpine as builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
```

### 12.4 Nginx配置
```nginx
server {
  listen 80;
  server_name localhost;

  location / {
    root /usr/share/nginx/html;
    index index.html;
    try_files $uri $uri/ /index.html;
  }

  location /api {
    proxy_pass http://backend:5000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
  }
}
```

## 13. 相关文档

- [组件设计文档](component-design.md) - 详细的组件设计规范
- [API服务封装](api-service.md) - API服务封装详解
- [状态管理设计](state-management.md) - 状态管理方案详解
- [路由设计文档](routing-design.md) - 路由设计详解
- [开发指南](development-guide.md) - 前端开发指南

---

**文档维护**: 前端程序员
**文档类型**: 前端技术架构文档
**最后更新**: 2026-01-25
