从零开始搞后台管理系统(1)——shin-admin
shin 的读音是[ʃɪn],谐音就是行,寓意可行的后台管理系统,shin-admin 的特点是:
- 站在巨人的肩膀上,依托Umi 2、Dva 2、Ant Design 3和React 16.8搭建的定制化后台。
- 介于半成品和成品之间,有很强的可塑性,短期内你就能把控全局。
- 借助模板组件可快速交付90%以上的页面。
- 多样的权限粒度,大到菜单,小到接口。
- 容易扩展,例如引入统计用的图表或富文本编辑器等。
当然它还有一些不友好的地方:
- 大流程绝对能跑起来,但仍潜伏着很多细节BUG有待解决。
- 有一定的学习成本,需要学习Umi配置,Dva数据流方案,Ant Design组件以及React、ES6+等语法。
准备工作
1)安装
在将项目下载下来后,来到其根目录,运行安装命令,自动将依赖包下载到本地。
- $ npm install
2)启动
启动开发服务器,默认会进入登录页(下图),由于会调用本地的Mock数据,所以即使没有后端服务器,项目也能运行。若要与后端配合,可参考 shin-server。
- $ npm start
用户名密码可以随意输入,提交后进入系统主页,目前是空白的,可自定义。
3)构建
在开发完成后调用构建命令,可自动生成dist目录,将该目录上传到服务器上用于部署。
- $ npm run build
在 package.json 的 scripts 字段中,还提供了其他命令,例如 lint、test 等。
4)运行流程
管理系统运行的大致流程,如下图所示,其中账号的登录态认证,基于JWT的方式。
目录
- ├── shin-admin
- │ ├── docs ----------------------------------- 说明文档
- │ ├── mock ----------------------------------- MOCK 数据
- │ ├── src ------------------------------------ 源码
- │ ├───└─── api ------------------------------- 接口API声明
- │ ├───└─── assets ---------------------------- 静态资源
- │ ├───└─── components ------------------------ 全局通用组件
- │ └───└────└──── Common ---------------------- 功能组件
- │ └───└────└──── Layout ---------------------- 结构组件
- │ └───└──── layouts -------------------------- 页面整体结构
- │ └───└──── models --------------------------- 全局 model(数据处理)
- │ └───└──── pages ---------------------------- 页面
- │ └───└────└──── path ------------------------ 页面路径(任意名称)
- │ └───└────└────└──── index.js --------------- 视图逻辑
- │ └───└────└────└──── model.js --------------- 页面 model
- │ └───└──── services ------------------------- 与后端通信的服务(可选)
- │ └───└──── utils ---------------------------- 各类工具辅助代码
- │ └───└──── app.js --------------------------- 运行时配置,处理40X状态码
- │ └───└──── routes.js ------------------------ 路由
- │ └───└──── authority.js --------------------- 权限
- │ └───└──── global.less ---------------------- 全局样式
- │ ├── .env ----------------------------------- 环境变量
- │ ├── .umirc.js ------------------------------ umi 配置
- └───└── package.json --------------------------- 命令和依赖包
1)api
api目录下可包含多个文件,默认只有一个 index.js,声明了与后端通信的 API 地址,例如。
- export default {
- templateCreate: "template/create", //模板示例中的创建和编辑
- templateQuery: "template/query", //模板示例中的查询
- templateHandle: "template/handle", //模板示例中的数据处理
- }
2)components
功能组件包括重置密码、拖动列表、上传按钮和模板组件,具体用法可参考此处。
结构组件包括顶部导航、侧边菜单栏、面包屑导航和快速搜索,在上面的主页图中已体现。
3)models
model 文件是 Dva 中的概念,用于处理组件中的数据(下面是数据流向图),典型事例参考此处。
- app.model({
- namespace: 'app', //命名空间,同时也是他在全局 state 上的属性
- state: {}, //初始值
- //处理同步操作,唯一可以修改 state 的地方,由 action 触发
- reducers: {
- add(state, { payload: todo }) {
- return [...state, todo]; // 保存数据到 state
- },
- },
- //处理异步操作和业务逻辑(和服务器交互),不直接修改 state,由 action 触发
- effects: {
- *save({ payload: todo }, { put, call }) {
- // 调用 saveTodoToServer,成功后触发 `add` action 保存到 state
- yield call(saveTodoToServer, todo);
- yield put({ type: 'add', payload: todo });
- },
- },
- //用于订阅一个数据源,然后根据需要 dispatch 相应的 action
- subscriptions: {
- setup({ history, dispatch }) {
- // 监听 history 变化,当进入 `/` 时触发 `load` action
- return history.listen(({ pathname }) => {
- if (pathname === '/') {
- dispatch({ type: 'load' });
- }
- });
- },
- },
- });
4)pages
所有页面的逻辑都放在此目录下,例如访问 http://localhost:8000/template/list ,那么就需要先创建 template 目录,然后创建其子目录 list,即路径为 pages/template/list。
在子目录中会包含 index.js 和 model.js,偶尔也会创建 less 样式文件。
由于采用了 Dva 数据流方案,因此在 index.js 中就不能直接修改内部状态(state),只能 dispatch 相应的 action,然后在 model.js 文件中更新状态。
下面是 index.js 的一个示例,App 组件中的 id 参数是 model 文件中的状态,dispatch()函数是Dva的库函数,用于触发 action。
底部的 connect() 函数用于连接 model 和 component。app 是 model.js 文件中的命名空间,App 是组件名称。
- import React from 'react';
- import { connect } from 'dva';
- import { Button } from 'antd';
- const App = ({ id, dispatch }) => {
- const onCreate = () => {
- dispatch({
- type: 'app/save',
- payload: {
- id
- },
- });
- };
- return <Button type="primary" onClick={onCreate}>新建</Button>;
- };
- export default connect(data => data.app)(App);
5)services
用来与后端通信,但在使用过程中发现经常只是做一层中转,内部并没有很多特定的逻辑,例如下面的登录函数。
其实就是声明一个请求地址,要传递的数据以及请求方法。
- import request from '../utils/request';
- export async function login(data) {
- return request('/api/user/login', {
- method: 'POST',
- data,
- });
- }
完全可以提炼出来,直接在 model.js 文件中直接发起请求,例如先在 api 处声明好地址(代码中的 url 参数),redirect、get 和 post 是封装的三种请求方式。
- import { redirect, get, post } from 'utils/request';
- export default {
- namespace: 'template',
- state: {},
- effects: {
- //查询
- *query({ payload }, { call, put }) {
- const { url, params } = payload;
- const { data } = yield call(get, url, params);
- },
- //Excel导出
- *export({ payload }, { call, put }) {
- yield call(redirect, payload.url, payload.params);
- },
- //处理数据,增删改
- *handle({ payload }, { call, put, select }) {
- const { url, params } = payload;
- const { data } = yield call(post, url, params);
- },
- },
- };
6)utils
utils 目录中的文件如下:
- config.js:全局配置参数
- constants.js:全局常量
- menu.js:菜单处理
- request.js:基于 axios 封装的通信库
- tools.js:杂七杂八的工具函数
7)app.js
app.js 在处理各种异常响应时会给出不同的提示,在401时会跳转到登录页。
- export const dva = {
- config: {
- onError(error) {
- if (error.status) {
- switch (error.status) {
- case 401:
- window.location = '/login';
- break;
- case 403:
- message.error('403 : 没有权限');
- break;
- case 404:
- message.error('404 : 对象不存在');
- break;
- case 409:
- message.error('409 : 服务升级,请重新登录');
- break;
- case 504:
- message.error('504 : 网络有点问题');
- break;
- default:
- Modal.error({ content: `${error.status} : ${error.response.data.error}` });
- }
- } else {
- Modal.error({ content: error.message });
- }
- },
- },
- };
8)routes.js
routes.js会声明组件和路由之间的映射关系,其实 pages 目录下的各个页面就是一个个的组件。
- module.exports = [
- {
- path: '/',
- component: '../layouts/index', //component 相对于 src/pages 目录
- routes: [
- { path: '/', component: 'index' },
- { path: '/login', component: 'login/', exact: true },
- { path: '/template/list', component: 'template/list/', exact: true },
- { path: '/*', component: '404', exact: true },
- ]
- }
- ];
9)authority.js
authority.js 中的权限会形成一棵树形结构,当 type 为 1 时,会在左侧菜单栏中展示,为 2 时就仅做一个接口权限。图标的选择可参考此处。
- /**
- * 权限列表
- * @param id {string} 权限id
- * @param pid {string} 父级权限id
- * @param status {number} 是否开启 1 开启 2 关闭
- * @param type {string} 权限类型 1 菜单 2 接口
- * @param name {string} 权限名称
- * @param desc {string} 权限描述
- * @param routers {string} 权限相关路由
- * @param icon {string} 菜单图标
- */
- export default [
- {
- id: 'backend',
- pid: '',
- status: 1,
- type: 1,
- name: '管理后台',
- desc: '',
- routers: '/',
- icon: 'desktop',
- },
- {
- id: 'backend.template',
- pid: 'backend',
- status: 1,
- type: 1,
- name: '全局模板',
- desc: '',
- routers: '/template',
- icon: 'file-text',
- },
- {
- id: 'backend.template.list',
- pid: 'backend.template',
- status: 1,
- type: 1,
- name: '列表模板',
- desc: '',
- routers: '/template/list',
- }
- ]
10).umirc.js
在 .umirc.js 中可引入路由信息,配置路径别名,开启代理服务器。
当配置了路由别名时,就不需要写相对路径了,但是无法使用IDE工具的代码导航了。
- import request from 'utils/request';
搭建
1)常规流程
在 pages 下的 login 和 user 两个目录中,采用了常规的搭建流程。
- 在 index.js 文件中编写视图的各类逻辑,将几个特定组件抽象到当前的 components 子目录中。
- 在 model.js 文件中处理各类组件状态,并且引用 serveices 中声明的函数。
其实很多后台页面所需的状态(例如Loading、列表、数量等)和几个特定组件都差不多,例如过滤条件、列表、模态窗口等,没必要每次写页面都重新声明一下。
在此背景下,提炼出了通用的模板组件(用法文档),位于 components/Common 的 Template 和 Upload 两个目录中,效果如下面两张图所示。
2)高速流程
模板组件(用法文档)就是将一些页面交互和数据处理封装起来,调用的时候只需要定义各类参数,就能快速搭建出一套完整的逻辑,并且能大大减少BUG数量。
以往搭建下面这样的一张页面(包括列表、分页、创建、查询、模态窗口等部分),熟练的话也得两三个小时以上,而采用模板组件的话,最多半小时就能完成。
在 template 目录中演示了三种类型的模板页面:列表、表单和照片墙。
在 tool 目录中完成了对模板组件的实践。
3)开发步骤
- 在 pages 目录中创建页面模块,分别新建 index.js 和 model.js。
- 在 api 目录中声明路由或在 services 目录中创建通信服务。
- 如果需要新增菜单栏,得需要三步走。
- 在 src 目录的 routes.js 路由文件中声明路径。保证 path 唯一性,component以 ”/“ 结尾,默认取该文件夹下 index.js。
- 在 src 目录的 authority.js 文件中配置权限列表项,routes 属性的值对应上面的 component 属性, id 会与后端权限中间件调用的关键字保持一致。
- 在用户管理 -》 角色管理 -》角色列表中,为当前角色增加该菜单的访问权限,然后退出登录重进。
- 重启项目。
其他
1)MOCK数据
Umi 框架安装了第三方的Mock.js模拟请求数据甚至逻辑,能够让前端开发独立自主,不会被服务端的开发所阻塞。
若要关闭,只要在 .env 文件中添加 MOCK=none 或者在 start 命令中将其添加即可。
- MOCK=none umi dev
2)ESLint
在 .eslintrc 中修改默认的配置,无法生效,无奈只能在某个文件顶部显式地声明,以此规避ESLint默认的规则。
- /* eslint-disable */
从零开始搞后台管理系统(1)——shin-admin的更多相关文章
- 从零开始搞后台管理系统(2)——shin-server
shin 的读音是[ʃɪn],谐音就是行,寓意可行的后端系统服务,shin-server 的特点是: 站在巨人的肩膀上,依托KOA2.bunyan.Sequelize等优秀的框架和库所搭建的定制化 ...
- vue从入门到女装??:从零开始搭建后台管理系统(二)用vue-docute生成线上文档
教程 vue从入门到女装??:从零开始搭建后台管理系统(一)安装框架 一个系统开发完成了总要有操作说明手册,接口文档之类的东西吧?这种要全部纯手写就很麻烦了,可以借助一些插件,比如: vue-docu ...
- vue从入门到女装:从零开始搭建后台管理系统(一)安装框架
安装及运行都是基于node的,不会node的可以自行百度,网上教程很多,也不难 项目效果预览: demo1 demo2 源码下载 开始安装框架: vue ==>vue-cli安装 eleme ...
- ace后台管理系统扁平化框架
Bootstrap ACE后台管理界面模板(扁平化) 所属分类:后台模板 文件大小:1.22 MB 阅读:236697次 下载:55929次 来源:www.daimajiayuan.com 分享到:更 ...
- 从零开始编写自己的C#框架(8)——后台管理系统功能设计
还是老规矩先吐下槽,在规范的开发过程中,这个时候应该是编写总体设计(概要设计)的时候,不过对于中小型项目来说,过于规范的遵守软件工程,编写太多文档也会拉长进度,一般会将它与详细设计合并到一起来处理,所 ...
- Admin Panel – 非常漂亮的后台管理系统模板
网站或者应用系统的管理后台的设计虽然不像前台界面那样要求设计精美,但是也需要有清晰的管理模块划分,下面分享的这个后台管理模板的设计非常漂亮,特别是导航部分,头部还有未读的短消息和提醒的条数显示.赶紧下 ...
- admin快速搭建后台管理系统
一.基于admin后台管理系统的特点: 权限管理:权限管理是后台管理系统必不可少的部分,拥有权限管理,可以赋予用户增删改查表权限(可以分别赋予用户对不同的表有不同的操作权限): 前端样式少:后台管理主 ...
- django后台管理系统(admin)的简单使用
目录 django后台管理系统的使用 检查配置文件 检查根urls.py文件 启动项目,浏览器输入ip端口/admin 如: 127.0.0.1/8000/admin 回车 注册后台管理系统超级管理 ...
- 从零开始搭建vue+element-ui后台管理系统项目到上线
前言 之前有些过移动端的项目搭建的文章,感觉不写个pc端管理系统老感觉少了点什么,最近公司项目比较多,恰巧要做一个申报系统的后台管理系统,鉴于对vue技术栈比较熟悉,所以考虑还是使用vue技术栈来做: ...
随机推荐
- 客户端负载均衡Ribbon
客户端负载均衡Ribbon 一.Ribbon是什么 二.Ribbon实现客户端负载均衡 三.Ribbon负载均衡策略 四.Rest请求模板类解读 4.1 RestTemplate的GET请求 第一种: ...
- Hadoop优势,组成的相关架构,大数据生态体系下的模式
Hadoop优势,组成的相关架构,大数据生态体系下的模式 一.Hadoop的优势 二.Hadoop的组成 2.1 HDFS架构 2.2 Yarn架构 2.3 MapReduce架构 三.大数据生态体系 ...
- 21.iptables
1.策略与规则链 iptables 服务把用于处理或过滤流量的策略条目称之为规则,多条规则可以组成一个规则链,而规则链则依据数据包处理位置的不同进行分类,具体如下: 在进行路由选择前处理数据包(PRE ...
- 4. DHCP配置(Windows2012)
1.点击服务器管理器 2.选择添加角色和功能 3. 按照添加角色和功能向导来添加 保持默认,下一步 保持默认,下一步 保持默认,下一步 勾选DHCP服务器,在弹出的小窗点击添加功能. 保持默认,下一步 ...
- jvm学习第一天
视频教程链接 第一部分-jvm初识 0.jvm概览图 JVM由三个主要的子系统构成 类加载子系统 运行时数据区(内存结构) 执行引擎运行时数据区(内存结构) 1.什么是jvm 定义: ①. JVM 是 ...
- Pytest(6)重复运行用例pytest-repeat
前言 平常在做功能测试的时候,经常会遇到某个模块不稳定,偶然会出现一些bug,对于这种问题我们会针对此用例反复执行多次,最终复现出问题来. 自动化运行用例时候,也会出现偶然的bug,可以针对单个用例, ...
- left join与inner join
举例a.b表: bId bNum 1 20 2 30 aId aNum 1 10 2 20 3 30 left join以左表为准 select * from a left join b on a.a ...
- Hiho1422 Harmonic Matrix Counter (高斯消元)
16年北京站A题 真的难啊.. 题意: 定义和谐矩阵 就是每个元素和上下左右的xor值=0 输出一个超大数 然后最多800个询问 求字典序第k小的和谐矩阵 x y位置上的数 题解: 首先这个超大数的范 ...
- 【uva 1152】4 Values Whose Sum is Zero(算法效率--中途相遇法+Hash或STL库)
题意:给定4个N元素几个A,B,C,D,要求分别从中选取一个元素a,b,c,d使得a+b+c+d=0.问有多少种选法.(N≤4000,D≤2^28) 解法:首先我们从最直接最暴力的方法开始思考:四重循 ...
- 南阳ccpc C题 The Battle of Chibi && hdu5542 The Battle of Chibi (树状数组优化+dp)
题意: 给你一个长度为n的数组,你需要从中找一个长度为m的严格上升子序列 问你最多能找到多少个 题解: 我们先对原序列从小到大排序,排序之后的序列就是一个上升序列 这里如果两个数相等的话,那么因为题目 ...