权限设计:http://www.imooc.com/article/40553
import ....
const Option= Select.Option;
const FormItem =Form.Item;
const TreeNode =Tree.TreeNode;
state={}
componentWillMount(){
axios.requestList(this,'/role/list',{})
//已经封装好的axios里面的requestList this指的是指向本元素this
}
//封装好的函数如下
requestList = ()=>{
axios.ajax({
url:'/role/list',
data:{
params:{}
}
}).then((res)=>{
if(res.code == 0){
let list = res.result.item_list.map((item,i)=>{
item.key = i;
return item;
})
this.setState({
list
})
}
})
}
// 角色创建
handleRole = ()=>{
this.setState({
isRoleVisible:true
})
}
// 角色提交
handleRoleSubmit = ()=>{
let data = this.roleForm.props.form.getFieldsValue();
axios.ajax({
url:'role/create',
data:{
params:{
...data
}
}
}).then((res)=>{
if(res.code ==0){
this.setState({
isRoleVisible:false
})
this.roleForm.props.form.resetFields();//清空角色创建弹框表单
axios.requestList(this,'role/list',{});
}
})
}
handlePermission = ()=>{
let item =this.state.selectedItem;//检查是否选中了项
if (!item) {
Modal.info({
text: '请选择一个角色'
})
return;
}
this.setState({
isPermVisible: true,
detailInfo: item,
menuInfo:item.menus
});
let menuList = this.state.selectedItem.menus;
this.setState({
menuInfo:menuList
})
}
handlePermEditSubmit = ()=>{
let data = this.permForm.props.form.getFieldsValue();
data.role_id = this.state.selectedItem.id;//被选中项的id获取到
data.menus = this.state.menuInfo;//选中的key值
axios.ajax({
url:'/permission/edit',
data:{
params:{
...data
}
}
}).then((res)=>{
if(res){
this.setState({
isPermVisible:false
})
axios.requestList(this,'role/list',{});
}
})
}
// 用户授权提交
handleUserSubmit = ()=>{
let data = {};
data.user_ids = this.state.targetKeys || [];
data.role_id = this.state.selectedItem.id;//大列表里面那一行的id(不是modal里的表单
axios.ajax({
url:'/role/user_role_edit',
data:{
params:{
...data
}
}
}).then((res)=>{
if(res){
this.setState({
isUserVisible:false
})
axios.requestList(this,'/role/list',{});
}
})
}
render(){
const columns = [
{
title: '角色ID',
dataIndex: 'id'
}, {
title: '角色名称',
dataIndex: 'role_name'
},{
title: '创建时间',
dataIndex: 'create_time',
render: Utils.formatTime //引用封装好的时间格式转换函数
}, {
title: '使用状态',
dataIndex: 'status',
render(status){
return status ==1?'启用':'停用'
}
}, {
title: '授权时间',
dataIndex: 'authorize_time',
render: Utils.formatTime
}, {
title: '授权人',
dataIndex: 'authorize_user_name'
}
];
return (
<div>
<Card>
<Button type="primary" onClick={this.handleRole}>创建角色</Button>
<Button type="primary" onClick={this.handlePermission}>设置权限</Button>
<Button type="primary" onClick={this.handleUserAuth}>用户授权</Button>
</Card>
<div className="content-wrap">
<ETable
updateSelectedItem={Utils.updateSelectedItem.bind(this)}
selectedRowKeys={this.state.selectedRowKeys}
dataSource={this.state.list}
columns={columns}
/>
</div>
<Modal
title="创建角色"
visible={this.state.isRoleVisible}
onOk={this.handleRoleSubmit}
onCancel={()=>{
this.roleForm.props.form.resetFields();//重置
this.setState({
isRoleVisible:false
})
}}
>
<RoleForm wrappedComponentRef={(inst) => this.roleForm = inst }/>//wrappedComponentRef获取该元素的值为inst 然后赋给this.roleForm
</Modal>
<Modal
title="权限设置"
visible={this.state.isPermVisible}
width={600}
onOk={this.handlePermEditSubmit}
onCancel={()=>{
this.setState({
isPermVisible:false
})
}}>
<PermEditForm
wrappedComponentRef={(inst) => this.permForm = inst }
detailInfo={this.state.detailInfo}
menuInfo={this.state.menuInfo||[]}
patchMenuInfo={(checkedKeys)=>{
this.setState({
menuInfo: checkedKeys
});
}}
/>
</Modal>
<Modal
title="用户授权"
visible={this.state.isUserVisible}
width={800}
onOk={this.handleUserSubmit}
onCancel={()=>{
this.setState({
isUserVisible:false
})
}}>
<RoleAuthForm
wrappedComponentRef={(inst) => this.userAuthForm = inst }
isClosed={this.state.isAuthClosed}
detailInfo={this.state.detailInfo}
targetKeys={this.state.targetKeys}
mockData={this.state.mockData}
patchUserInfo={(targetKeys)=>{
this.setState({ targetKeys})
}}
/>
</Modal>
</div>
);
}
}
// 角色创建
class RoleForm extends React.Component{
render(){
const { getFieldDecorator } = this.props.form;
const formItemLayout = {
labelCol: {span: 5},
wrapperCol: {span: 19}
};
return (
<Form layout="horizontal">
<FormItem label="角色名称" {...formItemLayout}>
{
getFieldDecorator('role_name',)(
<Input type="text" placeholder="请输入角色名称"/>
)
}
</FormItem>
<FormItem label="状态" {...formItemLayout}>
{
getFieldDecorator('state')(
<Select>
<Option value={1}>开启</Option>
<Option value={0}>关闭</Option>
</Select>
)}
</FormItem>
</Form>
);
}
}
RoleForm = Form.create({})(RoleForm);
// 设置权限
class PermEditForm extends React.Component {
state = {};
// 设置选中的节点,通过父组件方法再传递回来
onCheck = (checkedKeys) => {
this.props.patchMenuInfo(checkedKeys);//批量传回
};
//递归权限树
renderTreeNodes = (data) => {
return data.map((item) => {
//要分是否有子节点 如果有子节点继续递归
if (item.children) {
return (
<TreeNode title={item.title} key={parentKey} >
{this.renderTreeNodes(item.children)}
</TreeNode>
)
} else {
return
<TreeNode title={item.title} key={item.Key} />
//方法二:return
}
})
}
renderBtnTreedNode = (menu,parentKey='')=> {
const btnTreeNode = []
menu.btnList.forEach((item)=> {
console.log(parentKey+'-btn-'+item.key);
btnTreeNode.push(<TreeNode title={item.title} key={parentKey+'-btn-'+item.key} className="op-role-tree"/>);
})
return btnTreeNode;
}
render() {
const { getFieldDecorator } = this.props.form;
const formItemLayout = {
labelCol: {span: 5},
wrapperCol: {span: 18}
};
const detail_info = this.props.detailInfo;
const menuInfo = this.props.menuInfo;
return (
<Form layout="horizontal">
<FormItem label="角色名称:" {...formItemLayout}>
<Input disabled placeholder={detail_info.role_name}/>
</FormItem>
<FormItem label="状态:" {...formItemLayout}>
{getFieldDecorator('status',{
initialValue: '1'
})(
<Select style={{ width: 80}}
placeholder="启用"
>
<Option value="1">启用</Option>
<Option value="0">停用</Option>
</Select>
)}
</FormItem>
<Tree
checkable
defaultExpandAll //默认展开
//勾选时
onCheck={(checkedKeys)=>this.onCheck(checkedKeys)}
checkedKeys={menuInfo}//默认选择
>
<TreeNode title="平台权限" key="platform_all">
{this.renderTreeNodes(menuConfig)}
</TreeNode>
</Tree>
</Form>
)
}
}
PermEditForm = Form.create({})(PermEditForm);
menuConfig.js //权限树
const menuList =[
{
title:'首页',
key:'/home'
},
{
title:'UI',
key:'/ui',
children:[
{
title:'按钮',
key:'/admin/ui/buttons',
},
...
]
},
...
];
注意关于路由匹配一块
在router.js的设置上
先放/
再放/common 会使我们想进入/common时进入了/的页面 因为/common 拆解为/ common
我们可以把/common放在/前面 并且在/common里加上extract 精准匹配
依然还会出现两个页面都加载的问题
那可以借助swicth把两个 / /common的外面整个包起来
switch的意思即匹配了一个之后就返回 不会再往后面走的意思
用穿梭框来做这个用户授权
// 用户授权
handleUserAuth = ()=>{
if (!this.state.selectedItem) {
Modal.info({
title: '信息',
content: '未选中任何项目'
})
return;
}
this.setState({
isUserVisible: true,
isAuthClosed: false,
detailInfo: this.state.selectedItem
});
this.getRoleUserList(this.state.selectedItem.id);
}
getRoleUserList = (id)=>{//角色id
axios.ajax({
url:'/role/user_list',
data:{
params:{
id:id//即id
}
}
}).then((res)=>{
if(res){
this.getAuthUserList(res.result);//对用户进行筛选 已授权和未授权
}
})
}
// 筛选目标用户
getAuthUserList = (dataSource) => {
const mockData = [];//就是数据源 datasource
const targetKeys = [];
if (dataSource && dataSource.length > 0) {
for (let i = 0; i < dataSource.length; i++) {
const data = {
key: dataSource[i].user_id,
title: dataSource[i].user_name,
status: dataSource[i].status,
};
if (data.status == 1) {//1为目标用户
targetKeys.push(data.key);//从左侧挑出来同样key的放在右边
}
mockData.push(data);//全部的数据
}
}
this.setState({mockData, targetKeys});
};
// 用户授权
class RoleAuthForm extends React.Component {
filterOption = (inputValue, option) => {
return option.title.indexOf(inputValue) > -1;
};
handleChange = (targetKeys) => {
this.props.patchUserInfo(targetKeys);
};
render() {
const formItemLayout = {
labelCol: {span: 5},
wrapperCol: {span: 18}
};
const detail_info = this.props.detailInfo;
return (
<Form layout="horizontal">
<FormItem label="角色名称:" {...formItemLayout}>
<Input disabled maxLength={8} placeholder={detail_info.role_name}/>
</FormItem>
<FormItem label="选择用户:" {...formItemLayout}>
<Transfer
listStyle={{width: 200,height: 400}}//style
dataSource={this.props.mockData}
showSearch
titles={['待选用户', '已选用户']}
searchPlaceholder='输入用户名'
filterOption={this.filterOption}
targetKeys={this.props.targetKeys}
onChange={this.handleChange}
render={item => item.title}//渲染每一行 放在自己的类里 放在外面表单里不起作用
/>
</FormItem>
</Form>
)
}
}
RoleAuthForm = Form.create({})(RoleAuthForm);
handleClick=({item})=>{
const {dispatch }=this.props;
dispatch(switchMenu(item.props.title)); //引入Action里面的方法
this.setState({
currentKey:key//实际上是item.key 因为上面解构了
})
}
想要这个后台的左边栏有一个选中的栏,
首先我们要设置这个默认的选中栏
key取menuConfig.js里面的key =‘/order',或者等等
<Menu
onClick={this.handleClick}
selectedKeys={this.state.currentKey}
theme="dark"
>
想要实现进入某一个子页面 然后左边栏就会出现选中哪个子页面栏的标志,
关于这个Redux里面的设置见redux入门最前面
Navleft/index.js
state={ currentKey:''}
componentWillMount(){
//从路由里取key
//当页面里面只有子页面路由和#时 可以选择把#替换掉
let currentKey = window.location.hash.replace('#','');
//或者(/#|\?.*$/g,'')把#号或者是?后面还有任意字符结尾的替换掉
this.setState({
currentKey
})
}
显示选中那一页面的header/index.js
取这个name: {this.props.menuName}
const mapStateToPros =state =>{
return {
menuName:state.menuName
}
}
export default connect(mapStateToPros)(header);