laravel-react實戰打造企業級高併發分佈式電商小程序(三)--權限管理的前端

laravel-react實戰打造企業級高併發分佈式電商小程序(三)–權限管理的前端

react

我們前端使用react來做,我們這個後臺基於antd pro。使用npm創建它。

npm create umi

選擇 ant-design-pro


Select the boilerplate type (Use arrow keys)
❯ ant-design-pro - Create project with an layout-only ant-design-pro boilerplate, use together with umi block.
app - Create project with a simple boilerplate, support typescript.
block - Create a umi block.
library - Create a library with umi.
plugin - Create a umi plugin.


Ant Design Pro 腳手架將會自動安裝。

本地開發

npm installnpm start

啓動完成後會自動打開瀏覽器訪問 http://localhost:8000,你看到下面的頁面就代表成功了。

用戶管理

添加用戶管理的增刪改查,因爲後臺都需要一個表格展示數據,所以把表格抽出來一個組件。

src/components/下面添加Table文件夾,在src/components/Table/下面創建CommonTable.jsx.

src/components/Table/CommonTable.jsx文件內容如下:

import { Table } from 'antd';
import { PureComponent } from 'react';

class CommonTable extends PureComponent{
  constructor(props) {
    super(props);
  }

  render() {
    const {
      datas: { data, page },
      loading,
      columns,
      size,
    } = this.props;
    const paginationProps = {
      showSizeChanger: true,
      showQuickJumper: true,
      ...page
    }
    const scroll = {
      x:true,
      y:500,
      scrollToFirstRowOnChange:true
    }
    console.log(data)
    return <Table
            dataSource={data}
            columns={columns}
            pagination={paginationProps}
            bordered
            loading={loading}
            scroll={scroll}
            rowKey="id"
            size={size}
            />;
  }
}
export default CommonTable;

接下來在src/pages/下面新建auth文件夾和src/pages/auth/users.js



import { PageHeaderWrapper } from '@ant-design/pro-layout';
import CommonTable from '@/components/Table/CommonTable'
import { connect } from 'dva';
import { Popconfirm, Button, message, Card, Row, Col, Form, Modal, Input, Select } from 'antd'

const ButtonGroup = Button.Group;
const { Option } = Select;

const CreateForm = Form.create()(props => {
  const { modalVisible, form, handleAdd, handleModalVisible, handleChange, roleList: { data } } = props

  const okHandle = () => {
    form.validateFields((err, fieldsValue) => {
      if (err) return
      form.resetFields()
      handleAdd(fieldsValue)
    })
  }
  return (
    <Modal
      destroyOnClose
      title="創建用戶"
      visible={modalVisible}
      onOk={okHandle}
      onCancel={() => handleModalVisible()}
    >
      <Form.Item labelCol={{ span: 6 }} wrapperCol={{ span: 15 }} label="用戶名稱">
        {form.getFieldDecorator('name', {
          rules: [{ required: true, message: '請輸入用戶名稱' }],
        })(<Input placeholder="請輸入用戶名稱" />)}
      </Form.Item>
      <Form.Item labelCol={{ span: 6 }} wrapperCol={{ span: 15 }} label="用戶郵箱">
        {form.getFieldDecorator('email', {
          rules: [{ required: true, message: '請輸入用戶郵箱' }],
        })(<Input placeholder="請輸入用戶郵箱" />)}
      </Form.Item>
      <Form.Item labelCol={{ span: 6 }} wrapperCol={{ span: 15 }} label="用戶密碼">
        {form.getFieldDecorator('password', {
          rules: [{ required: true, message: '請輸入用戶密碼' }],
        })(<Input placeholder="請輸入用戶密碼" />)}
      </Form.Item>
      <Form.Item labelCol={{ span: 6 }} wrapperCol={{ span: 15 }} label="角色">
        {form.getFieldDecorator('roleIds', {
          rules: [{ required: true, message: '請選擇角色' }],
        })(<Select
          mode="multiple"
          style={{ width: '100%' }}
          placeholder="請選擇角色"
          // defaultValue={['a10', 'c12']}
          onChange={handleChange}
        >
          {data.map(t => <Option key={t.id} value={t.id} >{t.name}</Option>)}
        </Select>)}
      </Form.Item>
    </Modal>
  )
})

