Files
2026-01-25 15:05:03 +08:00

19 KiB
Raw Permalink Blame History

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

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规范

// 推荐的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(认证上下文)

// 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(主题上下文,可选)

// 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 路由配置

// 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 路由守卫

// 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配置

// 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模块化

// 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 组件级权限

// 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 按钮级权限

// 组件中使用
const { hasRole } = usePermission();

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

8. 性能优化

8.1 代码分割

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 注释规范

/**
 * 获取项目列表
 * @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 开发环境

npm run dev
# 访问 http://localhost:3000

12.2 生产构建

npm run build
# 生成 dist 目录

12.3 Docker部署

# 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配置

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. 相关文档


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