美文网首页
ant design的增删改查,前后端完整逻辑

ant design的增删改查,前后端完整逻辑

作者: front_ui | 来源:发表于2019-01-25 16:15 被阅读0次

    本文主要介绍antd的Table、Tree、Form等控件的详细用法,还有Tree的加勾选框,json对象转FormData对象。
    antd的官方教程没有完整的增删改查的例子,看完教程到真正的上手实际还需要查阅一定的文档。笔者针对管理系统的角色管理的增删改查功能做一个详细的阐述。先看效果图:


    角色管理.png

    页面采用传统的交互方式,修改、添加都是弹出模态窗口,删除是先弹出确认窗口。

    table列表的显示和增加就不细讲,官方文档里都有,这里主要讲修改是如何实现的。

    {
          title: '操作',
          dataIndex: 'state',
          key: 'state',
          render: (text, record) => (
            <Fragment>
              <a onClick={() => this.handleUpdateModalVisible(true, record)}>修改</a>
              <Divider type="vertical" />
              <a onClick={() => this.handleDelete(true, record)}>删除</a>
            </Fragment>
          ),
        },
    

    先看修改链接生成的代码,表格的最后一列通过render方法生产了两个链接,也就是页面上显示的修改和删除。两个按钮都有相关的onclick方法。这里注意record参数,这个参数实际上就是当前列对应的对象,也就是table的datasource的对应行的对象。下面看handleUpdateModalVisible方法:

    handleUpdateModalVisible = (flag, record) => {
        let that = this;
        this.props.dispatch({
            type: 'trainingrole/getUserRole',
            payload: {
              roleId: record.roleId,
            },
            callback: response => {
              if (response.code == 0) {
                that.setState({
                  updateModalVisible: !!flag,
                  visible: true,
                  currentItem: response.msg,
                  checkedKeys: response.msg.menuIds,
                  roleId:record.roleId,
                });
              } 
            }  
          });
          that.setState({
            modalTitle:'修改角色',
            modifyFlag:true,
          });  
      };
    

    由于table的datasource没有每个角色记录的详细信息,执行修改操作时需要去后端再获取一下详细的角色信息。所以handleUpdateModalVisible一开始就通过props.dispatch发送了一个异步请求获取当前要修改角色的详细信息。对应model里的方法如下:

    *getUserRole({ payload ,callback}, { call, put }) {
            const response = yield call(getTrainingUserRole, payload);
            if (callback) callback(response);
            yield put({
              type: 'userRole',
              payload: response.msg,
            });
          },
    

    获取角色详情的后端返回如下:

    {"msg":{"roleId":1,"roleName":"管理员","remark":"管理员","createTime":null,"modifyTime":null,"menuId":2,"menuIds":[2,3]},"code":0}
    

    这里和上一篇里写的登录一样,主要就是通过dva执行一个远程调用,参数就是点击修改链接时获取到的record.roleId。获取完后端的数据后,通过callback方法将修改的模态窗口弹出,并将获取的数据设置到state中。这里面要注意checkedKeys这个字段,这个是用来标识页面上菜单权限的Tree控件那一个是被选中状态的。
    拿到返回的角色详情后,就应该处理模态框里的数据展示里。具体代码如下:

    <Modal
              title={this.state.modalTitle}
              className={styles.standardListForm}
              visible={visible}
              onOk={this.handleSubmit}
              onCancel={this.handleCancel}
              width={640}
              bodyStyle={{ padding: '32px 40px 48px' }}
            >
              <Form>
               
                    <FormItem  label="角色名称" {...this.formLayout}>
                      {getFieldDecorator('roleName', {
                        rules: [{ required: true }],
                        initialValue: currentItem.roleName,
                      })(
                        <Input />
                      )}
                    </FormItem>
                  
                    <FormItem label="角色描述" {...this.formLayout}>
                      {getFieldDecorator('remark', {
                          initialValue: currentItem.remark,
                      })(
                        <Input />
                      )}
                    </FormItem>
              
                    <Form.Item label="菜单权限" {...this.formLayout}>
                      {getFieldDecorator('menuIds')(
                        <Tree
                        onCheck ={this.onCheck}
                        checkable
                        showIcon
                        multiple={true}
                        checkStrictly={true}
                        checkedKeys={this.state.checkedKeys}
                      >
                        {this.getMenuItems(menuTree)}
                      </Tree>
                      )}
                      
                    </Form.Item>
                  
              </Form>
            </Modal>
    

    这里主要要解决给控件赋值的问题,普通input比较简单,通过getFieldDecorator和initValue来解决,上面的代码一看就懂,下面主要讲一下角色所具有的菜单权限树如何生成。要生成菜单的树形接口,首先要做的是发起一各请求获取菜单的数据,这个数据是不根据角色的不同而变化的,所以在页面加载的时候就发起请求了,也就是在componentDidMount方法中会获取菜单的数据。这里的代码就不展示了,我们还是看一下菜单数据的数据结构:

      children: [
    {
    id: "1",
    icon: null,
    url: null,
    text: "系统管理",
    state: null,
    checked: false,
    attributes: null,
    children: [
    {
    id: "3",
    icon: null,
    url: null,
    text: "用户管理",
    state: null,
    checked: false,
    attributes: null,
    children: [ ],
    parentId: "1",
    hasParent: true,
    hasChildren: false
    },
    {
    id: "4",
    icon: null,
    url: null,
    text: "角色管理",
    state: null,
    checked: false,
    attributes: null,
    children: [ ],
    parentId: "1",
    hasParent: true,
    hasChildren: false
    }
    ],
    parentId: "0",
    hasParent: false,
    hasChildren: true
    }
    

    接下来要做的就是根据这个数据结构生成TreeNode,由于是树形结构,所以要用递归来实现了,具体代码如下:

    getMenuItems = (menuData, parent) => {
        
        if (!menuData) {
          return [];
        }
        return menuData
          .map(item => this.getSubMenuOrItem(item, parent)) 
      };
    
    
      getSubMenuOrItem = item => {
        
        const { TreeNode } = Tree;
        return (
            <TreeNode 
            icon={<Icon type="folder"/>} title={item.menuName} key={item.menuId}>
              {this.getMenuItems(item.children)}
            </TreeNode>
          );
      }
    

    通过getMenuItems 方法就生成了TreeNode显示在页面中。生成TreeNode后,由于设置了checkedKeys选项,需要实现oncheck方法,否则就会出现Tree里面的checkbox不能点的情况。oncheck方法比较简单:

      onCheck = (checkedKeys ,info) => {
        this.setState({ parentId : checkedKeys.checked[0],
            checkedKeys:checkedKeys.checked,
            onCheckFlag:true,
        });
    
      }
    

    到此,关于修改时的页面展示就已经完成,剩下的就是对页面上的数据做保存了。模态框处理确认按钮的方法是handleSubmit,具体代码如下:

    handleSubmit = e => {
        e.preventDefault();
        const { dispatch, form: { validateFields } ,form} = this.props;
        const {currentItem, menuId} = this.state;
    
        validateFields((err, values) => {
          if (err) return;
          let formData = new FormData();
          values.parentId = this.state.checkedKeys[0];
          values.menuId = this.state.checkedKeys;
          values.roleId = this.state.roleId;
          for (var key in values) {
              if (typeof(values[key]) != 'undefined') {
                    formData.append(key,values[key]);
              }
          }
          let that =this;
          dispatch({
              type: 'trainingrole/submitRole',
              payload: formData,
              callback: response => {
                if (response.code == 0) {
                  form.resetFields();
                  that.setState({ visible: false });
                  message.success(`操作成功`);
                  this.props.dispatch({
                    type: 'trainingrole/fetchRole',
                    payload: {
                        detail: true,
                      },
                  });
                  this.props.dispatch({
                    type: 'systemMenu/getSystemMenuData',
                    payload: {
                        detail: true,
                    },
                  });
                } else {
                  message.error(`操作失败`);
                }
    
              },
            });//end  dispatch
    
        });
        
    }
    

    这里的handleSubmit方法及处理创建也处理更新,相关判断逻辑在model层中。view层不做这些判断,只负责收集页面上的数据传回model层。model中的submitRole也比较简单,主要是根据是否有roleId来调用不同的后端方法。

    *submitRole({ payload, callback }, { call, put }) {
            let handleRole;
            if (payload.get('roleId')) {
              handleRole = editRole;
            } else {
              handleRole = addRole;
            }
            const rsp = yield call(handleRole, payload);
            if (callback) callback(rsp);
        },
    
    

    相关文章

      网友评论

          本文标题:ant design的增删改查,前后端完整逻辑

          本文链接:https://www.haomeiwen.com/subject/dcgmjqtx.html