const EditForm = Form.create()(props => {
  const { editModalVisible, form, handleSave, handleModalVisible, values: { name, email, roleIds }, handleChange, roleList: { data } } = props

  const okHandle = () => {
    form.validateFields((err, fieldsValue) => {
      if (err) return
      form.resetFields()
      handleSave(fieldsValue)
    })
  }
  console.log('默認值', name, email, roleIds)
  return (
    <Modal
      destroyOnClose
      title="修改用戶"
      visible={editModalVisible}
      onOk={okHandle}
      onCancel={() => handleModalVisible()}
    >
      <Form.Item labelCol={{ span: 6 }} wrapperCol={{ span: 15 }} label="用戶名稱">
        {form.getFieldDecorator('name', {
          rules: [{ required: true, message: '請輸入用戶名稱' }],
          initialValue: name,
        })(<Input placeholder="請輸入用戶名稱" />)}
      </Form.Item>
      <Form.Item labelCol={{ span: 6 }} wrapperCol={{ span: 15 }} label="用戶郵箱">
        {form.getFieldDecorator('email', {
          rules: [{ required: true, message: '請輸入用戶郵箱' }],
          initialValue: email,
        })(<Input placeholder="請輸入用戶郵箱" />)}
      </Form.Item>
      <Form.Item labelCol={{ span: 6 }} wrapperCol={{ span: 15 }} label="角色">
        {form.getFieldDecorator('roleIds', {
          rules: [{ required: true, message: '請選擇角色' }],
          initialValue: roleIds,
        })(<Select
          mode="multiple"
          style={{ width: '100%' }}
          placeholder="請選擇角色"
          // defaultValue={['a10', 'c12']}
          onChange={handleChange}
        >
          {data.map(t => <Option key={t.id} value={t.id} >{t.name}</Option>)}
        </Select>)}
      </Form.Item>
    </Modal>
  )
})

@connect(({ userList, loading, roleModel }) => ({
  userList,
  loading: loading.models.userList,
  roleModel,
  roleLoading: loading.models.roleModel,
}))
export default class Users extends React.PureComponent {
  constructor(props) {
    super(props)
    this.state = {
      pageIndex: 1,
      pageSize: 10,
      modalVisible: false,
      editModalVisible: false,
      values: {},
    }
  }

  componentDidMount() {
    this.handleSearch(this.state.pageIndex, this.state.pageSize)
  }

  // 獲取列
  getColumns = () => [
      {
        title: '用戶名',
        dataIndex: 'name',
        key: 'name',
        align: 'center',
        width: 200,
      },
      {
        title: '郵箱',
        dataIndex: 'email',
        key: 'email',
        align: 'center',
        width: 300,
      },
      {
        title: '創建時間',
        dataIndex: 'created_at',
        key: 'created_at',
        align: 'center',
        width: 600,
      },
      {
        title: '操作',
        render: (text, record) => (
              <ButtonGroup>
              <Button type="primary" onClick={() => this.edit(record)}>修改</Button>
              <Popconfirm title="確定要刪除嘛?" onConfirm={() => this.handleDelete(record.id)}>
                <Button type="danger">刪除</Button>
              </Popconfirm>
              </ButtonGroup>
          ),
        align: 'center',
      },
    ]

  // 搜索操作
  handleSearch = (pageIndex, pageSize) => {
    const { dispatch } = this.props
    dispatch({
      type: 'userList/getUserList',
      params: {
        pageIndex,
        pageSize,
      },
    })
  }

  // 獲取角色列表
  getRoles = () => {
    const { dispatch } = this.props
    dispatch({
      type: 'roleModel/getRoleList',
      params: {
        pageIndex: 1,
        pageSize: 10000,
      },
    })
  }

  edit = values => {
    console.log('value:', values)
    this.setState({
      values,
    })
    this.editVisible(true)
  }

  // 顯示創建彈窗
  createVisible = flag => {
    // 獲取角色列表
    this.getRoles()
    this.setState({
      modalVisible: !!flag,
    })
  }

