1. system 提供新的 Resource 相关接口
2. admin-web 接入新的 Resource 相关接口
This commit is contained in:
parent
caf605063c
commit
f7157d283c
@ -1,5 +1,5 @@
|
|||||||
import { message } from 'antd';
|
import { message } from 'antd';
|
||||||
import { addResource, updateResource, deleteResource, resourceTree } from '../../services/admin';
|
import { resourceTree, resourceAdd, resourceUpdate, resourceDelete } from '../../services/system';
|
||||||
|
|
||||||
const buildSelectTree = list => {
|
const buildSelectTree = list => {
|
||||||
return list.map(item => {
|
return list.map(item => {
|
||||||
@ -8,8 +8,8 @@ const buildSelectTree = list => {
|
|||||||
children = buildSelectTree(item.children);
|
children = buildSelectTree(item.children);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
title: item.displayName,
|
title: item.name,
|
||||||
value: `${item.displayName}-${item.id}`,
|
value: `${item.name}-${item.id}`,
|
||||||
key: item.id,
|
key: item.id,
|
||||||
children,
|
children,
|
||||||
};
|
};
|
||||||
@ -27,7 +27,7 @@ export default {
|
|||||||
effects: {
|
effects: {
|
||||||
*add({ payload }, { call, put }) {
|
*add({ payload }, { call, put }) {
|
||||||
const { callback, body } = payload;
|
const { callback, body } = payload;
|
||||||
const response = yield call(addResource, body);
|
const response = yield call(resourceAdd, body);
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback(response);
|
callback(response);
|
||||||
}
|
}
|
||||||
@ -38,7 +38,7 @@ export default {
|
|||||||
},
|
},
|
||||||
*update({ payload }, { call, put }) {
|
*update({ payload }, { call, put }) {
|
||||||
const { callback, body } = payload;
|
const { callback, body } = payload;
|
||||||
const response = yield call(updateResource, body);
|
const response = yield call(resourceUpdate, body);
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback(response);
|
callback(response);
|
||||||
}
|
}
|
||||||
@ -48,7 +48,7 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
*delete({ payload }, { call, put }) {
|
*delete({ payload }, { call, put }) {
|
||||||
yield call(deleteResource, payload);
|
yield call(resourceDelete, payload);
|
||||||
message.info('删除成功!');
|
message.info('删除成功!');
|
||||||
yield put({
|
yield put({
|
||||||
type: 'tree',
|
type: 'tree',
|
||||||
@ -71,7 +71,7 @@ export default {
|
|||||||
const resultData = payload;
|
const resultData = payload;
|
||||||
const treeData = buildSelectTree(resultData);
|
const treeData = buildSelectTree(resultData);
|
||||||
|
|
||||||
// value 要保护 displayName 不然,搜索会失效
|
// value 要保护 name 不然,搜索会失效
|
||||||
const rootNode = [
|
const rootNode = [
|
||||||
{
|
{
|
||||||
title: '根节点',
|
title: '根节点',
|
||||||
|
@ -89,9 +89,9 @@ 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('name', {
|
||||||
rules: [{ required: true, message: '请输入名称!', min: 2 }],
|
rules: [{ required: true, message: '请输入名称!', min: 2 }],
|
||||||
initialValue: initValues.displayName,
|
initialValue: initValues.name,
|
||||||
})(<Input placeholder="名称" />)}
|
})(<Input placeholder="名称" />)}
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="父级菜单">
|
<FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="父级菜单">
|
||||||
@ -99,8 +99,8 @@ const CreateForm = Form.create()(props => {
|
|||||||
rules: [{ required: true, message: '请选择父级编号!' }],
|
rules: [{ required: true, message: '请选择父级编号!' }],
|
||||||
initialValue:
|
initialValue:
|
||||||
initValues.pid === 0
|
initValues.pid === 0
|
||||||
? `根节点-${initValues.pid}`
|
? `根节点`
|
||||||
: initValues.pid ? `${initValues.displayName}-${initValues.pid}` : undefined,
|
: initValues.pid ? `${initValues.name}` : undefined,
|
||||||
})(
|
})(
|
||||||
<TreeSelect
|
<TreeSelect
|
||||||
showSearch
|
showSearch
|
||||||
@ -129,17 +129,17 @@ const CreateForm = Form.create()(props => {
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
initValues.type === 1 ? (
|
initValues.type === 1 ? (
|
||||||
<FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="操作">
|
<FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="路由">
|
||||||
{form.getFieldDecorator('handler', {
|
{form.getFieldDecorator('route', {
|
||||||
initialValue: initValues.handler,
|
initialValue: initValues.route,
|
||||||
})(<Input placeholder="操作" />)}
|
})(<Input placeholder="路由" />)}
|
||||||
</FormItem>
|
</FormItem>
|
||||||
) : ''
|
) : ''
|
||||||
}
|
}
|
||||||
<FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="权限标识">
|
<FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="权限标识">
|
||||||
{form.getFieldDecorator('permissions', {
|
{form.getFieldDecorator('permission', {
|
||||||
initialValue: initValues.permissions,
|
initialValue: initValues.permission,
|
||||||
})(<TextArea placeholder="多个用逗号进行分割,例如:system.admin.add,system.admin.update" />)}
|
})(<Input placeholder="多个用逗号进行分割,例如:system.admin.add,system.admin.update" />)}
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
@ -210,7 +210,7 @@ class ResourceList extends PureComponent {
|
|||||||
const { dispatch } = this.props;
|
const { dispatch } = this.props;
|
||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
title: `确认删除?`,
|
title: `确认删除?`,
|
||||||
content: `${row.displayName}`,
|
content: `${row.name}`,
|
||||||
onOk() {
|
onOk() {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'resourceList/delete',
|
type: 'resourceList/delete',
|
||||||
@ -237,7 +237,7 @@ class ResourceList extends PureComponent {
|
|||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
title: '名称',
|
title: '名称',
|
||||||
dataIndex: 'displayName',
|
dataIndex: 'name',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '图标',
|
title: '图标',
|
||||||
@ -256,27 +256,16 @@ class ResourceList extends PureComponent {
|
|||||||
dataIndex: 'sort',
|
dataIndex: 'sort',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '路由',
|
||||||
dataIndex: 'handler',
|
dataIndex: 'route',
|
||||||
width: 200,
|
width: 200,
|
||||||
render: val => <span>{val}</span>,
|
render: val => <span>{val}</span>,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '权限标识',
|
title: '权限标识',
|
||||||
dataIndex: 'permissions',
|
dataIndex: 'permission',
|
||||||
width: 300,
|
width: 300,
|
||||||
render(permissions) {
|
render: val => <span>{val}</span>,
|
||||||
let text = '';
|
|
||||||
if (permissions) {
|
|
||||||
for (let i in permissions) {
|
|
||||||
if (i > 0) {
|
|
||||||
text += ' ';
|
|
||||||
}
|
|
||||||
text += permissions[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (<span>{text}</span>);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '创建时间',
|
title: '创建时间',
|
||||||
|
@ -84,29 +84,7 @@ export async function deptTreeAll() {
|
|||||||
|
|
||||||
// resource
|
// resource
|
||||||
|
|
||||||
export async function addResource(params) {
|
|
||||||
return request(`/admin-api/admins/resource/add?${stringify(params)}`, {
|
|
||||||
method: 'POST',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function updateResource(params) {
|
|
||||||
return request(`/admin-api/admins/resource/update?${stringify(params)}`, {
|
|
||||||
method: 'POST',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function deleteResource(params) {
|
|
||||||
return request(`/admin-api/admins/resource/delete?${stringify(params)}`, {
|
|
||||||
method: 'POST',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function resourceTree(params) {
|
|
||||||
return request(`/admin-api/admins/resource/tree?${stringify(params)}`, {
|
|
||||||
method: 'GET',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// role
|
// role
|
||||||
|
|
||||||
|
@ -23,3 +23,29 @@ export async function authorizationResourcePermissions(params) {
|
|||||||
method: 'GET',
|
method: 'GET',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========== Resource 模块 ==========
|
||||||
|
|
||||||
|
export async function resourceTree(params) {
|
||||||
|
return request(`/system-api/admins/resource/tree`, {
|
||||||
|
method: 'GET',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function resourceAdd(params) {
|
||||||
|
return request(`/system-api/admins/resource/add?${stringify(params)}`, {
|
||||||
|
method: 'POST',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function resourceUpdate(params) {
|
||||||
|
return request(`/system-api/admins/resource/update?${stringify(params)}`, {
|
||||||
|
method: 'POST',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function resourceDelete(params) {
|
||||||
|
return request(`/system-api/admins/resource/delete?${stringify(params)}`, {
|
||||||
|
method: 'POST',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -1 +0,0 @@
|
|||||||
package cn.iocoder.mall.security;
|
|
@ -41,12 +41,12 @@ public enum SystemErrorCodeEnum implements ServiceExceptionUtil.Enumerable {
|
|||||||
// ADMIN_ADMIN_CAN_NOT_UPDATE(1002002008, "管理员的账号不允许变更"),
|
// ADMIN_ADMIN_CAN_NOT_UPDATE(1002002008, "管理员的账号不允许变更"),
|
||||||
|
|
||||||
// ========== 资源模块 1002003000 ==========
|
// ========== 资源模块 1002003000 ==========
|
||||||
// RESOURCE_NAME_DUPLICATE(1002003000, "已经存在该名字的资源"),
|
RESOURCE_NAME_DUPLICATE(1002003000, "已经存在该名字的资源"),
|
||||||
// RESOURCE_PARENT_NOT_EXISTS(1002003001, "父资源不存在"),
|
RESOURCE_PARENT_NOT_EXISTS(1002003001, "父资源不存在"),
|
||||||
// RESOURCE_PARENT_ERROR(1002003002, "不能设置自己为父资源"),
|
RESOURCE_PARENT_ERROR(1002003002, "不能设置自己为父资源"),
|
||||||
// RESOURCE_NOT_EXISTS(1002003003, "资源不存在"),
|
RESOURCE_NOT_EXISTS(1002003003, "资源不存在"),
|
||||||
// RESOURCE_EXISTS_CHILDREN(1002003004, "存在子资源,无法删除"),
|
RESOURCE_EXISTS_CHILDREN(1002003004, "存在子资源,无法删除"),
|
||||||
// RESOURCE_PARENT_NOT_MENU(1002003005, "父资源的类型必须是菜单"),
|
RESOURCE_PARENT_NOT_MENU(1002003005, "父资源的类型必须是菜单"),
|
||||||
|
|
||||||
// ========== 角色模块 1002004000 ==========
|
// ========== 角色模块 1002004000 ==========
|
||||||
// ROLE_NOT_EXISTS(1002004000, "角色不存在"),
|
// ROLE_NOT_EXISTS(1002004000, "角色不存在"),
|
||||||
|
@ -12,24 +12,24 @@ public enum ResourceTypeEnum implements IntArrayValuable {
|
|||||||
MENU(1, "菜单"),
|
MENU(1, "菜单"),
|
||||||
BUTTON(2, "按钮");
|
BUTTON(2, "按钮");
|
||||||
|
|
||||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ResourceTypeEnum::getValue).toArray();
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ResourceTypeEnum::getType).toArray();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 资源类型
|
* 资源类型
|
||||||
*/
|
*/
|
||||||
private final Integer value;
|
private final Integer type;
|
||||||
/**
|
/**
|
||||||
* 资源类型名
|
* 资源类型名
|
||||||
*/
|
*/
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
ResourceTypeEnum(Integer value, String name) {
|
ResourceTypeEnum(Integer type, String name) {
|
||||||
this.value = value;
|
this.type = type;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getValue() {
|
public Integer getType() {
|
||||||
return value;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
package cn.iocoder.mall.system.biz.bo.authorization;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权模块 - 资源信息树节点 BO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class ResourceTreeNodeBO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前节点
|
||||||
|
*/
|
||||||
|
private ResourceBO node;
|
||||||
|
/**
|
||||||
|
* 子节点们
|
||||||
|
*/
|
||||||
|
private List<ResourceTreeNodeBO> children;
|
||||||
|
|
||||||
|
}
|
@ -1,8 +1,12 @@
|
|||||||
package cn.iocoder.mall.system.biz.convert.authorization;
|
package cn.iocoder.mall.system.biz.convert.authorization;
|
||||||
|
|
||||||
import cn.iocoder.mall.system.biz.bo.authorization.ResourceBO;
|
import cn.iocoder.mall.system.biz.bo.authorization.ResourceBO;
|
||||||
|
import cn.iocoder.mall.system.biz.bo.authorization.ResourceTreeNodeBO;
|
||||||
import cn.iocoder.mall.system.biz.dataobject.authorization.ResourceDO;
|
import cn.iocoder.mall.system.biz.dataobject.authorization.ResourceDO;
|
||||||
|
import cn.iocoder.mall.system.biz.dto.authorization.ResourceAddDTO;
|
||||||
|
import cn.iocoder.mall.system.biz.dto.authorization.ResourceUpdateDTO;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -14,6 +18,13 @@ public interface ResourceConvert {
|
|||||||
|
|
||||||
ResourceBO convert(ResourceDO bean);
|
ResourceBO convert(ResourceDO bean);
|
||||||
|
|
||||||
|
@Mapping(source = "bean", target = "node")
|
||||||
|
ResourceTreeNodeBO convertTreeNode(ResourceDO bean);
|
||||||
|
|
||||||
List<ResourceBO> convertList(List<ResourceDO> beans);
|
List<ResourceBO> convertList(List<ResourceDO> beans);
|
||||||
|
|
||||||
|
ResourceDO convert(ResourceAddDTO bean);
|
||||||
|
|
||||||
|
ResourceDO convert(ResourceUpdateDTO bean);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,6 @@ public class RoleDO extends DeletableDO {
|
|||||||
private String code;
|
private String code;
|
||||||
/**
|
/**
|
||||||
* 角色类型
|
* 角色类型
|
||||||
*
|
|
||||||
* TODO 需要补充
|
|
||||||
*/
|
*/
|
||||||
private Integer type;
|
private Integer type;
|
||||||
|
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
package cn.iocoder.mall.system.biz.dto.authorization;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权模块 - 获得账号所拥有的资源树 DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class AuthorizationGetResourceTreeByAccountIdDTO {
|
||||||
|
|
||||||
|
@NotNull(message = "账号编号不能为空")
|
||||||
|
private Integer accountId;
|
||||||
|
/**
|
||||||
|
* 资源类型
|
||||||
|
*/
|
||||||
|
private Integer type;
|
||||||
|
|
||||||
|
}
|
@ -6,7 +6,7 @@ import lombok.experimental.Accessors;
|
|||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 授权模块 - 获得账号所拥有的资源 DTO
|
* 授权模块 - 获得账号所拥有的资源列表 DTO
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
package cn.iocoder.mall.system.biz.dto.authorization;
|
||||||
|
|
||||||
|
import cn.iocoder.common.framework.validator.InEnum;
|
||||||
|
import cn.iocoder.mall.system.biz.enums.authorization.ResourceTypeEnum;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源模块 - 添加资源 DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class ResourceAddDTO {
|
||||||
|
|
||||||
|
@NotNull(message = "管理员编号不能为空")
|
||||||
|
private Integer adminId;
|
||||||
|
|
||||||
|
@NotNull(message = "类型不能为空")
|
||||||
|
@InEnum(value = ResourceTypeEnum.class, message = "资源类型必须是 {value}")
|
||||||
|
private Integer type;
|
||||||
|
|
||||||
|
@NotNull(message = "类型不能为空")
|
||||||
|
private Integer sort;
|
||||||
|
|
||||||
|
@NotEmpty(message = "菜单名不能为空")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@NotNull(message = "父级资源编号不能为空")
|
||||||
|
private Integer pid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前端路由
|
||||||
|
*/
|
||||||
|
private String route;
|
||||||
|
/**
|
||||||
|
* 图标
|
||||||
|
*/
|
||||||
|
private String icon;
|
||||||
|
/**
|
||||||
|
* 权限标识
|
||||||
|
*/
|
||||||
|
private String permission;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package cn.iocoder.mall.system.biz.dto.authorization;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源模块 - 删除资源 DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class ResourceDeleteDTO {
|
||||||
|
|
||||||
|
@NotNull(message = "管理员编号不能为空")
|
||||||
|
private Integer adminId;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "资源编号", required = true, example = "1")
|
||||||
|
@NotNull(message = "资源编号不能为空")
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package cn.iocoder.mall.system.biz.dto.authorization;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源模块 - 获得资源树 DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class ResourceGetTreeDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源编号数组
|
||||||
|
*/
|
||||||
|
private Collection<Integer> ids;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源类型
|
||||||
|
*/
|
||||||
|
private Integer type;
|
||||||
|
|
||||||
|
}
|
@ -1,21 +1,24 @@
|
|||||||
package cn.iocoder.mall.system.api.dto.resource;
|
package cn.iocoder.mall.system.biz.dto.authorization;
|
||||||
|
|
||||||
import cn.iocoder.common.framework.validator.InEnum;
|
import cn.iocoder.common.framework.validator.InEnum;
|
||||||
import cn.iocoder.mall.system.api.constant.ResourceTypeEnum;
|
import cn.iocoder.mall.system.biz.enums.authorization.ResourceTypeEnum;
|
||||||
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 javax.validation.constraints.NotEmpty;
|
import javax.validation.constraints.NotEmpty;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ApiModel("资源更新 DTO")
|
/**
|
||||||
|
* 资源模块 - 更新资源 DTO
|
||||||
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
public class ResourceUpdateDTO implements Serializable {
|
public class ResourceUpdateDTO {
|
||||||
|
|
||||||
|
@NotNull(message = "管理员编号不能为空")
|
||||||
|
private Integer adminId;
|
||||||
|
|
||||||
@ApiModelProperty(value = "资源编号", required = true, example = "1")
|
@ApiModelProperty(value = "资源编号", required = true, example = "1")
|
||||||
@NotNull(message = "资源编号不能为空")
|
@NotNull(message = "资源编号不能为空")
|
@ -0,0 +1,29 @@
|
|||||||
|
package cn.iocoder.mall.system.biz.event.authorization;
|
||||||
|
|
||||||
|
import cn.iocoder.mall.system.biz.dataobject.authorization.ResourceDO;
|
||||||
|
import org.springframework.context.ApplicationEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link ResourceDO} 删除事件
|
||||||
|
*/
|
||||||
|
public class ResourceDeleteEvent extends ApplicationEvent {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源编号
|
||||||
|
*/
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
public ResourceDeleteEvent(Object source) {
|
||||||
|
super(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceDeleteEvent(Object source, Integer id) {
|
||||||
|
super(source);
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* Spring 事件机制
|
||||||
|
*
|
||||||
|
* 不了解的胖友,可以阅读 http://www.iocoder.cn/Spring-Boot/Event/?onemall 文章
|
||||||
|
*/
|
||||||
|
package cn.iocoder.mall.system.biz.event;
|
@ -2,6 +2,7 @@ package cn.iocoder.mall.system.biz.service.authorization;
|
|||||||
|
|
||||||
import cn.iocoder.common.framework.exception.ServiceException;
|
import cn.iocoder.common.framework.exception.ServiceException;
|
||||||
import cn.iocoder.mall.system.biz.bo.authorization.ResourceBO;
|
import cn.iocoder.mall.system.biz.bo.authorization.ResourceBO;
|
||||||
|
import cn.iocoder.mall.system.biz.bo.authorization.ResourceTreeNodeBO;
|
||||||
import cn.iocoder.mall.system.biz.dto.authorization.AuthorizationCheckPermissionsDTO;
|
import cn.iocoder.mall.system.biz.dto.authorization.AuthorizationCheckPermissionsDTO;
|
||||||
import cn.iocoder.mall.system.biz.dto.authorization.AuthorizationGetResourcesByAccountIdDTO;
|
import cn.iocoder.mall.system.biz.dto.authorization.AuthorizationGetResourcesByAccountIdDTO;
|
||||||
|
|
||||||
@ -25,8 +26,18 @@ public interface AuthorizationService {
|
|||||||
* 如果该账号为超级管理员,则返回所有资源
|
* 如果该账号为超级管理员,则返回所有资源
|
||||||
*
|
*
|
||||||
* @param getResourcesByAccountIdDTO 查询条件 DTO
|
* @param getResourcesByAccountIdDTO 查询条件 DTO
|
||||||
* @return 列表
|
* @return 资源列表
|
||||||
*/
|
*/
|
||||||
List<ResourceBO> getResourcesByAccountId(AuthorizationGetResourcesByAccountIdDTO getResourcesByAccountIdDTO);
|
List<ResourceBO> getResourcesByAccountId(AuthorizationGetResourcesByAccountIdDTO getResourcesByAccountIdDTO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得指定账号的资源树
|
||||||
|
*
|
||||||
|
* 如果该账号为超级管理员,则返回所有资源
|
||||||
|
*
|
||||||
|
* @param getResourceTreeByAccountIdDTO 查询条件 DTO
|
||||||
|
* @return 资源树
|
||||||
|
*/
|
||||||
|
List<ResourceTreeNodeBO> getResourceTreeByAccountId(AuthorizationGetResourcesByAccountIdDTO getResourceTreeByAccountIdDTO);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package cn.iocoder.mall.system.biz.service.authorization;
|
|||||||
import cn.iocoder.common.framework.util.CollectionUtil;
|
import cn.iocoder.common.framework.util.CollectionUtil;
|
||||||
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
|
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
|
||||||
import cn.iocoder.mall.system.biz.bo.authorization.ResourceBO;
|
import cn.iocoder.mall.system.biz.bo.authorization.ResourceBO;
|
||||||
|
import cn.iocoder.mall.system.biz.bo.authorization.ResourceTreeNodeBO;
|
||||||
import cn.iocoder.mall.system.biz.dao.authorization.AccountRoleMapper;
|
import cn.iocoder.mall.system.biz.dao.authorization.AccountRoleMapper;
|
||||||
import cn.iocoder.mall.system.biz.dao.authorization.RoleResourceMapper;
|
import cn.iocoder.mall.system.biz.dao.authorization.RoleResourceMapper;
|
||||||
import cn.iocoder.mall.system.biz.dataobject.authorization.AccountRoleDO;
|
import cn.iocoder.mall.system.biz.dataobject.authorization.AccountRoleDO;
|
||||||
@ -10,8 +11,11 @@ import cn.iocoder.mall.system.biz.dataobject.authorization.RoleResourceDO;
|
|||||||
import cn.iocoder.mall.system.biz.dto.authorization.AuthorizationCheckPermissionsDTO;
|
import cn.iocoder.mall.system.biz.dto.authorization.AuthorizationCheckPermissionsDTO;
|
||||||
import cn.iocoder.mall.system.biz.dto.authorization.AuthorizationGetResourcesByAccountIdDTO;
|
import cn.iocoder.mall.system.biz.dto.authorization.AuthorizationGetResourcesByAccountIdDTO;
|
||||||
import cn.iocoder.mall.system.biz.dto.authorization.ResourceGetListDTO;
|
import cn.iocoder.mall.system.biz.dto.authorization.ResourceGetListDTO;
|
||||||
|
import cn.iocoder.mall.system.biz.dto.authorization.ResourceGetTreeDTO;
|
||||||
|
import cn.iocoder.mall.system.biz.event.authorization.ResourceDeleteEvent;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.event.EventListener;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -89,8 +93,35 @@ public class AuthorizationServiceImpl implements AuthorizationService {
|
|||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
Set<Integer> resourceIds = CollectionUtil.convertSet(roleResourceDOs, RoleResourceDO::getResourceId);
|
Set<Integer> resourceIds = CollectionUtil.convertSet(roleResourceDOs, RoleResourceDO::getResourceId);
|
||||||
// 查询对应资源
|
// 查询对应资源列表
|
||||||
return resourceService.getResources(new ResourceGetListDTO().setIds(resourceIds).setType(getResourcesByAccountIdDTO.getType()));
|
return resourceService.getResources(new ResourceGetListDTO().setIds(resourceIds).setType(getResourcesByAccountIdDTO.getType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ResourceTreeNodeBO> getResourceTreeByAccountId(AuthorizationGetResourcesByAccountIdDTO getResourcesByAccountIdDTO) {
|
||||||
|
// 查询管理员拥有的角色关联数据
|
||||||
|
List<AccountRoleDO> accountRoleDOs = accountRoleMapper.selectByAccountId(getResourcesByAccountIdDTO.getAccountId());
|
||||||
|
if (CollectionUtil.isEmpty(accountRoleDOs)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
Set<Integer> roleIds = CollectionUtil.convertSet(accountRoleDOs, AccountRoleDO::getRoleId);
|
||||||
|
// 判断是否为超管。若是超管,默认有所有权限
|
||||||
|
if (roleService.hasSuperAdmin(roleIds)) {
|
||||||
|
return resourceService.getResourceTree(new ResourceGetTreeDTO().setType(getResourcesByAccountIdDTO.getType()));
|
||||||
|
}
|
||||||
|
// 查询角色拥有的资源关联数据
|
||||||
|
List<RoleResourceDO> roleResourceDOs = roleResourceMapper.selectListByRoleIds(roleIds);
|
||||||
|
if (CollectionUtil.isEmpty(roleResourceDOs)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
Set<Integer> resourceIds = CollectionUtil.convertSet(roleResourceDOs, RoleResourceDO::getResourceId);
|
||||||
|
// 查询对应资源树
|
||||||
|
return resourceService.getResourceTree(new ResourceGetTreeDTO().setIds(resourceIds).setType(getResourcesByAccountIdDTO.getType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventListener
|
||||||
|
public void handleResourceDeleteEvent(ResourceDeleteEvent event) {
|
||||||
|
roleResourceMapper.deleteByResourceId(event.getId());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,38 @@
|
|||||||
package cn.iocoder.mall.system.biz.service.authorization;
|
package cn.iocoder.mall.system.biz.service.authorization;
|
||||||
|
|
||||||
|
import cn.iocoder.common.framework.exception.ServiceException;
|
||||||
import cn.iocoder.mall.system.biz.bo.authorization.ResourceBO;
|
import cn.iocoder.mall.system.biz.bo.authorization.ResourceBO;
|
||||||
import cn.iocoder.mall.system.biz.dto.authorization.ResourceGetListDTO;
|
import cn.iocoder.mall.system.biz.bo.authorization.ResourceTreeNodeBO;
|
||||||
|
import cn.iocoder.mall.system.biz.dto.authorization.*;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源模块 - Service 接口
|
||||||
|
*/
|
||||||
public interface ResourceService {
|
public interface ResourceService {
|
||||||
|
|
||||||
List<ResourceBO> getResourcesByPermissions(Collection<String> permissions);
|
List<ResourceBO> getResourcesByPermissions(Collection<String> permissions);
|
||||||
|
|
||||||
List<ResourceBO> getResources(ResourceGetListDTO getListDTO);
|
List<ResourceBO> getResources(ResourceGetListDTO getListDTO);
|
||||||
|
|
||||||
|
List<ResourceTreeNodeBO> getResourceTree(ResourceGetTreeDTO getTreeDTO);
|
||||||
|
|
||||||
|
Integer addResource(ResourceAddDTO addDTO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新资源。如果更新失败,则抛出 {@link ServiceException} 异常
|
||||||
|
*
|
||||||
|
* @param updateDTO 更新资源
|
||||||
|
*/
|
||||||
|
void updateResource(ResourceUpdateDTO updateDTO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除资源。如果删除失败,则抛出 {@link ServiceException} 异常
|
||||||
|
*
|
||||||
|
* @param deleteDTO 删除资源
|
||||||
|
*/
|
||||||
|
void deleteResource(ResourceDeleteDTO deleteDTO);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,32 @@
|
|||||||
package cn.iocoder.mall.system.biz.service.authorization;
|
package cn.iocoder.mall.system.biz.service.authorization;
|
||||||
|
|
||||||
|
import cn.iocoder.common.framework.constant.DeletedStatusEnum;
|
||||||
|
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
|
||||||
import cn.iocoder.mall.system.biz.bo.authorization.ResourceBO;
|
import cn.iocoder.mall.system.biz.bo.authorization.ResourceBO;
|
||||||
|
import cn.iocoder.mall.system.biz.bo.authorization.ResourceTreeNodeBO;
|
||||||
import cn.iocoder.mall.system.biz.convert.authorization.ResourceConvert;
|
import cn.iocoder.mall.system.biz.convert.authorization.ResourceConvert;
|
||||||
import cn.iocoder.mall.system.biz.dao.authorization.ResourceMapper;
|
import cn.iocoder.mall.system.biz.dao.authorization.ResourceMapper;
|
||||||
import cn.iocoder.mall.system.biz.dataobject.authorization.ResourceDO;
|
import cn.iocoder.mall.system.biz.dataobject.authorization.ResourceDO;
|
||||||
import cn.iocoder.mall.system.biz.dto.authorization.ResourceGetListDTO;
|
import cn.iocoder.mall.system.biz.dto.authorization.*;
|
||||||
|
import cn.iocoder.mall.system.biz.enums.SystemErrorCodeEnum;
|
||||||
|
import cn.iocoder.mall.system.biz.enums.authorization.ResourceIdEnum;
|
||||||
|
import cn.iocoder.mall.system.biz.enums.authorization.ResourceTypeEnum;
|
||||||
|
import cn.iocoder.mall.system.biz.event.authorization.ResourceDeleteEvent;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.List;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
|
@Slf4j
|
||||||
public class ResourceServiceImpl implements ResourceService {
|
public class ResourceServiceImpl implements ResourceService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ApplicationEventPublisher eventPublisher;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ResourceMapper resourceMapper;
|
private ResourceMapper resourceMapper;
|
||||||
|
|
||||||
@ -29,4 +42,122 @@ public class ResourceServiceImpl implements ResourceService {
|
|||||||
return ResourceConvert.INSTANCE.convertList(resourceDOs);
|
return ResourceConvert.INSTANCE.convertList(resourceDOs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ResourceTreeNodeBO> getResourceTree(ResourceGetTreeDTO getTreeDTO) {
|
||||||
|
// 获得对应的资源列表
|
||||||
|
List<ResourceDO> resourceDOs = resourceMapper.selectListByIdsAndType(getTreeDTO.getIds(), getTreeDTO.getType());
|
||||||
|
// 拼装成树
|
||||||
|
// 使用 LinkedHashMap 的原因,是为了排序 。实际也可以用 Stream API ,就是太丑了。
|
||||||
|
Map<Integer, ResourceTreeNodeBO> treeNodeMap = new LinkedHashMap<>();
|
||||||
|
resourceDOs.stream().sorted(Comparator.comparing(ResourceDO::getSort))
|
||||||
|
.forEach(resourceDO -> treeNodeMap.put(resourceDO.getId(), ResourceConvert.INSTANCE.convertTreeNode(resourceDO)));
|
||||||
|
// 处理父子关系
|
||||||
|
treeNodeMap.values().stream()
|
||||||
|
.filter(node -> !node.getNode().getPid().equals(ResourceIdEnum.ROOT.getId()))
|
||||||
|
.forEach((childNode) -> {
|
||||||
|
// 获得父节点
|
||||||
|
ResourceTreeNodeBO parentNode = treeNodeMap.get(childNode.getNode().getPid());
|
||||||
|
if (parentNode == null) {
|
||||||
|
log.error("[getResourceTree][resource({}) 找不到父资源({})]", childNode.getNode().getId(), childNode.getNode().getPid());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (parentNode.getChildren() == null) { // 初始化 children 数组
|
||||||
|
parentNode.setChildren(new ArrayList<>());
|
||||||
|
}
|
||||||
|
// 将自己添加到父节点中
|
||||||
|
parentNode.getChildren().add(childNode);
|
||||||
|
});
|
||||||
|
// 获得到所有的根节点
|
||||||
|
return treeNodeMap.values().stream()
|
||||||
|
.filter(node -> node.getNode().getPid().equals(ResourceIdEnum.ROOT.getId()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer addResource(ResourceAddDTO addDTO) {
|
||||||
|
// 校验父资源存在
|
||||||
|
checkParentResource(addDTO.getPid(), null);
|
||||||
|
// 存储到数据库
|
||||||
|
ResourceDO resource = ResourceConvert.INSTANCE.convert(addDTO);
|
||||||
|
initResourceProperty(resource);
|
||||||
|
resource.setCreateTime(new Date());
|
||||||
|
resource.setDeleted(DeletedStatusEnum.DELETED_NO.getValue());
|
||||||
|
resourceMapper.insert(resource);
|
||||||
|
// TODO 操作日志
|
||||||
|
// 返回成功
|
||||||
|
return resource.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateResource(ResourceUpdateDTO updateDTO) {
|
||||||
|
// 校验更新的资源是否存在
|
||||||
|
if (resourceMapper.selectById(updateDTO.getId()) == null) {
|
||||||
|
throw ServiceExceptionUtil.exception(SystemErrorCodeEnum.RESOURCE_NOT_EXISTS.getCode());
|
||||||
|
}
|
||||||
|
// 校验父资源存在
|
||||||
|
checkParentResource(updateDTO.getPid(), updateDTO.getId());
|
||||||
|
// 更新到数据库
|
||||||
|
ResourceDO resource = ResourceConvert.INSTANCE.convert(updateDTO);
|
||||||
|
initResourceProperty(resource);
|
||||||
|
resourceMapper.updateById(resource);
|
||||||
|
// TODO 操作日志
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteResource(ResourceDeleteDTO deleteDTO) {
|
||||||
|
// 校验更新的资源是否存在
|
||||||
|
if (resourceMapper.selectById(deleteDTO.getId()) == null) {
|
||||||
|
throw ServiceExceptionUtil.exception(SystemErrorCodeEnum.RESOURCE_NOT_EXISTS.getCode());
|
||||||
|
}
|
||||||
|
// 校验是否还有子资源
|
||||||
|
if (resourceMapper.selectCountByPid(deleteDTO.getId()) > 0) {
|
||||||
|
throw ServiceExceptionUtil.exception(SystemErrorCodeEnum.RESOURCE_EXISTS_CHILDREN.getCode());
|
||||||
|
}
|
||||||
|
// 更新到数据库
|
||||||
|
resourceMapper.deleteById(deleteDTO.getId());
|
||||||
|
// 删除资源关联表
|
||||||
|
eventPublisher.publishEvent(new ResourceDeleteEvent(this, deleteDTO.getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验父资源是否合法
|
||||||
|
*
|
||||||
|
* @param pid 父资源编号
|
||||||
|
* @param childId 当前资源编号
|
||||||
|
*/
|
||||||
|
private void checkParentResource(Integer pid, Integer childId) {
|
||||||
|
if (pid == null || ResourceIdEnum.ROOT.getId().equals(pid)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (pid.equals(childId)) { // 不能设置自己为父资源
|
||||||
|
throw ServiceExceptionUtil.exception(SystemErrorCodeEnum.RESOURCE_PARENT_ERROR.getCode());
|
||||||
|
}
|
||||||
|
ResourceDO resource = resourceMapper.selectById(pid);
|
||||||
|
if (resource == null) { // 父资源不存在
|
||||||
|
throw ServiceExceptionUtil.exception(SystemErrorCodeEnum.RESOURCE_PARENT_NOT_EXISTS.getCode());
|
||||||
|
}
|
||||||
|
if (!ResourceTypeEnum.MENU.getType().equals(resource.getType())) { // 父资源必须是菜单类型
|
||||||
|
throw ServiceExceptionUtil.exception(SystemErrorCodeEnum.RESOURCE_PARENT_NOT_MENU.getCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化资源的通用属性。
|
||||||
|
*
|
||||||
|
* 例如说,只有菜单类型的资源,才设置 icon
|
||||||
|
*
|
||||||
|
* @param resource 资源
|
||||||
|
*/
|
||||||
|
private void initResourceProperty(ResourceDO resource) {
|
||||||
|
// 初始化根节点的情况
|
||||||
|
if (resource.getPid() == null) {
|
||||||
|
resource.setPid(ResourceIdEnum.ROOT.getId());
|
||||||
|
}
|
||||||
|
// 初始化资源为按钮类型时,无需 route 和 icon 属性
|
||||||
|
if (ResourceTypeEnum.BUTTON.getType().equals(resource.getType())) {
|
||||||
|
resource.setRoute(null);
|
||||||
|
resource.setIcon(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,8 @@ import cn.iocoder.common.framework.constant.MallConstants;
|
|||||||
import cn.iocoder.common.framework.vo.CommonResult;
|
import cn.iocoder.common.framework.vo.CommonResult;
|
||||||
import cn.iocoder.mall.security.core.context.AdminSecurityContextHolder;
|
import cn.iocoder.mall.security.core.context.AdminSecurityContextHolder;
|
||||||
import cn.iocoder.mall.system.biz.bo.authorization.ResourceBO;
|
import cn.iocoder.mall.system.biz.bo.authorization.ResourceBO;
|
||||||
|
import cn.iocoder.mall.system.biz.bo.authorization.ResourceTreeNodeBO;
|
||||||
import cn.iocoder.mall.system.biz.dto.authorization.AuthorizationGetResourcesByAccountIdDTO;
|
import cn.iocoder.mall.system.biz.dto.authorization.AuthorizationGetResourcesByAccountIdDTO;
|
||||||
import cn.iocoder.mall.system.biz.enums.authorization.ResourceIdEnum;
|
|
||||||
import cn.iocoder.mall.system.biz.enums.authorization.ResourceTypeEnum;
|
import cn.iocoder.mall.system.biz.enums.authorization.ResourceTypeEnum;
|
||||||
import cn.iocoder.mall.system.biz.service.authorization.AuthorizationService;
|
import cn.iocoder.mall.system.biz.service.authorization.AuthorizationService;
|
||||||
import cn.iocoder.mall.system.rest.convert.authorization.AdminsAuthorizationConvert;
|
import cn.iocoder.mall.system.rest.convert.authorization.AdminsAuthorizationConvert;
|
||||||
@ -18,7 +18,8 @@ import org.springframework.web.bind.annotation.GetMapping;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@ -33,34 +34,9 @@ public class AdminsAuthorizationController {
|
|||||||
@GetMapping("/menu-resource-tree")
|
@GetMapping("/menu-resource-tree")
|
||||||
@ApiOperation(value = "获得当前账号的菜单资源树", notes = "以树结构返回")
|
@ApiOperation(value = "获得当前账号的菜单资源树", notes = "以树结构返回")
|
||||||
public CommonResult<List<AdminsAuthorizationMenuTreeResponse>> menuResourceTree() {
|
public CommonResult<List<AdminsAuthorizationMenuTreeResponse>> menuResourceTree() {
|
||||||
List<ResourceBO> resources = authorizationService.getResourcesByAccountId(new AuthorizationGetResourcesByAccountIdDTO()
|
List<ResourceTreeNodeBO> resourceTreeNodeBOs = authorizationService.getResourceTreeByAccountId(new AuthorizationGetResourcesByAccountIdDTO()
|
||||||
.setAccountId(AdminSecurityContextHolder.getAccountId()).setType(ResourceTypeEnum.MENU.getValue()));
|
.setAccountId(AdminSecurityContextHolder.getAccountId()).setType(ResourceTypeEnum.MENU.getType()));
|
||||||
// 创建 AdminMenuTreeNodeVO Map
|
return CommonResult.success(AdminsAuthorizationConvert.INSTANCE.convertList(resourceTreeNodeBOs));
|
||||||
// 使用 LinkedHashMap 的原因,是为了排序 。实际也可以用 Stream API ,就是太丑了。
|
|
||||||
Map<Integer, AdminsAuthorizationMenuTreeResponse> treeNodeMap = new LinkedHashMap<>();
|
|
||||||
resources.stream().sorted(Comparator.comparing(ResourceBO::getSort))
|
|
||||||
.forEach(resourceBO -> treeNodeMap.put(resourceBO.getId(), AdminsAuthorizationConvert.INSTANCE.convert(resourceBO)));
|
|
||||||
// 处理父子关系
|
|
||||||
treeNodeMap.values().stream()
|
|
||||||
.filter(node -> !node.getPid().equals(ResourceIdEnum.ROOT.getId()))
|
|
||||||
.forEach((childNode) -> {
|
|
||||||
// 获得父节点
|
|
||||||
AdminsAuthorizationMenuTreeResponse parentNode = treeNodeMap.get(childNode.getPid());
|
|
||||||
if (parentNode == null) {
|
|
||||||
log.error("[menuResourceTree][resource({}) 找不到父资源({})]", childNode.getId(), childNode.getPid());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (parentNode.getChildren() == null) { // 初始化 children 数组
|
|
||||||
parentNode.setChildren(new ArrayList<>());
|
|
||||||
}
|
|
||||||
// 将自己添加到父节点中
|
|
||||||
parentNode.getChildren().add(childNode);
|
|
||||||
});
|
|
||||||
// 获得到所有的根节点
|
|
||||||
List<AdminsAuthorizationMenuTreeResponse> rootNodes = treeNodeMap.values().stream()
|
|
||||||
.filter(node -> node.getPid().equals(ResourceIdEnum.ROOT.getId()))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
return CommonResult.success(rootNodes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/resource-permissions")
|
@GetMapping("/resource-permissions")
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
package cn.iocoder.mall.system.rest.controller.authorization;
|
||||||
|
|
||||||
|
import cn.iocoder.common.framework.constant.MallConstants;
|
||||||
|
import cn.iocoder.common.framework.vo.CommonResult;
|
||||||
|
import cn.iocoder.mall.security.core.annotation.RequiresPermissions;
|
||||||
|
import cn.iocoder.mall.security.core.context.AdminSecurityContextHolder;
|
||||||
|
import cn.iocoder.mall.system.biz.bo.authorization.ResourceTreeNodeBO;
|
||||||
|
import cn.iocoder.mall.system.biz.dto.authorization.ResourceAddDTO;
|
||||||
|
import cn.iocoder.mall.system.biz.dto.authorization.ResourceDeleteDTO;
|
||||||
|
import cn.iocoder.mall.system.biz.dto.authorization.ResourceGetTreeDTO;
|
||||||
|
import cn.iocoder.mall.system.biz.dto.authorization.ResourceUpdateDTO;
|
||||||
|
import cn.iocoder.mall.system.biz.service.authorization.ResourceService;
|
||||||
|
import cn.iocoder.mall.system.rest.convert.authorization.AdminsResourceConvert;
|
||||||
|
import cn.iocoder.mall.system.rest.request.authorization.AdminsResourceAddRequest;
|
||||||
|
import cn.iocoder.mall.system.rest.request.authorization.AdminsResourceUpdateRequest;
|
||||||
|
import cn.iocoder.mall.system.rest.response.authorization.AdminsResourceTreeResponse;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiImplicitParam;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping(MallConstants.ROOT_PATH_ADMIN + "/resource")
|
||||||
|
@Api(tags = "管理员 - 资源 API")
|
||||||
|
public class AdminsResourceController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ResourceService resourceService;
|
||||||
|
|
||||||
|
@GetMapping("/tree")
|
||||||
|
@ApiOperation(value = "获得所有资源,按照树形结构返回")
|
||||||
|
@RequiresPermissions("system:resource:tree")
|
||||||
|
public CommonResult<List<AdminsResourceTreeResponse>> tree() {
|
||||||
|
List<ResourceTreeNodeBO> resourceTreeNodeBOs = resourceService.getResourceTree(new ResourceGetTreeDTO());
|
||||||
|
return CommonResult.success(AdminsResourceConvert.INSTANCE.convertList(resourceTreeNodeBOs));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/add")
|
||||||
|
@ApiOperation(value = "创建资源", notes = "例如说,菜单资源,按钮资源")
|
||||||
|
@RequiresPermissions("system:resource:add")
|
||||||
|
public CommonResult<Integer> add(AdminsResourceAddRequest request) {
|
||||||
|
ResourceAddDTO addDTO = AdminsResourceConvert.INSTANCE.convert(request)
|
||||||
|
.setAdminId(AdminSecurityContextHolder.getAdminId());
|
||||||
|
return CommonResult.success(resourceService.addResource(addDTO));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/update")
|
||||||
|
@ApiOperation(value = "更新资源")
|
||||||
|
@RequiresPermissions("system:resource:update")
|
||||||
|
public CommonResult<Boolean> update(AdminsResourceUpdateRequest request) {
|
||||||
|
ResourceUpdateDTO updateDTO = AdminsResourceConvert.INSTANCE.convert(request)
|
||||||
|
.setAdminId(AdminSecurityContextHolder.getAdminId());
|
||||||
|
resourceService.updateResource(updateDTO);
|
||||||
|
return CommonResult.success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/delete")
|
||||||
|
@ApiOperation(value = "删除资源")
|
||||||
|
@ApiImplicitParam(name = "id", value = "资源编号", required = true, example = "1")
|
||||||
|
@RequiresPermissions("system:resource:delete")
|
||||||
|
public CommonResult<Boolean> delete(@RequestParam("id") Integer id) {
|
||||||
|
ResourceDeleteDTO deleteDTO = new ResourceDeleteDTO().setId(id)
|
||||||
|
.setAdminId(AdminSecurityContextHolder.getAdminId());
|
||||||
|
resourceService.deleteResource(deleteDTO);
|
||||||
|
return CommonResult.success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,11 +1,7 @@
|
|||||||
package cn.iocoder.mall.system.rest.controller.datadict;
|
package cn.iocoder.mall.system.rest.controller.datadict;
|
||||||
|
|
||||||
import cn.iocoder.common.framework.constant.MallConstants;
|
import cn.iocoder.common.framework.constant.MallConstants;
|
||||||
import cn.iocoder.common.framework.vo.CommonResult;
|
|
||||||
import cn.iocoder.mall.security.core.annotation.RequiresPermissions;
|
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
@ -17,13 +13,6 @@ public class AdminsDataDictController {
|
|||||||
// @Reference(validation = "true", version = "${dubbo.provider.DataDictService.version}")
|
// @Reference(validation = "true", version = "${dubbo.provider.DataDictService.version}")
|
||||||
// private DataDictService dataDictService;
|
// private DataDictService dataDictService;
|
||||||
|
|
||||||
@GetMapping("/demo")
|
|
||||||
@ApiOperation(value = "数据字典全列表")
|
|
||||||
@RequiresPermissions("system.dataDict.list")
|
|
||||||
public CommonResult<Boolean> list() {
|
|
||||||
return CommonResult.success(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// @GetMapping("/list")
|
// @GetMapping("/list")
|
||||||
// @ApiOperation(value = "数据字典全列表")
|
// @ApiOperation(value = "数据字典全列表")
|
||||||
// @RequiresPermissions("system.dataDict.list")
|
// @RequiresPermissions("system.dataDict.list")
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
package cn.iocoder.mall.system.rest.convert.authorization;
|
package cn.iocoder.mall.system.rest.convert.authorization;
|
||||||
|
|
||||||
import cn.iocoder.mall.system.biz.bo.authorization.ResourceBO;
|
import cn.iocoder.mall.system.biz.bo.authorization.ResourceBO;
|
||||||
|
import cn.iocoder.mall.system.biz.bo.authorization.ResourceTreeNodeBO;
|
||||||
import cn.iocoder.mall.system.rest.response.authorization.AdminsAuthorizationMenuTreeResponse;
|
import cn.iocoder.mall.system.rest.response.authorization.AdminsAuthorizationMenuTreeResponse;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface AdminsAuthorizationConvert {
|
public interface AdminsAuthorizationConvert {
|
||||||
|
|
||||||
@ -12,4 +16,12 @@ public interface AdminsAuthorizationConvert {
|
|||||||
|
|
||||||
AdminsAuthorizationMenuTreeResponse convert(ResourceBO bean);
|
AdminsAuthorizationMenuTreeResponse convert(ResourceBO bean);
|
||||||
|
|
||||||
|
@Mapping(source = "node.id", target = "id")
|
||||||
|
@Mapping(source = "node.name", target = "name")
|
||||||
|
@Mapping(source = "node.route", target = "route")
|
||||||
|
@Mapping(source = "node.icon", target = "icon")
|
||||||
|
AdminsAuthorizationMenuTreeResponse convert(ResourceTreeNodeBO bean);
|
||||||
|
|
||||||
|
List<AdminsAuthorizationMenuTreeResponse> convertList(List<ResourceTreeNodeBO> beans);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
package cn.iocoder.mall.system.rest.convert.authorization;
|
||||||
|
|
||||||
|
import cn.iocoder.mall.system.biz.bo.authorization.ResourceTreeNodeBO;
|
||||||
|
import cn.iocoder.mall.system.biz.dto.authorization.ResourceAddDTO;
|
||||||
|
import cn.iocoder.mall.system.biz.dto.authorization.ResourceUpdateDTO;
|
||||||
|
import cn.iocoder.mall.system.rest.request.authorization.AdminsResourceAddRequest;
|
||||||
|
import cn.iocoder.mall.system.rest.request.authorization.AdminsResourceUpdateRequest;
|
||||||
|
import cn.iocoder.mall.system.rest.response.authorization.AdminsResourceTreeResponse;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface AdminsResourceConvert {
|
||||||
|
|
||||||
|
AdminsResourceConvert INSTANCE = Mappers.getMapper(AdminsResourceConvert.class);
|
||||||
|
|
||||||
|
@Mapping(source = "node.id", target = "id")
|
||||||
|
@Mapping(source = "node.name", target = "name")
|
||||||
|
@Mapping(source = "node.permission", target = "permission")
|
||||||
|
@Mapping(source = "node.type", target = "type")
|
||||||
|
@Mapping(source = "node.sort", target = "sort")
|
||||||
|
@Mapping(source = "node.pid", target = "pid")
|
||||||
|
@Mapping(source = "node.route", target = "route")
|
||||||
|
@Mapping(source = "node.icon", target = "icon")
|
||||||
|
AdminsResourceTreeResponse convert(ResourceTreeNodeBO bean);
|
||||||
|
|
||||||
|
List<AdminsResourceTreeResponse> convertList(List<ResourceTreeNodeBO> beans);
|
||||||
|
|
||||||
|
ResourceAddDTO convert(AdminsResourceAddRequest bean);
|
||||||
|
|
||||||
|
ResourceUpdateDTO convert(AdminsResourceUpdateRequest bean);
|
||||||
|
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
package cn.iocoder.mall.system.api.dto.resource;
|
package cn.iocoder.mall.system.rest.request.authorization;
|
||||||
|
|
||||||
import cn.iocoder.common.framework.validator.InEnum;
|
import cn.iocoder.common.framework.validator.InEnum;
|
||||||
import cn.iocoder.mall.system.api.constant.ResourceTypeEnum;
|
import cn.iocoder.mall.system.biz.enums.authorization.ResourceTypeEnum;
|
||||||
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;
|
||||||
@ -9,13 +9,11 @@ import lombok.experimental.Accessors;
|
|||||||
|
|
||||||
import javax.validation.constraints.NotEmpty;
|
import javax.validation.constraints.NotEmpty;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@ApiModel("资源添加 DTO")
|
@ApiModel("管理员 - 资源模块 - 添加资源 Request")
|
||||||
@Data
|
@Data
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
public class ResourceAddDTO implements Serializable {
|
public class AdminsResourceAddRequest {
|
||||||
|
|
||||||
@ApiModelProperty(value = "资源类型。1 代表【菜单】;2 代表【按钮】", required = true, example = "1")
|
@ApiModelProperty(value = "资源类型。1 代表【菜单】;2 代表【按钮】", required = true, example = "1")
|
||||||
@NotNull(message = "类型不能为空")
|
@NotNull(message = "类型不能为空")
|
||||||
@ -26,21 +24,21 @@ public class ResourceAddDTO implements Serializable {
|
|||||||
@NotNull(message = "类型不能为空")
|
@NotNull(message = "类型不能为空")
|
||||||
private Integer sort;
|
private Integer sort;
|
||||||
|
|
||||||
@ApiModelProperty(value = "菜单展示名", required = true, example = "商品管理")
|
@ApiModelProperty(value = "菜单名", required = true, example = "商品管理")
|
||||||
@NotEmpty(message = "资源名字不能为空")
|
@NotEmpty(message = "菜单名不能为空")
|
||||||
private String displayName;
|
private String name;
|
||||||
|
|
||||||
@ApiModelProperty(value = "父级资源编号", required = true, example = "1")
|
@ApiModelProperty(value = "父级资源编号", required = true, example = "1")
|
||||||
@NotNull(message = "父级资源编号不能为空")
|
@NotNull(message = "父级资源编号不能为空")
|
||||||
private Integer pid;
|
private Integer pid;
|
||||||
|
|
||||||
@ApiModelProperty(value = "操作", example = "/order/list")
|
@ApiModelProperty(value = "前端路由", example = "/order/list")
|
||||||
private String handler;
|
private String route;
|
||||||
|
|
||||||
@ApiModelProperty(value = "图标", example = "add")
|
@ApiModelProperty(value = "图标", example = "add")
|
||||||
private String icon;
|
private String icon;
|
||||||
|
|
||||||
@ApiModelProperty(value = "权限标识数组", example = "system.order.add,system.order.update")
|
@ApiModelProperty(value = "权限标识", example = "permission")
|
||||||
private List<String> permissions;
|
private String permission;
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package cn.iocoder.mall.system.rest.request.authorization;
|
||||||
|
|
||||||
|
import cn.iocoder.common.framework.validator.InEnum;
|
||||||
|
import cn.iocoder.mall.system.biz.enums.authorization.ResourceTypeEnum;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
@ApiModel("管理员 - 资源模块 - 更新资源 Request")
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class AdminsResourceUpdateRequest {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "资源编号", required = true, example = "1")
|
||||||
|
@NotNull(message = "资源编号不能为空")
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "资源类型。1 代表【菜单】;2 代表【按钮】", required = true, example = "1")
|
||||||
|
@NotNull(message = "类型不能为空")
|
||||||
|
@InEnum(value = ResourceTypeEnum.class, message = "资源类型必须是 {value}")
|
||||||
|
private Integer type;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "排序", required = true, example = "1")
|
||||||
|
@NotNull(message = "类型不能为空")
|
||||||
|
private Integer sort;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "菜单名", required = true, example = "商品管理")
|
||||||
|
@NotEmpty(message = "菜单名不能为空")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "父级资源编号", required = true, example = "1")
|
||||||
|
@NotNull(message = "父级资源编号不能为空")
|
||||||
|
private Integer pid;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "前端路由", example = "/order/list")
|
||||||
|
private String route;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "图标", example = "add")
|
||||||
|
private String icon;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "权限标识", example = "permission")
|
||||||
|
private String permission;
|
||||||
|
|
||||||
|
}
|
@ -16,13 +16,10 @@ public class AdminsAuthorizationMenuTreeResponse {
|
|||||||
private Integer id;
|
private Integer id;
|
||||||
@ApiModelProperty(value = "菜单名", required = true, example = "商品管理")
|
@ApiModelProperty(value = "菜单名", required = true, example = "商品管理")
|
||||||
private String name;
|
private String name;
|
||||||
|
@ApiModelProperty(value = "前端路由", required = true, example = "/order/list")
|
||||||
@ApiModelProperty(value = "排序", required = true, example = "1")
|
|
||||||
private Integer sort;
|
|
||||||
@ApiModelProperty(value = "父菜单编号", required = true, example = "1", notes = "如果无父菜单,则值为 0")
|
|
||||||
private Integer pid;
|
|
||||||
@ApiModelProperty(value = "route", required = true, example = "/order/list")
|
|
||||||
private String route;
|
private String route;
|
||||||
|
@ApiModelProperty(value = "菜单图标", required = true, example = "user")
|
||||||
|
private String icon;
|
||||||
@ApiModelProperty(value = "子节点数组")
|
@ApiModelProperty(value = "子节点数组")
|
||||||
private List<AdminsAuthorizationMenuTreeResponse> children;
|
private List<AdminsAuthorizationMenuTreeResponse> children;
|
||||||
|
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
package cn.iocoder.mall.system.rest.response.authorization;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@ApiModel("管理员 - 授权模块 - 菜单资源树")
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class AdminsResourceTreeResponse {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "菜单编号", required = true, example = "1")
|
||||||
|
private Integer id;
|
||||||
|
@ApiModelProperty(value = "菜单名", required = true, example = "商品管理")
|
||||||
|
private String name;
|
||||||
|
@ApiModelProperty(value = "权限标识", example = "/order/list")
|
||||||
|
private String permission;
|
||||||
|
@ApiModelProperty(value = "资源类型", required = true, example = "1-菜单;2-按钮")
|
||||||
|
private Integer type;
|
||||||
|
@ApiModelProperty(value = "排序", required = true, example = "1")
|
||||||
|
private Integer sort;
|
||||||
|
@ApiModelProperty(value = "父菜单编号", required = true, example = "1", notes = "如果无父菜单,则值为 0")
|
||||||
|
private Integer pid;
|
||||||
|
@ApiModelProperty(value = "前端路由", example = "/order/list")
|
||||||
|
private String route;
|
||||||
|
@ApiModelProperty(value = "菜单图标", example = "user")
|
||||||
|
private String icon;
|
||||||
|
/**
|
||||||
|
* 子节点数组
|
||||||
|
*/
|
||||||
|
private List<AdminsResourceTreeResponse> children;
|
||||||
|
|
||||||
|
}
|
@ -1,36 +0,0 @@
|
|||||||
package cn.iocoder.mall.system.api;
|
|
||||||
|
|
||||||
import cn.iocoder.mall.system.api.bo.resource.ResourceBO;
|
|
||||||
import cn.iocoder.mall.system.api.dto.resource.ResourceAddDTO;
|
|
||||||
import cn.iocoder.mall.system.api.dto.resource.ResourceUpdateDTO;
|
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public interface ResourceService {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询指定类型 + 指定角色的资源列表
|
|
||||||
*
|
|
||||||
* @param type 指定类型。可以为空,此时不作为过滤条件
|
|
||||||
* @param roleIds 指定角色的数组。
|
|
||||||
* @return 资源列表
|
|
||||||
*/
|
|
||||||
List<ResourceBO> getResourcesByTypeAndRoleIds(@Nullable Integer type, Set<Integer> roleIds);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询指定类型的资源列表
|
|
||||||
*
|
|
||||||
* @param type 指定类型。可以为空,此时不做为过滤条件
|
|
||||||
* @return 资源列表
|
|
||||||
*/
|
|
||||||
List<ResourceBO> getResourcesByType(@Nullable Integer type);
|
|
||||||
|
|
||||||
ResourceBO addResource(Integer adminId, ResourceAddDTO resourceAddDTO);
|
|
||||||
|
|
||||||
Boolean updateResource(Integer adminId, ResourceUpdateDTO resourceUpdateDTO);
|
|
||||||
|
|
||||||
Boolean deleteResource(Integer adminId, Integer resourceId);
|
|
||||||
|
|
||||||
}
|
|
@ -1,148 +0,0 @@
|
|||||||
package cn.iocoder.mall.admin.service;
|
|
||||||
|
|
||||||
import cn.iocoder.common.framework.constant.DeletedStatusEnum;
|
|
||||||
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
|
|
||||||
import cn.iocoder.common.framework.util.StringUtil;
|
|
||||||
import cn.iocoder.mall.system.api.ResourceService;
|
|
||||||
import cn.iocoder.mall.system.api.bo.resource.ResourceBO;
|
|
||||||
import cn.iocoder.mall.system.api.constant.AdminErrorCodeEnum;
|
|
||||||
import cn.iocoder.mall.system.api.constant.ResourceConstants;
|
|
||||||
import cn.iocoder.mall.system.api.dto.resource.ResourceAddDTO;
|
|
||||||
import cn.iocoder.mall.system.api.dto.resource.ResourceUpdateDTO;
|
|
||||||
import cn.iocoder.mall.admin.convert.ResourceConvert;
|
|
||||||
import cn.iocoder.mall.admin.dao.ResourceMapper;
|
|
||||||
import cn.iocoder.mall.admin.dao.RoleResourceMapper;
|
|
||||||
import cn.iocoder.mall.admin.dataobject.ResourceDO;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@org.apache.dubbo.config.annotation.Service(validation = "true", version = "${dubbo.provider.ResourceService.version}")
|
|
||||||
public class ResourceServiceImpl implements ResourceService {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ResourceMapper resourceMapper;
|
|
||||||
@Autowired
|
|
||||||
private RoleResourceMapper roleResourceMapper;
|
|
||||||
|
|
||||||
public List<ResourceDO> getResourceListByPermission(String permission) {
|
|
||||||
List<ResourceDO> resources = resourceMapper.selectListByPermission(permission);
|
|
||||||
if (resources.isEmpty()) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
// 因为 ResourceDO 存储的 permissions 是字符串,使用逗号分隔,需要进一步判断
|
|
||||||
resources.removeIf(resourceDO -> !StringUtil.split(resourceDO.getPermissions(), ",").contains(permission));
|
|
||||||
return resources;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<ResourceBO> getResourcesByTypeAndRoleIds(Integer type, Set<Integer> roleIds) {
|
|
||||||
if (roleIds == null || roleIds.isEmpty()) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
return ResourceConvert.INSTANCE.convert(resourceMapper.selectListByTypeAndRoleIds(type, roleIds));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<ResourceBO> getResourcesByType(Integer type) {
|
|
||||||
return ResourceConvert.INSTANCE.convert(resourceMapper.selectListByType (type));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceBO addResource(Integer adminId, ResourceAddDTO resourceAddDTO) {
|
|
||||||
// 校验父资源存在
|
|
||||||
checkParentResource(resourceAddDTO.getPid(), null);
|
|
||||||
// 存储到数据库
|
|
||||||
ResourceDO resource = ResourceConvert.INSTANCE.convert(resourceAddDTO);
|
|
||||||
initResourceProperty(resource);
|
|
||||||
resource.setCreateTime(new Date());
|
|
||||||
resource.setDeleted(DeletedStatusEnum.DELETED_NO.getValue());
|
|
||||||
resourceMapper.insert(resource);
|
|
||||||
// TODO 操作日志
|
|
||||||
// 返回成功
|
|
||||||
return ResourceConvert.INSTANCE.convert(resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Boolean updateResource(Integer adminId, ResourceUpdateDTO resourceUpdateDTO) {
|
|
||||||
// 校验更新的资源是否存在
|
|
||||||
if (resourceMapper.selectById(resourceUpdateDTO.getId()) == null) {
|
|
||||||
throw ServiceExceptionUtil.exception(AdminErrorCodeEnum.RESOURCE_NOT_EXISTS.getCode());
|
|
||||||
}
|
|
||||||
// 校验父资源存在
|
|
||||||
checkParentResource(resourceUpdateDTO.getPid(), resourceUpdateDTO.getId());
|
|
||||||
// 更新到数据库
|
|
||||||
ResourceDO resource = ResourceConvert.INSTANCE.convert(resourceUpdateDTO);
|
|
||||||
initResourceProperty(resource);
|
|
||||||
resourceMapper.updateById(resource);
|
|
||||||
// TODO 操作日志
|
|
||||||
// 返回成功
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional
|
|
||||||
public Boolean deleteResource(Integer adminId, Integer resourceId) {
|
|
||||||
// 校验更新的资源是否存在
|
|
||||||
if (resourceMapper.selectById(resourceId) == null) {
|
|
||||||
throw ServiceExceptionUtil.exception(AdminErrorCodeEnum.RESOURCE_NOT_EXISTS.getCode());
|
|
||||||
}
|
|
||||||
// 校验是否还有子资源
|
|
||||||
if (resourceMapper.selectCountByPid(resourceId) > 0) {
|
|
||||||
throw ServiceExceptionUtil.exception(AdminErrorCodeEnum.RESOURCE_EXISTS_CHILDREN.getCode());
|
|
||||||
}
|
|
||||||
// 更新到数据库
|
|
||||||
resourceMapper.deleteById(resourceId);
|
|
||||||
// 删除资源关联表
|
|
||||||
roleResourceMapper.deleteByResourceId(resourceId);
|
|
||||||
// 返回成功
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ResourceDO> getResources(Set<Integer> resourceIds) {
|
|
||||||
if (resourceIds == null || resourceIds.isEmpty()) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
return resourceMapper.selectListByIds(resourceIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkParentResource(Integer pid, Integer childId) {
|
|
||||||
if (pid == null || ResourceConstants.PID_ROOT.equals(pid)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (pid.equals(childId)) { // 不能设置自己为父资源
|
|
||||||
throw ServiceExceptionUtil.exception(AdminErrorCodeEnum.RESOURCE_PARENT_ERROR.getCode());
|
|
||||||
}
|
|
||||||
ResourceDO resource = resourceMapper.selectById(pid);
|
|
||||||
if (resource == null) { // 父资源不存在
|
|
||||||
throw ServiceExceptionUtil.exception(AdminErrorCodeEnum.RESOURCE_PARENT_NOT_EXISTS.getCode());
|
|
||||||
}
|
|
||||||
if (!ResourceConstants.TYPE_MENU.equals(resource.getType())) { // 父资源必须是菜单类型
|
|
||||||
throw ServiceExceptionUtil.exception(AdminErrorCodeEnum.RESOURCE_PARENT_NOT_MENU.getCode());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化资源的通用属性。
|
|
||||||
*
|
|
||||||
* 例如说,只有菜单类型的资源,才设置 icon
|
|
||||||
*
|
|
||||||
* @param resource 资源
|
|
||||||
*/
|
|
||||||
private void initResourceProperty(ResourceDO resource) {
|
|
||||||
if (resource.getPid() == null) {
|
|
||||||
resource.setPid(ResourceConstants.PID_ROOT);
|
|
||||||
}
|
|
||||||
if (ResourceConstants.TYPE_BUTTON.equals(resource.getType())) {
|
|
||||||
resource.setHandler(null);
|
|
||||||
resource.setIcon(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -9,17 +9,8 @@ import cn.iocoder.mall.system.api.bo.role.RoleBO;
|
|||||||
import cn.iocoder.mall.system.api.constant.AdminErrorCodeEnum;
|
import cn.iocoder.mall.system.api.constant.AdminErrorCodeEnum;
|
||||||
import cn.iocoder.mall.system.api.dto.role.RoleAddDTO;
|
import cn.iocoder.mall.system.api.dto.role.RoleAddDTO;
|
||||||
import cn.iocoder.mall.system.api.dto.role.RoleAssignResourceDTO;
|
import cn.iocoder.mall.system.api.dto.role.RoleAssignResourceDTO;
|
||||||
import cn.iocoder.mall.system.api.dto.role.RolePageDTO;
|
|
||||||
import cn.iocoder.mall.system.api.dto.role.RoleUpdateDTO;
|
import cn.iocoder.mall.system.api.dto.role.RoleUpdateDTO;
|
||||||
import cn.iocoder.mall.admin.convert.RoleConvert;
|
import cn.iocoder.mall.admin.convert.RoleConvert;
|
||||||
import cn.iocoder.mall.admin.dao.AdminRoleMapper;
|
|
||||||
import cn.iocoder.mall.admin.dao.RoleMapper;
|
|
||||||
import cn.iocoder.mall.admin.dao.RoleResourceMapper;
|
|
||||||
import cn.iocoder.mall.admin.dataobject.ResourceDO;
|
|
||||||
import cn.iocoder.mall.admin.dataobject.RoleDO;
|
|
||||||
import cn.iocoder.mall.admin.dataobject.RoleResourceDO;
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@ -150,34 +141,4 @@ public class RoleServiceImpl implements RoleService {
|
|||||||
return roleMapper.selectBatchIds(roleIds);
|
return roleMapper.selectBatchIds(roleIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得权限与角色的映射关系。
|
|
||||||
*
|
|
||||||
* TODO 芋艿,等以后有 redis ,优化成从缓存读取。每个 permission ,哪些角色可以访问
|
|
||||||
*
|
|
||||||
* @param permissions 权限标识数组
|
|
||||||
* @return 映射关系。KEY:权限标识;VALUE:角色编号数组
|
|
||||||
*/
|
|
||||||
public Map<String, List<Integer>> getPermissionRoleMap(List<String> permissions) {
|
|
||||||
if (CollectionUtil.isEmpty(permissions)) {
|
|
||||||
return Collections.emptyMap();
|
|
||||||
}
|
|
||||||
Map<String, List<Integer>> result = Maps.newHashMapWithExpectedSize(permissions.size());
|
|
||||||
for (String permission : permissions) {
|
|
||||||
List<ResourceDO> resources = resourceService.getResourceListByPermission(permission);
|
|
||||||
if (resources.isEmpty()) { // 无需授权
|
|
||||||
result.put(permission, Collections.emptyList());
|
|
||||||
} else {
|
|
||||||
List<RoleResourceDO> roleResources = roleResourceMapper.selectListByResourceId(
|
|
||||||
CollectionUtil.convertSet(resources, ResourceDO::getId));
|
|
||||||
if (roleResources.isEmpty()) {
|
|
||||||
result.put(permission, Collections.emptyList());
|
|
||||||
} else {
|
|
||||||
result.put(permission, CollectionUtil.convertList(roleResources, RoleResourceDO::getRoleId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user