- 后端:权限模块,增加 icon、permissions、去除 name 。

This commit is contained in:
YunaiV 2019-05-15 23:50:47 +08:00
parent 051bdeff27
commit 755d94cbdc
10 changed files with 106 additions and 126 deletions

View File

@ -41,7 +41,7 @@ export default {
// admin // admin
'menu.admin': '系统设置', 'menu.admin': '系统设置',
'menu.admin.admin-list': '管理员列表', 'menu.admin.admin-list': '管理员列表',
'menu.admin.resource-list': '资源列表', 'menu.admin.resource-list': '权限列表',
'menu.admin.role-list': '角色列表', 'menu.admin.role-list': '角色列表',
'menu.admin.dictionary-list': '数据字典', 'menu.admin.dictionary-list': '数据字典',
// 商品相关 // 商品相关

View File

@ -15,6 +15,7 @@ import {
TreeSelect, TreeSelect,
Radio, Radio,
Divider, Divider,
Icon, InputNumber,
} from 'antd'; } from 'antd';
import PageHeaderWrapper from '@/components/PageHeaderWrapper'; import PageHeaderWrapper from '@/components/PageHeaderWrapper';
@ -23,7 +24,8 @@ import styles from './ResourceList.less';
const RadioGroup = Radio.Group; const RadioGroup = Radio.Group;
const FormItem = Form.Item; const FormItem = Form.Item;
const { Option } = Select; const { Option } = Select;
const types = ['未知', '菜单', '链接']; const TextArea = Input.TextArea;
const types = ['未知', '菜单', '按钮'];
// 添加 form 表单 // 添加 form 表单
const CreateForm = Form.create()(props => { const CreateForm = Form.create()(props => {
@ -58,8 +60,15 @@ const CreateForm = Form.create()(props => {
width: 200, width: 200,
}; };
const title = modalType === 'add' ? '添加一个 Resource' : '更新一个 Resource'; function onTypeChange(event) {
const okText = modalType === 'add' ? '添加' : '更新'; initValues.type = parseInt(event.target.value);
}
// type 赋予初始值
initValues.type = initValues.type || 1;
const title = modalType === 'add' ? '添加一个权限' : '编辑一个权限';
const okText = modalType === 'add' ? '添加' : '编辑';
return ( return (
<Modal <Modal
destroyOnClose destroyOnClose
@ -71,9 +80,9 @@ const CreateForm = Form.create()(props => {
> >
<FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="类型"> <FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="类型">
{form.getFieldDecorator('type', { {form.getFieldDecorator('type', {
initialValue: initValues.type || 1, initialValue: initValues.type,
})( })(
<RadioGroup> <RadioGroup onChange={onTypeChange}>
<Radio value={1}>菜单</Radio> <Radio value={1}>菜单</Radio>
<Radio value={2}>按钮</Radio> <Radio value={2}>按钮</Radio>
</RadioGroup> </RadioGroup>
@ -81,28 +90,17 @@ const CreateForm = Form.create()(props => {
</FormItem> </FormItem>
<FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="名称"> <FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="名称">
{form.getFieldDecorator('displayName', { {form.getFieldDecorator('displayName', {
rules: [{ required: true, message: '请输入菜单展示名字', min: 2 }], rules: [{ required: true, message: '请输入名称', min: 2 }],
initialValue: initValues.displayName, initialValue: initValues.displayName,
})(<Input placeholder="显示名称" />)} })(<Input placeholder="名称" />)}
</FormItem>
<FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="菜单KEY">
{form.getFieldDecorator('name', {
rules: [{ required: true, message: '请输入资源名字' }],
initialValue: initValues.name,
})(<Input placeholder="菜单KEY 如:用户 USER" />)}
</FormItem>
<FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="操作/路由">
{form.getFieldDecorator('handler', {
initialValue: initValues.handler,
})(<Input placeholder="操作/路由" />)}
</FormItem> </FormItem>
<FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="父级菜单"> <FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="父级菜单">
{form.getFieldDecorator('pid', { {form.getFieldDecorator('pid', {
rules: [{ required: true, message: '输入父级编号' }], rules: [{ required: true, message: '请选择父级编号' }],
initialValue: initialValue:
initValues.pid === 0 initValues.pid === 0
? `根节点-${initValues.pid}` ? `根节点-${initValues.pid}`
: `${initValues.displayName}-${initValues.pid}`, : initValues.pid ? `${initValues.displayName}-${initValues.pid}` : undefined,
})( })(
<TreeSelect <TreeSelect
showSearch showSearch
@ -113,11 +111,35 @@ const CreateForm = Form.create()(props => {
/> />
)} )}
</FormItem> </FormItem>
<FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="菜单排序"> <FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="排序">
{form.getFieldDecorator('sort', { {form.getFieldDecorator('sort', {
rules: [{ required: true, message: '请输入菜单排序' }], rules: [{ required: true, message: '请输入排序' }],
initialValue: initValues.sort, initialValue: initValues.sort,
})(<Input placeholder="请输入" />)} })(<InputNumber placeholder="请输入" />)}
</FormItem>
{
initValues.type === 1 ? (
<FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="图标">
{form.getFieldDecorator('icon', {
rules: [{ required: true, message: '请输入图标' }],
initialValue: initValues.icon,
})(<Input placeholder="图标" />)}
</FormItem>
) : ''
}
{
initValues.type === 1 ? (
<FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="操作">
{form.getFieldDecorator('handler', {
initialValue: initValues.handler,
})(<Input placeholder="操作" />)}
</FormItem>
) : ''
}
<FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="权限标识">
{form.getFieldDecorator('permissions', {
initialValue: initValues.permissions,
})(<TextArea placeholder="多个用逗号进行分割例如system.admin.add,system.admin.update" />)}
</FormItem> </FormItem>
</Modal> </Modal>
); );
@ -176,7 +198,7 @@ class ResourceList extends PureComponent {
...fields, ...fields,
}, },
callback: () => { callback: () => {
message.success('更新成功'); message.success('编辑成功');
this.handleModalVisible(); this.handleModalVisible();
}, },
}, },
@ -214,24 +236,13 @@ class ResourceList extends PureComponent {
const columns = [ const columns = [
{ {
title: '编号', title: '名称',
dataIndex: 'id',
render: text => <strong>{text}</strong>,
},
{
title: '显示名字',
dataIndex: 'displayName', dataIndex: 'displayName',
render: text => <a>{text}</a>,
}, },
{ {
title: '菜单KEY', title: '图标',
dataIndex: 'name', dataIndex: 'icon',
}, render: text => text ? <Icon type={text} /> : '',
{
title: '父级编号',
dataIndex: 'pid',
sorter: true,
render: val => `${val}`,
}, },
{ {
title: '类型', title: '类型',
@ -241,12 +252,32 @@ class ResourceList extends PureComponent {
}, },
}, },
{ {
title: '菜单/操作', title: '排序',
dataIndex: 'sort',
},
{
title: '操作',
dataIndex: 'handler', dataIndex: 'handler',
sorter: true, width: 200,
width: 300,
render: val => <span>{val}</span>, render: val => <span>{val}</span>,
}, },
{
title: '权限标识',
dataIndex: 'permissions',
width: 300,
render(permissions) {
let text = '';
if (permissions) {
for (let i in permissions) {
if (i > 0) {
text += ' ';
}
text += permissions[i];
}
}
return (<span>{text}</span>);
}
},
{ {
title: '创建时间', title: '创建时间',
dataIndex: 'createTime', dataIndex: 'createTime',
@ -257,7 +288,7 @@ class ResourceList extends PureComponent {
title: '操作', title: '操作',
render: (text, record) => ( render: (text, record) => (
<Fragment> <Fragment>
<a onClick={() => this.handleModalVisible(true, 'update', record)}>更新</a> <a onClick={() => this.handleModalVisible(true, 'update', record)}>编辑</a>
<Divider type="vertical" /> <Divider type="vertical" />
<a className={styles.tableDelete} onClick={() => this.handleDelete(record)}> <a className={styles.tableDelete} onClick={() => this.handleDelete(record)}>
删除 删除
@ -268,7 +299,7 @@ class ResourceList extends PureComponent {
]; ];
return ( return (
<PageHeaderWrapper title="查询表格"> <PageHeaderWrapper>
<Card bordered={false}> <Card bordered={false}>
<div className={styles.tableList}> <div className={styles.tableList}>
<div className={styles.tableListOperator}> <div className={styles.tableListOperator}>
@ -277,7 +308,7 @@ class ResourceList extends PureComponent {
type="primary" type="primary"
onClick={() => this.handleModalVisible(true, 'add', {})} onClick={() => this.handleModalVisible(true, 'add', {})}
> >
新建 新建权限
</Button> </Button>
</div> </div>
</div> </div>

View File

@ -1,34 +1,18 @@
package cn.iocoder.mall.admin.application.vo.resource; package cn.iocoder.mall.admin.application.vo.resource;
import cn.iocoder.mall.admin.api.bo.resource.ResourceBO;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import java.util.Date;
import java.util.List; import java.util.List;
@ApiModel("资源树结构 VO") @ApiModel("资源树结构 VO")
@Data @Data
@Accessors(chain = true) @Accessors(chain = true)
public class ResourceTreeNodeVO { public class ResourceTreeNodeVO extends ResourceBO {
@ApiModelProperty(value = "资源编号", required = true, example = "1")
private Integer id;
@ApiModelProperty(value = "资源名字(标识)", required = true, example = "商品管理")
private String name;
@ApiModelProperty(value = "资源类型", required = true, example = "1")
private Integer type;
@ApiModelProperty(value = "排序", required = true, example = "1")
private Integer sort;
@ApiModelProperty(value = "菜单展示名", required = true, example = "商品管理")
private String displayName;
@ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式")
private Date createTime;
@ApiModelProperty(value = "父级资源编号", required = true, example = "1", notes = "如果无父资源,则值为 0")
private Integer pid;
@ApiModelProperty(value = "操作", required = true, example = "/order/list")
private String handler;
@ApiModelProperty(value = "子节点数组") @ApiModelProperty(value = "子节点数组")
private List<ResourceTreeNodeVO> children; private List<ResourceTreeNodeVO> children;

View File

@ -7,6 +7,7 @@ import lombok.experimental.Accessors;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date; import java.util.Date;
import java.util.List;
@ApiModel("资源 BO") @ApiModel("资源 BO")
@Data @Data
@ -34,6 +35,9 @@ public class ResourceBO implements Serializable {
@ApiModelProperty(value = "图标", example = "add") @ApiModelProperty(value = "图标", example = "add")
private String icon; private String icon;
@ApiModelProperty(value = "权限标识数组", example = "system.order.add,system.order.update")
private List<String> permissions;
@ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式") @ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式")
private Date createTime; private Date createTime;

View File

@ -26,15 +26,24 @@ public interface ResourceConvert {
@Mappings({}) @Mappings({})
List<ResourceBO> convert(List<ResourceDO> resourceDOs); List<ResourceBO> convert(List<ResourceDO> resourceDOs);
@Mappings({}) @Mappings({
@Mapping(source = "permissions", target = "permissions", qualifiedByName = "translateStringFromList")
})
ResourceDO convert(ResourceAddDTO resourceAddDTO); ResourceDO convert(ResourceAddDTO resourceAddDTO);
@Mappings({}) @Mappings({
@Mapping(source = "permissions", target = "permissions", qualifiedByName = "translateStringFromList")
})
ResourceDO convert(ResourceUpdateDTO resourceUpdateDTO); ResourceDO convert(ResourceUpdateDTO resourceUpdateDTO);
@Named("translateListFromString") @Named("translateListFromString")
default List<String> translateListFromString(String picUrls) { default List<String> translateListFromString(String str) {
return StringUtil.split(picUrls, ","); return StringUtil.split(str, ",");
}
@Named("translateStringFromList")
default String translateStringFromList(List<String> list) {
return StringUtil.join(list, ",");
} }
} }

View File

@ -1,6 +1,7 @@
package cn.iocoder.mall.admin.dao; package cn.iocoder.mall.admin.dao;
import cn.iocoder.mall.admin.dataobject.ResourceDO; import cn.iocoder.mall.admin.dataobject.ResourceDO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
@ -8,7 +9,7 @@ import java.util.List;
import java.util.Set; import java.util.Set;
@Repository @Repository
public interface ResourceMapper { public interface ResourceMapper extends BaseMapper<ResourceDO> {
ResourceDO selectByTypeAndHandler(@Param("type") Integer type, ResourceDO selectByTypeAndHandler(@Param("type") Integer type,
@Param("handler") String handler); @Param("handler") String handler);
@ -18,16 +19,8 @@ public interface ResourceMapper {
List<ResourceDO> selectListByType(@Param("type") Integer type); List<ResourceDO> selectListByType(@Param("type") Integer type);
ResourceDO selectByName(@Param("name") String name);
ResourceDO selectById(@Param("id") Integer id);
List<ResourceDO> selectListByIds(@Param("ids") Set<Integer> ids); List<ResourceDO> selectListByIds(@Param("ids") Set<Integer> ids);
void insert(ResourceDO resource);
int update(ResourceDO resource);
int selectCountByPid(@Param("pid") Integer pid); int selectCountByPid(@Param("pid") Integer pid);
} }

View File

@ -1,12 +1,14 @@
package cn.iocoder.mall.admin.dataobject; package cn.iocoder.mall.admin.dataobject;
import cn.iocoder.common.framework.dataobject.DeletableDO; import cn.iocoder.common.framework.dataobject.DeletableDO;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
/** /**
* 资源实体 * 资源实体
*/ */
@TableName(value = "resource")
@Data @Data
@Accessors(chain = true) @Accessors(chain = true)
public class ResourceDO extends DeletableDO { public class ResourceDO extends DeletableDO {

View File

@ -6,6 +6,7 @@ import cn.iocoder.mall.admin.api.OAuth2Service;
import cn.iocoder.mall.admin.api.bo.oauth2.OAuth2AccessTokenBO; import cn.iocoder.mall.admin.api.bo.oauth2.OAuth2AccessTokenBO;
import cn.iocoder.mall.admin.api.bo.oauth2.OAuth2AuthenticationBO; import cn.iocoder.mall.admin.api.bo.oauth2.OAuth2AuthenticationBO;
import cn.iocoder.mall.admin.api.constant.AdminErrorCodeEnum; import cn.iocoder.mall.admin.api.constant.AdminErrorCodeEnum;
import cn.iocoder.mall.admin.api.constant.ResourceConstants;
import cn.iocoder.mall.admin.convert.OAuth2Convert; import cn.iocoder.mall.admin.convert.OAuth2Convert;
import cn.iocoder.mall.admin.dao.OAuth2AccessTokenMapper; import cn.iocoder.mall.admin.dao.OAuth2AccessTokenMapper;
import cn.iocoder.mall.admin.dao.OAuth2RefreshTokenMapper; import cn.iocoder.mall.admin.dao.OAuth2RefreshTokenMapper;
@ -96,7 +97,7 @@ public class OAuth2ServiceImpl implements OAuth2Service {
@Override @Override
public CommonResult<Boolean> checkPermission(Integer adminId, Set<Integer> roleIds, String url) { public CommonResult<Boolean> checkPermission(Integer adminId, Set<Integer> roleIds, String url) {
// 如果未配置该资源说明无需权限控制 // 如果未配置该资源说明无需权限控制
ResourceDO resource = resourceService.getResourceByTypeAndHandler(ResourceDO.TYPE_OPERATION, url); ResourceDO resource = resourceService.getResourceByTypeAndHandler(ResourceConstants.TYPE_BUTTON, url);
if (resource == null) { if (resource == null) {
return CommonResult.success(true); return CommonResult.success(true);
} }

View File

@ -80,7 +80,7 @@ public class ResourceServiceImpl implements ResourceService {
// 更新到数据库 // 更新到数据库
ResourceDO resource = ResourceConvert.INSTANCE.convert(resourceUpdateDTO); ResourceDO resource = ResourceConvert.INSTANCE.convert(resourceUpdateDTO);
initResourceProperty(resource); initResourceProperty(resource);
resourceMapper.update(resource); resourceMapper.updateById(resource);
// TODO 操作日志 // TODO 操作日志
// 返回成功 // 返回成功
return true; return true;
@ -98,9 +98,7 @@ public class ResourceServiceImpl implements ResourceService {
throw ServiceExceptionUtil.exception(AdminErrorCodeEnum.RESOURCE_EXISTS_CHILDREN.getCode()); throw ServiceExceptionUtil.exception(AdminErrorCodeEnum.RESOURCE_EXISTS_CHILDREN.getCode());
} }
// 更新到数据库 // 更新到数据库
ResourceDO resource = new ResourceDO().setId(resourceId); resourceMapper.deleteById(resourceId);
resource.setDeleted(DeletedStatusEnum.DELETED_YES.getValue());
resourceMapper.update(resource);
// 删除资源关联表 // 删除资源关联表
roleResourceMapper.updateToDeletedByResourceId(resourceId); roleResourceMapper.updateToDeletedByResourceId(resourceId);
// 返回成功 // 返回成功

View File

@ -3,7 +3,7 @@
<mapper namespace="cn.iocoder.mall.admin.dao.ResourceMapper"> <mapper namespace="cn.iocoder.mall.admin.dao.ResourceMapper">
<sql id="FIELDS"> <sql id="FIELDS">
id, name, type, sort, display_name, id, type, sort, display_name, icon, permissions,
create_time, pid, handler create_time, pid, handler
</sql> </sql>
@ -46,23 +46,6 @@
AND r.id = rr.resource_id AND r.id = rr.resource_id
</select> </select>
<select id="selectByName" parameterType="String" resultType="ResourceDO">
SELECT
<include refid="FIELDS"/>
FROM resource
WHERE name = #{name}
AND deleted = 0
LIMIT 1
</select>
<select id="selectById" resultType="ResourceDO">
SELECT
<include refid="FIELDS"/>
FROM resource
WHERE id = #{id}
AND deleted = 0
</select>
<select id="selectListByIds" resultType="ResourceDO"> <select id="selectListByIds" resultType="ResourceDO">
SELECT SELECT
<include refid="FIELDS"/> <include refid="FIELDS"/>
@ -82,29 +65,4 @@
AND deleted = 0 AND deleted = 0
</select> </select>
<update id="update" parameterType="ResourceDO">
UPDATE resource
<set>
<if test="name != null">
name = #{name},
</if>
<if test="sort != null">
sort = #{sort},
</if>
<if test="displayName != null">
display_name = #{displayName},
</if>
<if test="pid != null">
pid = #{pid},
</if>
<if test="handler != null">
handler = #{handler},
</if>
<if test="deleted != null">
deleted = #{deleted}
</if>
</set>
WHERE id = #{id}
</update>
</mapper> </mapper>