  // 顯示修改彈窗
  editVisible = flag => {
    this.setState({
      editModalVisible: !!flag,
    })
  }

  // 刪除操作
  handleDelete = id => {
    const { dispatch } = this.props
    dispatch({
      type: 'userList/delete',
      params: id,
      callback: () => {
        message.success('刪除用戶成功!')
        this.handleSearch(this.state.pageIndex, this.state.pageSize)
      },
    });
  }

  // 創建操作
  handleAdd = fields => {
    const { dispatch } = this.props
    const newFieldsValue = {
      name: fields.name,
      email: fields.email,
      password: fields.password,
      roleIds: fields.roleIds,
    }
    // 跳到第一頁
    this.setState({
      pageIndex: 1,
    })

    dispatch({
      type: 'userList/create',
      params: newFieldsValue,
      callback: () => {
        message.success('新建用戶成功!')
        this.handleSearch(this.state.pageIndex, this.state.pageSize)
      },
    })
    this.createVisible()
  }

  handleSave= fields => {
    const { dispatch } = this.props
    console.log('表單', this.state.values)
    const newFieldsValue = {
      name: fields.name,
      email: fields.email,
      roleIds: fields.roleIds,
    }
    // 跳到第一頁
    this.setState({
      pageIndex: 1,
    })

    dispatch({
      type: 'userList/save',
      id: this.state.values.id,
      params: newFieldsValue,
      callback: () => {
        message.success('修改用戶成功!')
        this.handleSearch(this.state.pageIndex, this.state.pageSize)
      },
    })

    this.editVisible()
  }

  handleChange = value => {
    console.log(`selected ${value}`);
  }


  render() {
    const { userList: { userList }, loading, roleModel: { roleList } } = this.props
    console.log('props:', this.props)
    console.log('load', loading)
    console.log('roles', roleList)

    return (
    <PageHeaderWrapper>
      <Card bordered={false}>
        <Row>
          <Col style={{ paddingBottom: 20 }}>
            <Button icon="plus" type="primary" onClick={() => this.createVisible(true)}>新建用戶</Button>
          </Col>
        </Row>
        <CommonTable
            datas={userList}
            loading={loading}
            columns={this.getColumns()}
            size="middle"
        />
      </Card>
      <CreateForm
          handleAdd={this.handleAdd}
          handleModalVisible={this.createVisible}
          modalVisible={this.state.modalVisible}
          roleList={roleList}
          handleChange={this.handleChange}
        />
        <EditForm
          handleSave={this.handleSave}
          handleModalVisible={this.editVisible}
          editModalVisible={this.state.editModalVisible}
          values={this.state.values}
          roleList={roleList}
          handleChange={this.handleChange}
        />
    </PageHeaderWrapper>
    )
  }
}

在這個頁面中還用到了model,所以我們創建model,在src/models下面創建auth文件夾和src/models/auth/userList.js文件


import {getUsers, deleteUser, createUser, saveUser} from '@/services/auth/users'

export default {
  namespace: 'userList',
  state: {
    userList:{
      data: [],
      page: {},
    }
  },
  effects: {
    *getUserList({params},{call, put}) {
      // console.log(params)
      const res = yield call(getUsers, params);

      // console.log(res)
      yield put({
        type: 'get_user_list',
        payload: res
      })
    },
    *delete({params, callback},{call}) {
      const res = yield call(deleteUser, params);
      if (res !== false) {
        callback()
      }

    },
    *create({params, callback },{call}) {
      const res = yield call(createUser, params);
      if (res !== false) {
        callback()
      }
    },
    *save({id ,params, callback },{call}) {
      const res = yield call(saveUser, id, params);
      if (res !== false) {
        callback()
      }
    }
  },
  reducers: {
    get_user_list(state, action) {
        return  {
          ...state,
          userList:{...state.userList,...action.payload},
        }
    }
  },
};

這裏面使用了service來給後端發送請求,model裏面主要effects裏面封裝了一些給page使用的方法來操作數據,state裏面存放了page需要使用的數據。

