【dva-boot-admin】学React的小菜鸟做的后台管理

#1

学React的小菜鸟做的后台管理

GitHub地址

预览地址 用户名/密码 admin/admin


功能

  • 封装了dva框架的数据流转,简单的请求可以不用在model和service中定义
  • 封装了数据模模拟,可以独立于后台开发前台功能
  • 封装了分页请求,简化并规范了分页逻辑
  • 封装了fetch请求,适应与后台多种交互请求, body参数 parameter参数 path参数,动态请求头,请求前后拦截
  • 扩展了antd写了许多实用的UI,通过一个配置生成即可生成,后台CRUD三件套
  • 按业务模块划分的目录结构,尽量做到最小耦合
  • 一些常用的小部件用法
  • 许多精心设计的页面及交互场景
  • dva-boot脚手架封装的功能
  • 全局异常处理,全局请求拦截,公共配置提取

目录结构

.
├── public                   # 不参与编译的资源文件
├── src                      # 主程序目录
│   ├── index.js             # 程序启动和渲染入口文件
│   ├── components           # 全局公共组件
│   ├── layouts              # 页面结构组件
│   │   ├── BasicLayout      # 基本布局
│   │   └── OtherLayout      # 布局组件根据具体功能调整,在路由配置中引用
│   ├── routes               # 动态路由目录(每个功能一个文件夹的MVC结构)
│   │   ├── index.js         # 路由配置文件
│   │   ├── Home             # 功能模块
│   │   │   ├── index.js     # 路由配置文件
│   │   │   ├── assets       # 单独属于这个模块的静态资源文件
│   │   │   ├── components   # 页面组件
│   │   │   ├── model        # dva model
│   │   │   ├── service      # dva service
│   │   │   └── routes **    # 子路由(目录结构与父级相同)
│   │   └── Login            # 功能模块
│   │       ├── index.js     # 路由配置文件
│   │       ├── assets       # 单独属于这个模块的静态资源文件
│   │       ├── components   # 页面组件
│   │       ├── model        # dva model
│   │       ├── service      # dva service
│   │       └── routes **    # 子路由(目录结构与父级相同)
│   ├── utils                # 工具类
│   └── assets               # 资源文件
│           ├── fonts        # 字体 & 字体图标
│           ├── images       # 图片
│           └── styles       # 全局样式

常用方法

modelEnhance

modelEnhance是对dva model层的简单包装函数,有时候我们只是想要简单的fetch一下,从服务端获取数据进行展示,之前可能要专门在model中写一些effects和reducers,在service中定义请求函数,如果用modelEnhance包装一下的话可以简写成下面的形式

// src/routes/UserInfo/model/index.js

import modelEnhance from '@/utils/modelEnhance';

// 就是普通的dva model传入modelEnhance即可,不用定义其它变量
export default modelEnhance({
  namespace: 'userInfo',
});

// src/routes/UserInfo/components/index.js

// 在组件中直接发出一个类型为`@request`的action,
// 结果会存入userInfo对应的state中,使用的key为`valueField`的值
this.props.dispatch({
  type: 'userInfo/@request',
  payload: {
    url: 'http://httpbin.org/get',
    valueField: 'httpbin',
    method: 'GET'
  }
});

// 同时请求两个
this.props.dispatch({
  type: 'userInfo/@request',
  payload: [{
    url: 'http://httpbin.org/get',
    valueField: 'httpbin',
    method: 'GET'
  }, {
    url: 'http://httpbin.org/post',
    valueField: 'httpbin'
  }]
});

// 结合分页助手使用,查询第1页10条数据
this.props.dispatch({
  type: 'userInfo/@request',
  payload: {
    valueField: 'pageData',
    url: '/api/userInfo/getList',
    pageInfo: pageData.startPage(1, 10),
  }
});

exception

全局异常处理,我们可以在src/config.js的exceptiion中处理通用异常,这里共实就是dva的onError方法的入口,我们一般处理如登录超时,用户没有权限,或另种请求异常等,建议大家不同的异常可以单独包装成一个异常类进行分类处理,这样更容易维护以及调试。

config

工程的配置文件

fetch mock

模拟服务端响应数据,常常用在前后端分离的项目中,我们在开发新功能的时候,前后端是不同步的,这时我们就会创建一些数据原型,协商好后这时后端就可以开始开发,而我们可以继续使用模拟数据,只有当后端完成这个接口并测试通过后,二者才会被整合。这之后如果后端因为某些原因服务不可用时,我们也会很方便的切换回模拟数据,这样不会因为后端的问题而影响后续的开发。

要新建一些模拟数据只要在__mocks__文件夹中,创建一个文件,并在文件夹中的index.js中进行声明,一些例子可以直接在文件夹下面找到。

