# @peace/template_front_client > 基于 React.18 + Vite.4 预置 Antd.5 的客户端(web) ## 简洁 本项目以核心包`@peace/react_client`封装服务内容。 以`服务端渲染(SSR)`为核心,提供日常工作所需的`变量配置`、`路由配置`、`跨平台数据请求`、`统一资源管理`、`工具函数预置`等相关内容。 ## 使用 > 使用前可参阅下方 `目录结构` 了解项目结构 ### 启动服务 确保 Node.js 和 npm 已安装。 ```bash npm start ``` > 建议使用 vscode 的 `运行和调试`(F5)快捷键启动服务,更可方便配置环境变量 ### 项目配置 项目配置文件位于 `config.cjs` 文件,可根据实际需求进行配置。 配置内容均已在文件中预置和注释说明,可根据实际需求进行修改。 - 关键配置(*) - vite:Vite 相关配置 https://vitejs.cn/vite5-cn/config/ - envPrefix:环境变量前缀,此前缀的环境变量将会被注入到 `window.env` 中 - server: - alias: 别名配置(框架预置了一下别名以供调用) - @u:工具集目录 - @comps:公共组件目录 - @assets:静态资源目录 ### 功能模块编写`sections` > 模块化设计,以功能模块为单位进行编写。 模块应该在 `client/src/sections` 目录下创建 目录结构如下: ``` 模块 ├── actions // Redux actions ├── components // 组件 ├── container // 容器 ├── index.js // 模块入口文件 └── router.js // [!]路由文件 ``` #### 路由配置`router.js` 路由文件以对象形式配置,兼顾路由导航及 Menu 主菜单、面包屑等信息配置 .eg ```javascript import { HomeOutlined, ApartmentOutlined, } from "@ant-design/icons"; import Index from "./container"; export default { type: "inner", // 路由类型 ('inner' 出现在 layout 布局内 | 'outer' layout 布局外,内容占满页面全部) route: { key: "home", // 路由 key path: "home", // 路由 component: Index, // 路由对应组件 label: "Home", // 导航栏或面包屑显示的名称 icon: , // 导航栏图标 nav: true, // 是否显示在左侧 Sider - Menu 导航栏 auth: ["admin"], // 访问权限 key children: [ // 子路由 // { ... 重复以上配置 }, ], }, }; ``` #### Redux `actions` 框架使用 Redux 进行状态管理,以 `actions` 为基础,提供 `reducer` 和 `store` 等内容。 对于数据请求内容,根据需要可编写 `action` 以存储‘状态’并使用 - 编写`action` ```javascript // actions/auth.js import { basicAction, apiTable } from "@u" const login = basicAction.post('/login', { reducerName: "user" // 存储状态的 reducer 名称 }); export default { login } ``` `basicAction` 为框架多次封装的 `action`(基于`@peace/react_client - request`,更多参数可参考相关目录),基于此方法可免于编写`reducer` 所有 `action` 需在 入口文件`index.js` 中暴露,以集中至 `state.global` 方便调用 ```javascript // actions/index.js import actions from "./auth"; export default { ...actions } ``` - 使用`action` 在 `container` 或 `components` 等地方使用 `action`时: ```javascript import { useDispatch, useSelector } from "react-redux"; export default function login (){ const dispatch = useDispatch(); // 获取 dispatch const actions = useSelector(state => state.global.actions); // 获取所有 actions // 使用 useSelector 可以获取所有 actions 的值 dispatch(actions.login({ // 调用 action body: {}, })).then(res => { const { success, data } = res.payload; // 从 payload 中获取数据 /** * success: true, // 请求是否成功 * data: {} // 请求返回的数据 */ }); } ``` 除 `dispatch(action()).then()` 获取 `action` 的返回值外,还可以以一下方式获取: ```javascript import { useDispatch, useSelector } from "react-redux"; export default function login (){ const dispatch = useDispatch(); const actions = useSelector(state => state.global.actions); dispatch(actions.login()) // ... const { success, data, error, loading } = useSelector(state => state.user); // state.user 是因为 action 定义了 reducerName = "user" // 返回值包括 success, data, error, loading } ``` #### 组件 `components` - 定义: - 组件是一个 UI 逻辑的最小单位,通常专注于如何呈现内容(即外观)。 - 无状态组件(Stateless Components)较常见,它们通常只接收 props,不直接管理状态。 #### 容器 `container` - 定义 - 容器是负责 业务逻辑和数据管理 的组件,通常连接应用的状态(如 Redux store)并将数据传递给组件。 - 容器通常管理状态、数据流、API 调用等复杂逻辑。 #### 模块入口`index.js` 模块入口文件需暴露指定内容以便于`Layout`进行渲染 ```javascript import route from './router' import actions from './actions' export default { route: route, actions: actions, } ``` #### 模块使用 模块内容需在 `client/src/app.jsx` 中引用并挂载至 `Layout` 组件 ```javascript // ... import Auth from "./sections/auth"; // ... ``` ### 工具集 `utils` 工具集在 `client/src/utils` 目录下; 工具集内提供了一些常用的工具函数,如 `api.js`、`parseProcessData.js` 等。 - `api.js`:提供了 api 路由 map,可根据实际需求进行配置并多处使用;一般 action 中建议直接写入 api 路由,以方便管理。 - `parseProcessData.js`:提供了项企表单数据解析能力。 - `index.js`:工具集入口文件,暴露所有工具函数。 - `apiRequest`: 在入口文件中暴露了 `apiRequest` 方法,适用于本项目的二次封装,用于请求数据,可根据实际需求进行配置。 ### 构建 项目提供了 Docker 构建配置文件 `Dockerfile` 和 Jenkins 构建配置文件 `jenkinsfile`,根据实际需求进行修改配置。 ## 核心包 `@peace/react_client` 核心包除提供封装的核心内容外,还暴露了一些常用功能: ### `request` 基于 `superagent` 封装的请求方法,使用方式上更接近直觉; class 构造,使用前需实例化 - 实例化 ```javascript import { message } from 'antd' import { request } from "@peace/react_client"; const apiRequest = new request({ proxy: '/_api', // 代理前缀 与 `config.cjs` 中的 `proxy` 保持一致 才可生效 userKey: 'user', // session 中的用户键值,用于拼接 token,默认为 `user`,session中没有也不影响使用 message: message, // 全局提示组件,用于提示请求结果(如果需要) interceptor: (res, err) => { // 拦截器,用于处理请求结果,两参数互斥出现 if (err) { if (err?.status === 401) { window.location.replace('/signin'); sessionStorage.clear() } return err } return res } }) ``` - 使用 ```javascript apiRequest[method](route,{ body: {}, // 请求体 query: {}, // 请求参数 params: {}, // 请求路径参数 header: {}, // 请求头 timeout: 3000, // 超时时间 tipSuccess:'', // 成功提示 tipFail:'', // 失败提示 tip:'', // 提示(成功 & 失败) }).then(res => { const { success, data } = res; // 请求结果 }) ``` ### Redux 相关 #### `basicAction` 构造 action 的主要工具,可直接使用,无需编写 reducer;可参考目录 'Redux `actions`'; #### `basicReducer` 聚合项目中所有的 action,统一生成匹配 reducer [redux 切片]的工具; #### `createSlice` 创建一个 redux 切片(reducer); 导出自 `@reduxjs/toolkit`,Redux 官方包; #### `createStore` 创建一个 redux store; 导出自 `@reduxjs/toolkit`,Redux 官方包; ## 目录结构 ``` ├── .vscode // vscode 相关配置 | ├── launch.json // 启动命令配置,包含环境变量 | └── settings.json ├── client │ ├── assets // 静态资源文件夹 │ ├── entry // 服务渲染入口 │ ├── src // 源码 │ │ ├── components // 公共组件 │ │ | ├── errorBoundary.jsx // [预置]错误拦截组件 │ │ | ├── index.js // 入口文件 │ │ | └── upload.jsx // [预置]上传组件 │ │ ├── layout // 布局 │ │ | ├── components // 布局组件 │ │ | ├── container // 容器 │ │ | ├── middleWare // │ │ | └── index.jsx // 入口文件 │ │ ├── sections // [!]功能模块 │ │ | └── auth // 认证模块 │ │ | ├── actions // Redux actions │ │ | ├── components // 组件 │ │ | ├── container // 容器 │ │ | ├── index.js // 模块入口文件 │ │ | └── router.js // [!]路由文件 │ │ ├── utils // 工具集 │ │ | ├── api.js // api 路由 map │ │ | ├── index.js // 入口文件 │ │ | └── parseProcessData.js // [预置]项企表单数据解析 │ │ ├── app.js // 次级入口 │ │ └── app.less // 全局样式 │ └── index.js // 项目入口 ├── server // ssr 服务端 │ ├── controllers // 控制器 │ ├── index.js // 入口文件 │ └── routes.js // 路由文件 ├── .editorconfig // 代码风格配置 ├── .gitignore // git 忽略配置 ├── .npmrc // npm 配置 ├── config.cjs // 项目配置 ├── Dockerfile // Docker 构建配置 ├── index.html // 模板文件 ├── jenkinsfile // Jenkins 构建配置 ├── package.json ├── README.md // 项目说明 ```