我們創建service,在src/services下面創建auth文件夾和src/services/auth/users.js文件。


import request from '@/utils/request';

export async function getUsers(params) {
  return request('/api/auth/users', {
    method: 'get',
    params,
  });
}

export async function deleteUser(id) {
  return request(`/api/auth/user/${id}`, {
    method: 'delete',
  });
}

export async function createUser(params) {
  return request('/api/auth/user', {
    method: 'post',
    data: params,
  });
}

export async function saveUser(id, params) {
  return request(`/api/auth/user/${id}`, {
    method: 'put',
    data: params,
  });
}

好了,接下來就完成了,可以看到service調用了後端剛剛的幾個用戶的增刪改查接口。而model調用了service封裝的接口來改變model中的數據。page通過調用model的數據進行渲染,調用函數進行操作數據。

我們還需要對request進行一個攔截器的封裝,因爲我們使用到了token機制。

src/utils/request.js文件下面添加如下內容:


// request攔截器, 改變url 或 options.
request.interceptors.request.use(async (url, options) => {
  // console.log(url)
  let token = localStorage.getItem('token');
  if (!token) {
    // 請求token
    const res = await fetch('http://www.laraadmin.com/api/require_token', {
      method: 'post',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json; charset=utf-8' },
      })
      const body = await res.json()
    token = body.data
    localStorage.setItem('token', token)
  }
  const headers = {
    Authorization: token,
  };
  return (
    {
      url: `http://www.laraadmin.com${url}`,
      options: { ...options, headers },
    }
  );
})

// response攔截器, 處理response
request.interceptors.response.use(async (response, options) => {
  const res = await response.json()
  // eslint-disable-next-line eqeqeq
  if (res.code != 0) {
    // eslint-disable-next-line eqeqeq
    if (res.code == '400003') {
      // 令牌過期
      // console.log(response, options)
      localStorage.removeItem('token')
      // 重新請求
      request(response.url, options)
    } else {
      message.error(res.msg)
      return false
    }
  }
  return res.data;
});

注意,這些內容放在最後一行上面,也就是下面這句的上面。

export default request;

接下來運行

npm run start

打開瀏覽器

localhost:8000

就可以看到結果了。

角色管理

接下來角色管理,也差不多,就不再寫那麼多目錄結構了。

src/pages/auth/role.js



import { PageHeaderWrapper } from '@ant-design/pro-layout';
import CommonTable from '@/components/Table/CommonTable'
import { connect } from 'dva';
import {Popconfirm, Button, message, Card, Row, Col, Form, Modal, Input } from 'antd'

const ButtonGroup = Button.Group;

const CreateForm = Form.create()(props => {
  const { modalVisible, form, handleAdd, handleModalVisible } = props

  const okHandle = () => {
    form.validateFields((err, fieldsValue) => {
      if (err) return
      form.resetFields()
      handleAdd(fieldsValue)
    })
  }
  return (
    <Modal
      destroyOnClose
      title="創建角色"
      visible={modalVisible}
      onOk={okHandle}
      onCancel={() => handleModalVisible()}
    >
      <Form.Item labelCol={{ span: 6 }} wrapperCol={{ span: 15 }} label="角色名稱">
        {form.getFieldDecorator('name', {
          rules: [{ required: true, message: '請輸入角色名稱'  }],
        })(<Input placeholder="請輸入角色名稱" />)}
      </Form.Item>
    </Modal>
  )
})

const EditForm = Form.create()(props => {
  const { editModalVisible, form, handleSave, handleModalVisible, values:{name} } = props

  const okHandle = () => {
    form.validateFields((err, fieldsValue) => {
      if (err) return
      form.resetFields()
      handleSave(fieldsValue)
    })
  }
  return (
    <Modal
      destroyOnClose
      title="修改角色"
      visible={editModalVisible}
      onOk={okHandle}
      onCancel={() => handleModalVisible()}
    >
      <Form.Item labelCol={{ span: 6 }} wrapperCol={{ span: 15 }} label="角色名稱">
        {form.getFieldDecorator('name', {
          rules: [{ required: true, message: '請輸入角色名稱'  }],
          initialValue:name
        })(<Input placeholder="請輸入角色名稱" />)}
      </Form.Item>
    </Modal>
  )
})