所有的模拟数据是在开发环境中运行的,当您打包成生产环境的包时,会自动屏蔽所有模拟数据接口。

// 例子: /src/__mocks__/userInfo.js
/**
 * 模拟请求数据
 * @param {FetchMock} fetchMock 当现有条件不满足时,可以使用fetchMock来进行扩展
 * @param {number} delay 增加延迟时间 ms
 * @param {function} mock 使用mock生成数据,例如:

   mock({
     'string|1-10': '★' // 生成最少1颗,最多10颗星字符
   })
   // {'string': '★★★★★★'} 
 */
export default ({fetchMock, delay, mock}) => {
  // 如果现有扩展不满足需求,可以直接使用fetchMock方法
  // fetchMock.mock(/httpbin.org\/post/, {/* response */}, {/* options */});

  return {
    // 一般用法
    'GET /api/getUserInfo': {
      name: 'jonn'
    },
    // 省略 method, 模拟真实请求延迟效果
    '/api/getUsers': delay([
      { name: 'jonn' },
      { name: 'weiq' },
    ]),
    // 表格带分页
    '/api/userInfo/getList': delay(mock({
      'pageNum|+1': 1,                      // 递增加1
      'pageSize': 10,
      'size': 10,
      'total': 500,
      'totalPages': 50,
      'list|10': [{
        'name': '@cname',                   // 中文名称
        'age|1-100': 100,                   // 100以内随机整数
        'birthday': '@date("yyyy-MM-dd")',  // 日期
        'city': '@city(true)',              // 中国城市
        'phone': /^1[385][1-9]\d{8}/        // 手机号
      }],
    })),
    // 表格带分页, 写成函数形式可以使用请求参数,
    // 更真实的模拟后端数据处理业务
    '/api/userInfo/getList1': (options) => {
      const body = JSON.parse(options.body);
      const pageNum = body.pageNum;
      const idbase = (pageNum - 1) * 10 + 1;
      return toSuccess(mock({
        'pageNum': pageNum,
        'pageSize': 10,
        'size': 10,
        'total': 100,
        'totalPages': 10,
        'list|10': [{
          'id|+1': idbase,
          'name': '@cname',                   // 中文名称
          'age|1-100': 100,                   // 100以内随机整数
          'birthday': '@date("yyyy-MM-dd")',  // 日期
          'city': '@city(true)',              // 中国城市
          'phone': /^1[385][1-9]\d{8}/        // 手机号
        }],
      }), 400)
    }
  } 
}

page helper (简单分页)

在做后台系统的时候,做的最多的可能就是对表格的增、删、改、查,这时我们的页面一般是这样的,上面是对表格条件的检索框,中间是我们的数据表格,表格下面是分页组件,还会有新增,修改时用到表单组件

拿对表格数据进行检索这个场景来说,在搜索框(可能有多个)输入条件,点击搜索,检索到结果(可能非常多),我们会点击下面的分页组件进行翻页,翻页时我们就得带着之前的检索条件,我们会在发送请求前手动合并这些条件,并计算下一页的页数等

PageHelper分页助手就是为了简化我们的代码量的,如使用PageHelper.create()这个方法会为我们自动生成分页对象

// model.js

state: {
  pageData: PageHelper.create()
}

这时我们可以在组件中使用这个对象很方便的进行分页,及检索,并且支持链式写法,所有条件会自动进行合并,如:

// components

const {pageData} = this.props;
// 查询第1页,每页10条,并且name为jonn的数据
pageData.startPage(1, 10).filter({name: 'jonn'}).filter(...).sortBy(...);

// 查询下一页,并且会带着之前的查询条件
pageData.nextPage();

我们还可以结合modelEnhance来使用分页,更多用法会在例子中进行说明。

cmn-utils

脚手架使用了cmn-utils做为工具库,这里面提供了请求、存储、事件等许多实用方法

开发&运行

$ git clone https://github.com/LANIF-UI/dva-boot.git
$ cd dva-boot
$ yarn
$ yarn start
// 或使用npm
$ npm install
$ npm start
14 Likes
#2

:clap::clap::clap::clap::clap::clap:

#5

:heart_eyes::heart_eyes:不錯不錯

#7

var date = new Date(), var month = parseInt(date.getMonth()) + 1; console.log(date.getFullYear() + '-' + month + '-' + date.getDate());

#8

楼主,这是怎么回事啊?

#9

你的运行环境是什么样的

#10

node7.7 win10

#12

你用yarn安装一下试试,我又安了一遍没问题

#13

好的啦啦啦啊

#15

不错,喜欢:heart_eyes:

#16

不错不错^^

#17

:grin:牛B:grinning::grin:

#18

图表组件不错:kissing_heart:

#20

:relaxed:谢谢。。。

#21

谢谢支持:wink:

#22

#23

#24

#25

#26