這是一個基于 React + TypeScript + Ant Design 開發的向明天系統前端項目。
git倉庫地址
技術棧
- React 19
- TypeScript
- Ant Design 5.x
- Redux Toolkit
- React Router
- Axios
- Less
環境要求
- Node.js (推薦使用最新LTS版本)
- npm 或 yarn
安裝步驟
- 克隆項目到本地
git clone [https://gitee.com/to-tomorrow-xmt/react.git]
- 進入項目目錄
cd remote-monitoring-system
- 安裝依賴
npm install
# 或使用 yarn
yarn install
開發環境運行
npm start
# 或使用 yarn
yarn start
項目將在開發模式下運行,訪問 http://localhost:3000 查看效果。
生產環境構建
npm run build
# 或使用 yarn
yarn build
構建后的文件將生成在 build
目錄中。
項目結構
src/├── api/ # API 接口定義├── assets/ # 靜態資源├── components/ # 公共組件├── pages/ # 頁面組件├── redux/ # Redux 狀態管理├── router/ # 路由配置├── styles/ # 全局樣式├── types/ # TypeScript 類型定義└── utils/ # 工具函數
主要功能
- 用戶認證與授權
- 數據可視化
- 系統設置
- 封裝接口請求數據
開發規范
- 使用 TypeScript 進行開發
- 遵循 ESLint 代碼規范
- 使用 Prettier 進行代碼格式化
- 組件命名采用 PascalCase
- 文件命名采用 kebab-case
接口配置文件
在 src/config
目錄下創建 api.config.ts
文件:
// src/config/api.config.ts
export const API_CONFIG = {baseURL: process.env.REACT_APP_API_URL,timeout: 10000,withCredentials: true,headers: {'Content-Type': 'application/json',},
};
跨域處理
開發環境跨域配置
在項目根目錄下的 craco.config.js
文件中配置開發環境代理:
// craco.config.js
module.exports = {devServer: {proxy: {'/api': {target: '',//真實地址changeOrigin: true,pathRewrite: {'^/api': '',},},},},
};
生產環境跨域處理
生產環境跨域需要在后端服務器進行配置,以下是常見的配置方式:
- Nginx 配置示例:
server {listen 80;server_name your-domain.com;location /api {proxy_pass http://backend-server;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;# 跨域配置add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';if ($request_method = 'OPTIONS') {add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';add_header 'Access-Control-Max-Age' 1728000;add_header 'Content-Type' 'text/plain charset=UTF-8';add_header 'Content-Length' 0;return 204;}}
}
- 后端服務器配置示例(以 Node.js Express 為例):
const express = require('express');
const cors = require('cors');
const app = express();app.use(cors({origin: process.env.REACT_APP_BASE_URL,methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],allowedHeaders: ['Content-Type', 'Authorization'],credentials: true
}));
請求配置
項目使用 Axios 進行 HTTP 請求,主要配置如下:
// 基礎配置
const baseURL = 'http://your-api-domain.com/api';
const timeout = 10000; // 請求超時時間// 請求攔截器
axios.interceptors.request.use((config) => {// 添加tokenconst token = localStorage.getItem('token');if (token) {config.headers.Authorization = `Bearer ${token}`;}return config;},(error) => {return Promise.reject(error);}
);// 響應攔截器
axios.interceptors.response.use((response) => {return response.data;},(error) => {// 處理錯誤響應if (error.response.status === 401) {// 處理未授權localStorage.removeItem('token');window.location.href = '/login';}return Promise.reject(error);}
);
請求方法示例
// GET 請求
const getData = async (params: any) => {try {const response = await axios.get('/endpoint', { params });return response;} catch (error) {console.error('請求失敗:', error);throw error;}
};// POST 請求
const postData = async (data: any) => {try {const response = await axios.post('/endpoint', data);return response;} catch (error) {console.error('請求失敗:', error);throw error;}
};// PUT 請求
const updateData = async (id: string, data: any) => {try {const response = await axios.put(`/endpoint/${id}`, data);return response;} catch (error) {console.error('請求失敗:', error);throw error;}
};// DELETE 請求
const deleteData = async (id: string) => {try {const response = await axios.delete(`/endpoint/${id}`);return response;} catch (error) {console.error('請求失敗:', error);throw error;}
};
錯誤處理
項目使用統一的錯誤處理機制:
- 網絡錯誤:顯示"網絡連接失敗,請檢查網絡設置"
- 401 未授權:自動跳轉到登錄頁面
- 403 禁止訪問:顯示"沒有權限訪問該資源"
- 404 資源不存在:顯示"請求的資源不存在"
- 500 服務器錯誤:顯示"服務器內部錯誤,請稍后重試"
請求封裝
建議將 API 請求封裝在 src/api
目錄下,按模塊組織:
src/api/├── auth.ts # 認證相關接口├── device.ts # 設備相關接口├── monitor.ts # 監控相關接口└── index.ts # 統一導出
權限路由說明
<!-- 路由格式 -->使用方式,登錄以后后端把這個數據放給角色,根據這個格式,把所有路徑路由配置放在這里,讀取的時候讓后臺判斷,返回那些路徑,與后端溝通好.<!-- 把路由配置放在這里 -->parentId: id;index: index;title:一級路由名稱icon:圖標 我用的是iconfont 的圖標 根據自己情況替換就行了;type: group;children: [ //子級路由index:index;title:二級路由名稱path:path;name:name;component:文件讀取路徑 讀取pages 文件 路徑// 看不明白的就把這里的路徑和pages 下的路徑對比一下就明白了menuType:menuType;meta: 路由原信息] ;"nav": [{"parentId": "1","index": "1","title": "首頁","icon": "icon-shouye","type": "group","children": [{"index": "1-1","title": "首頁","name": "home","path": "/home","component": "shouYe/index","menuType": 0,"meta": {"selectIndex": "1-1","check": true}}]},{"parentId": "2","index": "2","title": "設備管理","icon": "icon-shebei","type": "group","children": [{"index": "2-1","title": "設備列表","name": "shebei","path": "/shebei","component": "shebei/shebei","menuType": 0,"meta": {"selectIndex": "2-1","check": true}}]},{"parentId": "3","index": "3","title": "模塊管理","icon": "icon-mokuai","type": "group","children": [{"index": "3-1","title": "模塊列表","name": "mokuai","path": "/mokuai","component": "mokuai/Mokuai","menuType": 0,"meta": {"selectIndex": "3-1","check": true}}]},{"parentId": "4","index": "4","title": "標靶檢測","icon": "icon-mubiaobachang1","type": "group","children": [{"index": "4-1","title": "報警列表","name": "jingIndex","path": "/jingIndex","component": "biaoba/index","menuType": 0,"meta": {"selectIndex": "4-1","check": true}},{"index": "4-2","title": "標靶檢測","name": "biaoba","path": "/biaoba","component": "biaoba/biaoba","menuType": 0,"meta": {"selectIndex": "4-2","check": true}},{"index": "4-3","title": "標靶報警","name": "baojing","path": "/baojing","component": "biaoba/baojing","menuType": 0,"meta": {"selectIndex": "4-3","check": true}},{"index": "4-4","title": "報警等級","name": "dengji","path": "/dengji","component": "biaoba/dengji","menuType": 0,"meta": {"selectIndex": "4-4","check": true}}]}]