@connect(({ roleModel,loading }) => ({
  roleModel,
  loading: loading.models.roleModel,
}))
export default class Roles extends React.PureComponent{
  constructor(props) {
    super(props)
    this.state = {
      pageIndex: 1,
      pageSize: 10,
      modalVisible: false,
      editModalVisible: false,
      values: {},
    }
  }

  componentDidMount() {
    this.handleSearch(this.state.pageIndex, this.state.pageSize)
  }

  //獲取列
  getColumns = () => {
    return [
      {
        title: '角色名',
        dataIndex: 'name',
        key:'name',
        align:'center',
        width: 400,
      },
      {
        title: '創建時間',
        dataIndex: 'created_at',
        key:'created_at',
        align:'center',
        width: 600,
      },
      {
        title: '操作',
        render: (text, record) => {
          return (
              <ButtonGroup>
              <Button type="primary" onClick={() => this.edit(record)}>修改</Button>
              <Popconfirm title="確定要刪除嘛?" onConfirm={() => this.handleDelete(record.id)}>
                <Button type="danger">刪除</Button>
              </Popconfirm>
              </ButtonGroup>
          );
        },
        align:'center'
      },
    ];
  }

  //搜索操作
  handleSearch = (pageIndex, pageSize) => {
    const { dispatch } = this.props
    dispatch({
      type: 'roleModel/getRoleList',
      params: {
        pageIndex,
        pageSize,
      },
    })
  }

  edit = (values) => {
    this.setState({
      values: values
    })
    this.editVisible(true)
  }

  //顯示創建彈窗
  createVisible = flag => {
    this.setState({
      modalVisible: !!flag,
    })
  }

  //顯示修改彈窗
  editVisible = (flag) => {
    this.setState({
      editModalVisible: !!flag,
    })
  }

  //刪除操作
  handleDelete = (id) => {
    const { dispatch } = this.props
    dispatch({
      type: 'roleModel/delete',
      params: id,
      callback: () =>{
        message.success('刪除角色成功!')
        this.handleSearch(this.state.pageIndex, this.state.pageSize)
      }
    });
  }

  //創建操作
  handleAdd = (fields) => {
    const { dispatch } = this.props

    //跳到第一頁
    this.setState({
      pageIndex: 1,
    })

    dispatch({
      type: 'roleModel/create',
      params: fields,
      callback: () => {
        message.success('新建角色成功!')
        this.handleSearch(this.state.pageIndex, this.state.pageSize)
      },
    })
    this.createVisible()
  }

  handleSave= (fields) => {
    const { dispatch } = this.props

    //跳到第一頁
    this.setState({
      pageIndex: 1,
    })

    dispatch({
      type: 'roleModel/save',
      id: this.state.values.id,
      params: fields,
      callback: () => {
        message.success('修改角色成功!')
        this.handleSearch(this.state.pageIndex, this.state.pageSize)
      },
    })

    this.editVisible()

  }


  render(){
    const { roleModel:{roleList}, loading } = this.props
    return (
    <PageHeaderWrapper>
      <Card bordered={false}>
        <Row>
          <Col style={{ paddingBottom: 20 }}>
            <Button icon="plus" type="primary" onClick={() => this.createVisible(true)}>新建角色</Button>
          </Col>
        </Row>
        <CommonTable
            datas={roleList}
            loading={loading}
            columns={this.getColumns()}
            size='middle'
        />
      </Card>
      <CreateForm
          handleAdd={this.handleAdd}
          handleModalVisible={this.createVisible}
          modalVisible={this.state.modalVisible}
        />
        <EditForm
          handleSave={this.handleSave}
          handleModalVisible={this.editVisible}
          editModalVisible={this.state.editModalVisible}
          values={this.state.values}
        />
    </PageHeaderWrapper>
    )
  }
}

model

src/models/auth/roleModel.js


import { getRoles, deleteRole, createRole, saveRole } from '@/services/auth/roleService'

export default {
  namespace: 'roleModel',
  state: {
    roleList:{
      data: [],
      page: {},
    }
  },
  effects: {
    *getRoleList({params},{call, put}) {
      // console.log(params)
      const res = yield call(getRoles, params);

      // console.log(res)
      yield put({
        type: 'get_role_list',
        payload: res
      })
    },
    *delete({params, callback},{call}) {
      const res = yield call(deleteRole, params);
      if (res !== false) {
        callback()
      }

    },
    *create({params, callback },{call}) {
      const res = yield call(createRole, params);
      if (res !== false) {
        callback()
      }
    },
    *save({id ,params, callback },{call}) {
      const res = yield call(saveRole, id, params);
      if (res !== false) {
        callback()
      }
    }
  },
  reducers: {
    get_role_list(state, action) {
        return  {
          ...state,
          roleList:{...state.roleList,...action.payload},
        }
    }
  },
};

service

src/services/auth/roleService.js


import request from '@/utils/request';

export async function getRoles(params) {
  return request('/api/auth/roles', {
    method: 'get',
    params,
  });
}

export async function deleteRole(id) {
  return request(`/api/auth/role/${id}`, {
    method: 'delete',
  });
}

export async function createRole(params) {
  return request('/api/auth/role', {
    method: 'post',
    data: params,
  });
}

export async function saveRole(id, params) {
  return request(`/api/auth/role/${id}`, {
    method: 'put',
    data: params,
  });
}

權限管理

page

src/pages/auth/permission.js


import { PageHeaderWrapper } from '@ant-design/pro-layout';
import CommonTable from '@/components/Table/CommonTable'
import { connect } from 'dva';
import {Popconfirm, Button, message, Card, Row, Col, Form, Modal, Input, Select, TreeSelect  } from 'antd'

const ButtonGroup = Button.Group;

const CreateForm = Form.create()(props => {
  const { modalVisible, form, handleAdd, handleModalVisible, treeValue, treeData, treeOnChange } = props

  const okHandle = () => {
    form.validateFields((err, fieldsValue) => {
      if (err) return
      form.resetFields()
      handleAdd(fieldsValue)
    })
  }
  return (
    <Modal
      destroyOnClose
      title="創建菜單"
      visible={modalVisible}
      onOk={okHandle}
      onCancel={() => handleModalVisible()}
    >
      <Form.Item labelCol={{ span: 6 }} wrapperCol={{ span: 15 }} label="菜單名稱">
        {form.getFieldDecorator('name', {
          rules: [{ required: true, message: '請輸入菜單名稱'  }],
        })(<Input placeholder="請輸入菜單名稱" />)}
      </Form.Item>
      <Form.Item labelCol={{ span: 6 }} wrapperCol={{ span: 15 }} label="菜單類型">
        {form.getFieldDecorator('type', {
          rules: [{ required: true, message: '請輸入菜單類型'  }],
          initialValue:"menu"
        })(<Select style={{ width: 120 }}>
          <Select.Option value="menu">菜單</Select.Option>
          <Select.Option value="action">功能</Select.Option>
        </Select>)}
      </Form.Item>
      <Form.Item labelCol={{ span: 6 }} wrapperCol={{ span: 15 }} label="上級菜單">
        {form.getFieldDecorator('parentId', {
          setFieldsValue:treeValue
        })(<TreeSelect
          treeDataSimpleMode
          treeDefaultExpandAll="false"
          style={{ width: '100%' }}
          dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
          treeData={treeData}
          placeholder="Please select"
          treeDefaultExpandAll
          onChange={treeOnChange}
        />)}
      </Form.Item>
    </Modal>
  )
})

const EditForm = Form.create()(props => {
  const { editModalVisible, form, handleSave, handleModalVisible, treeValue, treeData, treeOnChange, values:{name,type,parent_id} } = props

  const okHandle = () => {
    form.validateFields((err, fieldsValue) => {
      if (err) return
      form.resetFields()
      handleSave(fieldsValue)
    })
  }
  console.log('tree',treeValue,parent_id,type)
  return (
    <Modal
      destroyOnClose
      title="修改菜單"
      visible={editModalVisible}
      onOk={okHandle}
      onCancel={() => handleModalVisible()}
    >
      <Form.Item labelCol={{ span: 6 }} wrapperCol={{ span: 15 }} label="菜單名稱">
        {form.getFieldDecorator('name', {
          rules: [{ required: true, message: '請輸入菜單名稱'  }],
          initialValue:name,
        })(<Input placeholder="請輸入菜單名稱" />)}
      </Form.Item>
      <Form.Item labelCol={{ span: 6 }} wrapperCol={{ span: 15 }} label="菜單類型">
        {form.getFieldDecorator('type', {
          rules: [{ required: true, message: '請輸入菜單類型'  }],
          initialValue:type,
        })(<Select style={{ width: 120 }}>
          <Select.Option value="menu">菜單</Select.Option>
          <Select.Option value="action">功能</Select.Option>
        </Select>)}
      </Form.Item>
      <Form.Item labelCol={{ span: 6 }} wrapperCol={{ span: 15 }} label="上級菜單">
        {form.getFieldDecorator('parentId', {
          setFieldsValue:treeValue,
          initialValue:parent_id,
        })(<TreeSelect
          treeDataSimpleMode
          treeDefaultExpandAll="false"
          style={{ width: '100%' }}
          dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
          treeData={treeData}
          placeholder="Please select"
          treeDefaultExpandAll
          onChange={treeOnChange}
        />)}
      </Form.Item>
    </Modal>
  )
})

@connect(({ permissionModel,loading }) => ({
  permissionModel,
  loading: loading.models.permissionModel,
}))
export default class Permission extends React.PureComponent{
  constructor(props) {
    super(props)
    this.state = {
      pageIndex: 1,
      pageSize: 10,
      modalVisible: false,
      editModalVisible: false,
      values: {},
      treeValue:undefined,
    }
  }

  //選擇上級菜單
  treeOnChange = value => {

    this.setState({ treeValue:value });
  };

  componentDidMount() {
    this.handleSearch(this.state.pageIndex, this.state.pageSize)
  }

  //獲取列
  getColumns = () => {
    return [
      {
        title: '菜單名',
        dataIndex: 'name',
        key:'name',
        align:'left',
      },
      {
        title: '菜單類型',
        dataIndex: 'type.name',
        key:'type.name',
        align:'center',
      },
      {
        title: '創建時間',
        dataIndex: 'created_at',
        key:'created_at',
        align:'center',
      },
      {
        title: '操作',
        render: (text, record) => {
          return (
              <ButtonGroup>
              <Button type="primary" onClick={() => this.edit(record)}>修改</Button>
              <Popconfirm title="確定要刪除嘛?" onConfirm={() => this.handleDelete(record.id)}>
                <Button type="danger">刪除</Button>
              </Popconfirm>
              </ButtonGroup>
          );
        },
        align:'center'
      },
    ];
  }

  //搜索操作
  handleSearch = (pageIndex, pageSize) => {
    const { dispatch } = this.props
    dispatch({
      type: 'permissionModel/getPermissionList',
      params: {
        pageIndex,
        pageSize,
      },
    })
  }

  edit = (values) => {
    console.log('菜單',values)
    this.getTreeList()
    this.setState({
      values: {...values,type:values.type.code}
    })
    this.editVisible(true)
  }

  //顯示創建彈窗
  createVisible = flag => {
    this.getTreeList()
    this.setState({
      modalVisible: !!flag,
    })
  }

  //顯示修改彈窗
  editVisible = (flag) => {
    this.setState({
      editModalVisible: !!flag,
    })
  }

  //刪除操作
  handleDelete = (id) => {
    const { dispatch } = this.props
    dispatch({
      type: 'permissionModel/delete',
      params: id,
      callback: () =>{
        message.success('刪除菜單成功!')
        this.handleSearch(this.state.pageIndex, this.state.pageSize)
      }
    });
  }

  //創建操作
  handleAdd = (fields) => {
    const { dispatch } = this.props

    //跳到第一頁
    this.setState({
      pageIndex: 1,
    })

    dispatch({
      type: 'permissionModel/create',
      params: fields,
      callback: () => {
        message.success('新建菜單成功!')
        this.handleSearch(this.state.pageIndex, this.state.pageSize)
      },
    })
    this.createVisible()
  }

  handleSave= (fields) => {
    const { dispatch } = this.props

    //跳到第一頁
    this.setState({
      pageIndex: 1,
    })

    dispatch({
      type: 'permissionModel/save',
      id: this.state.values.id,
      params: fields,
      callback: () => {
        message.success('修改菜單成功!')
        this.handleSearch(this.state.pageIndex, this.state.pageSize)
      },
    })

    this.editVisible()

  }

  //獲取樹形列表
  getTreeList = () => {
    const {dispatch} = this.props
    dispatch({
      type: 'permissionModel/getTree',
    })

  }

  render(){
    const { permissionModel:{permissionList,permissionTrees  }, loading } = this.props

    const treeData = permissionTrees
    console.log('list',permissionList)
    return (
    <PageHeaderWrapper>
      <Card bordered={false}>
        <Row>
          <Col style={{ paddingBottom: 20 }}>
            <Button icon="plus" type="primary" onClick={() => this.createVisible(true)}>新建菜單</Button>
          </Col>
        </Row>
        <CommonTable
            datas={permissionList}
            loading={loading}
            columns={this.getColumns()}
            size='middle'
        />
      </Card>
      <CreateForm
          handleAdd={this.handleAdd}
          handleModalVisible={this.createVisible}
          modalVisible={this.state.modalVisible}
          treeData={treeData}
          treeValue={this.state.treeValue}
          treeOnChange={this.treeOnChange}
        />
        <EditForm
          handleSave={this.handleSave}
          handleModalVisible={this.editVisible}
          editModalVisible={this.state.editModalVisible}
          treeData={treeData}
          treeValue={this.state.treeValue}
          treeOnChange={this.treeOnChange}
          values={this.state.values}
        />
    </PageHeaderWrapper>
    )
  }
}

model

src/models/auth/permissionModel.js

import { getPermissions, deletePermission, createPermission, savePermission, getPermissionTree } from '@/services/auth/permissionService'

export default {
  namespace: 'permissionModel',
  state: {
    permissionList:{
      data: [],
      page: {},
    },
    permissionTrees:[]
  },
  effects: {
    *getPermissionList({params},{call, put}) {
      // console.log(params)
      const res = yield call(getPermissions, params);

      // console.log(res)
      yield put({
        type: 'get_list',
        payload: res
      })
    },
    *delete({params, callback},{call}) {
      const res = yield call(deletePermission, params);
      if (res !== false) {
        callback()
      }

    },
    *create({params, callback },{call}) {
      const res = yield call(createPermission, params);
      if (res !== false) {
        callback()
      }
    },
    *save({id ,params, callback },{call}) {
      const res = yield call(savePermission, id, params);
      if (res !== false) {
        callback()
      }
    },
    *getTree({params},{call, put}) {
      const res = yield call(getPermissionTree, params);
      yield put({
        type: 'get_tree_list',
        payload: res
      })
    }
  },
  reducers: {
    get_list(state, action) {
        return  {
          ...state,
          permissionList:{...state.permissionList,...action.payload},
        }
    },
    get_tree_list(state, action) {
      return  {
        ...state,
        permissionTrees:action.payload,
      }
  }
  },
};

service

src/services/auth/permisiionService.js

import request from '@/utils/request';

export async function getPermissions(params) {
  return request('/api/auth/permissions', {
    method: 'get',
    params,
  });
}

export async function deletePermission(id) {
  return request(`/api/auth/permission/${id}`, {
    method: 'delete',
  });
}

export async function createPermission(params) {
  return request('/api/auth/permission', {
    method: 'post',
    data: params,
  });
}

export async function savePermission(id, params) {
  return request(`/api/auth/permission/${id}`, {
    method: 'put',
    data: params,
  });
}

export async function getPermissionTree(params) {
  return request('/api/auth/permission/tree', {
    method: 'get',
    params,
  })
}

好了,權限管理完成了,可以自己試一下。因爲本系列主要講的是後端和高併發的應用而不是前端,所以前端這裏會略過。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章