diff --git a/admin-web/src/models/admin/resourceList.js b/admin-web/src/models/admin/resourceList.js
index f3d723e81..1859d53af 100644
--- a/admin-web/src/models/admin/resourceList.js
+++ b/admin-web/src/models/admin/resourceList.js
@@ -1,5 +1,5 @@
import { message } from 'antd';
-import { addResource, updateResource, deleteResource, resourceTree } from '../../services/admin';
+import { resourceTree, resourceAdd, resourceUpdate, resourceDelete } from '../../services/system';
const buildSelectTree = list => {
return list.map(item => {
@@ -8,8 +8,8 @@ const buildSelectTree = list => {
children = buildSelectTree(item.children);
}
return {
- title: item.displayName,
- value: `${item.displayName}-${item.id}`,
+ title: item.name,
+ value: `${item.name}-${item.id}`,
key: item.id,
children,
};
@@ -27,7 +27,7 @@ export default {
effects: {
*add({ payload }, { call, put }) {
const { callback, body } = payload;
- const response = yield call(addResource, body);
+ const response = yield call(resourceAdd, body);
if (callback) {
callback(response);
}
@@ -38,7 +38,7 @@ export default {
},
*update({ payload }, { call, put }) {
const { callback, body } = payload;
- const response = yield call(updateResource, body);
+ const response = yield call(resourceUpdate, body);
if (callback) {
callback(response);
}
@@ -48,7 +48,7 @@ export default {
});
},
*delete({ payload }, { call, put }) {
- yield call(deleteResource, payload);
+ yield call(resourceDelete, payload);
message.info('删除成功!');
yield put({
type: 'tree',
@@ -71,7 +71,7 @@ export default {
const resultData = payload;
const treeData = buildSelectTree(resultData);
- // value 要保护 displayName 不然,搜索会失效
+ // value 要保护 name 不然,搜索会失效
const rootNode = [
{
title: '根节点',
diff --git a/admin-web/src/pages/Admin/ResourceList.js b/admin-web/src/pages/Admin/ResourceList.js
index 31fc8ca1d..fb81ac897 100644
--- a/admin-web/src/pages/Admin/ResourceList.js
+++ b/admin-web/src/pages/Admin/ResourceList.js
@@ -89,9 +89,9 @@ const CreateForm = Form.create()(props => {
)}
- {form.getFieldDecorator('displayName', {
+ {form.getFieldDecorator('name', {
rules: [{ required: true, message: '请输入名称!', min: 2 }],
- initialValue: initValues.displayName,
+ initialValue: initValues.name,
})()}
@@ -99,8 +99,8 @@ const CreateForm = Form.create()(props => {
rules: [{ required: true, message: '请选择父级编号!' }],
initialValue:
initValues.pid === 0
- ? `根节点-${initValues.pid}`
- : initValues.pid ? `${initValues.displayName}-${initValues.pid}` : undefined,
+ ? `根节点`
+ : initValues.pid ? `${initValues.name}` : undefined,
})(
{
}
{
initValues.type === 1 ? (
-
- {form.getFieldDecorator('handler', {
- initialValue: initValues.handler,
- })()}
+
+ {form.getFieldDecorator('route', {
+ initialValue: initValues.route,
+ })()}
) : ''
}
- {form.getFieldDecorator('permissions', {
- initialValue: initValues.permissions,
- })()}
+ {form.getFieldDecorator('permission', {
+ initialValue: initValues.permission,
+ })()}
);
@@ -210,7 +210,7 @@ class ResourceList extends PureComponent {
const { dispatch } = this.props;
Modal.confirm({
title: `确认删除?`,
- content: `${row.displayName}`,
+ content: `${row.name}`,
onOk() {
dispatch({
type: 'resourceList/delete',
@@ -237,7 +237,7 @@ class ResourceList extends PureComponent {
const columns = [
{
title: '名称',
- dataIndex: 'displayName',
+ dataIndex: 'name',
},
{
title: '图标',
@@ -256,27 +256,16 @@ class ResourceList extends PureComponent {
dataIndex: 'sort',
},
{
- title: '操作',
- dataIndex: 'handler',
+ title: '路由',
+ dataIndex: 'route',
width: 200,
render: val => {val},
},
{
title: '权限标识',
- dataIndex: 'permissions',
+ dataIndex: 'permission',
width: 300,
- render(permissions) {
- let text = '';
- if (permissions) {
- for (let i in permissions) {
- if (i > 0) {
- text += ' ';
- }
- text += permissions[i];
- }
- }
- return ({text});
- }
+ render: val => {val},
},
{
title: '创建时间',
diff --git a/admin-web/src/services/admin.js b/admin-web/src/services/admin.js
index 03e44d30f..b048b595f 100644
--- a/admin-web/src/services/admin.js
+++ b/admin-web/src/services/admin.js
@@ -84,29 +84,7 @@ export async function deptTreeAll() {
// 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
diff --git a/admin-web/src/services/system.js b/admin-web/src/services/system.js
index e893e4cbb..d3b4e53d9 100644
--- a/admin-web/src/services/system.js
+++ b/admin-web/src/services/system.js
@@ -23,3 +23,29 @@ export async function authorizationResourcePermissions(params) {
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',
+ });
+}
diff --git a/common/mall-spring-boot-starter-security/src/main/java/cn/iocoder/mall/security/package-info.java b/common/mall-spring-boot-starter-security/src/main/java/cn/iocoder/mall/security/package-info.java
deleted file mode 100644
index 616a4a12b..000000000
--- a/common/mall-spring-boot-starter-security/src/main/java/cn/iocoder/mall/security/package-info.java
+++ /dev/null
@@ -1 +0,0 @@
-package cn.iocoder.mall.security;
diff --git a/system/system-biz-api/src/main/java/cn/iocoder/mall/system/biz/enums/SystemErrorCodeEnum.java b/system/system-biz-api/src/main/java/cn/iocoder/mall/system/biz/enums/SystemErrorCodeEnum.java
index 07827ac86..d277cee7e 100644
--- a/system/system-biz-api/src/main/java/cn/iocoder/mall/system/biz/enums/SystemErrorCodeEnum.java
+++ b/system/system-biz-api/src/main/java/cn/iocoder/mall/system/biz/enums/SystemErrorCodeEnum.java
@@ -41,12 +41,12 @@ public enum SystemErrorCodeEnum implements ServiceExceptionUtil.Enumerable {
// ADMIN_ADMIN_CAN_NOT_UPDATE(1002002008, "管理员的账号不允许变更"),
// ========== 资源模块 1002003000 ==========
-// RESOURCE_NAME_DUPLICATE(1002003000, "已经存在该名字的资源"),
-// RESOURCE_PARENT_NOT_EXISTS(1002003001, "父资源不存在"),
-// RESOURCE_PARENT_ERROR(1002003002, "不能设置自己为父资源"),
-// RESOURCE_NOT_EXISTS(1002003003, "资源不存在"),
-// RESOURCE_EXISTS_CHILDREN(1002003004, "存在子资源,无法删除"),
-// RESOURCE_PARENT_NOT_MENU(1002003005, "父资源的类型必须是菜单"),
+ RESOURCE_NAME_DUPLICATE(1002003000, "已经存在该名字的资源"),
+ RESOURCE_PARENT_NOT_EXISTS(1002003001, "父资源不存在"),
+ RESOURCE_PARENT_ERROR(1002003002, "不能设置自己为父资源"),
+ RESOURCE_NOT_EXISTS(1002003003, "资源不存在"),
+ RESOURCE_EXISTS_CHILDREN(1002003004, "存在子资源,无法删除"),
+ RESOURCE_PARENT_NOT_MENU(1002003005, "父资源的类型必须是菜单"),
// ========== 角色模块 1002004000 ==========
// ROLE_NOT_EXISTS(1002004000, "角色不存在"),
diff --git a/system/system-biz-api/src/main/java/cn/iocoder/mall/system/biz/enums/authorization/ResourceTypeEnum.java b/system/system-biz-api/src/main/java/cn/iocoder/mall/system/biz/enums/authorization/ResourceTypeEnum.java
index 50c1cf2f9..851452f40 100644
--- a/system/system-biz-api/src/main/java/cn/iocoder/mall/system/biz/enums/authorization/ResourceTypeEnum.java
+++ b/system/system-biz-api/src/main/java/cn/iocoder/mall/system/biz/enums/authorization/ResourceTypeEnum.java
@@ -12,24 +12,24 @@ public enum ResourceTypeEnum implements IntArrayValuable {
MENU(1, "菜单"),
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;
- ResourceTypeEnum(Integer value, String name) {
- this.value = value;
+ ResourceTypeEnum(Integer type, String name) {
+ this.type = type;
this.name = name;
}
- public Integer getValue() {
- return value;
+ public Integer getType() {
+ return type;
}
public String getName() {
diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/bo/authorization/ResourceTreeNodeBO.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/bo/authorization/ResourceTreeNodeBO.java
new file mode 100644
index 000000000..db124ca94
--- /dev/null
+++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/bo/authorization/ResourceTreeNodeBO.java
@@ -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 children;
+
+}
diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/convert/authorization/ResourceConvert.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/convert/authorization/ResourceConvert.java
index 5e395f915..33bb60a1e 100644
--- a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/convert/authorization/ResourceConvert.java
+++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/convert/authorization/ResourceConvert.java
@@ -1,8 +1,12 @@
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.ResourceTreeNodeBO;
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.Mapping;
import org.mapstruct.factory.Mappers;
import java.util.List;
@@ -14,6 +18,13 @@ public interface ResourceConvert {
ResourceBO convert(ResourceDO bean);
+ @Mapping(source = "bean", target = "node")
+ ResourceTreeNodeBO convertTreeNode(ResourceDO bean);
+
List convertList(List beans);
+ ResourceDO convert(ResourceAddDTO bean);
+
+ ResourceDO convert(ResourceUpdateDTO bean);
+
}
diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dataobject/authorization/RoleDO.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dataobject/authorization/RoleDO.java
index ec97a9f23..1d803693b 100644
--- a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dataobject/authorization/RoleDO.java
+++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dataobject/authorization/RoleDO.java
@@ -29,8 +29,6 @@ public class RoleDO extends DeletableDO {
private String code;
/**
* 角色类型
- *
- * TODO 需要补充
*/
private Integer type;
diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/authorization/AuthorizationGetResourceTreeByAccountIdDTO.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/authorization/AuthorizationGetResourceTreeByAccountIdDTO.java
new file mode 100644
index 000000000..c1bea98e4
--- /dev/null
+++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/authorization/AuthorizationGetResourceTreeByAccountIdDTO.java
@@ -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;
+
+}
diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/authorization/AuthorizationGetResourcesByAccountIdDTO.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/authorization/AuthorizationGetResourcesByAccountIdDTO.java
index 3eec850b8..a59f14867 100644
--- a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/authorization/AuthorizationGetResourcesByAccountIdDTO.java
+++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/authorization/AuthorizationGetResourcesByAccountIdDTO.java
@@ -6,7 +6,7 @@ import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
/**
- * 授权模块 - 获得账号所拥有的资源 DTO
+ * 授权模块 - 获得账号所拥有的资源列表 DTO
*/
@Data
@Accessors(chain = true)
diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/authorization/ResourceAddDTO.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/authorization/ResourceAddDTO.java
new file mode 100644
index 000000000..86e27ecef
--- /dev/null
+++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/authorization/ResourceAddDTO.java
@@ -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;
+
+}
diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/authorization/ResourceDeleteDTO.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/authorization/ResourceDeleteDTO.java
new file mode 100644
index 000000000..c6bc835f6
--- /dev/null
+++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/authorization/ResourceDeleteDTO.java
@@ -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;
+
+}
diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/authorization/ResourceGetTreeDTO.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/authorization/ResourceGetTreeDTO.java
new file mode 100644
index 000000000..afdfb9cc0
--- /dev/null
+++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/authorization/ResourceGetTreeDTO.java
@@ -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 ids;
+
+ /**
+ * 资源类型
+ */
+ private Integer type;
+
+}
diff --git a/system/system-service-api/src/main/java/cn/iocoder/mall/system/api/dto/resource/ResourceUpdateDTO.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/authorization/ResourceUpdateDTO.java
similarity index 84%
rename from system/system-service-api/src/main/java/cn/iocoder/mall/system/api/dto/resource/ResourceUpdateDTO.java
rename to system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/authorization/ResourceUpdateDTO.java
index 75d744d25..e3aea1812 100644
--- a/system/system-service-api/src/main/java/cn/iocoder/mall/system/api/dto/resource/ResourceUpdateDTO.java
+++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/authorization/ResourceUpdateDTO.java
@@ -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.mall.system.api.constant.ResourceTypeEnum;
-import io.swagger.annotations.ApiModel;
+import cn.iocoder.mall.system.biz.enums.authorization.ResourceTypeEnum;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
-import java.io.Serializable;
import java.util.List;
-@ApiModel("资源更新 DTO")
+/**
+ * 资源模块 - 更新资源 DTO
+ */
@Data
@Accessors(chain = true)
-public class ResourceUpdateDTO implements Serializable {
+public class ResourceUpdateDTO {
+
+ @NotNull(message = "管理员编号不能为空")
+ private Integer adminId;
@ApiModelProperty(value = "资源编号", required = true, example = "1")
@NotNull(message = "资源编号不能为空")
diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/event/authorization/ResourceDeleteEvent.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/event/authorization/ResourceDeleteEvent.java
new file mode 100644
index 000000000..795fe9987
--- /dev/null
+++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/event/authorization/ResourceDeleteEvent.java
@@ -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;
+ }
+
+}
diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/event/package-info.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/event/package-info.java
new file mode 100644
index 000000000..eb9461bba
--- /dev/null
+++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/event/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * Spring 事件机制
+ *
+ * 不了解的胖友,可以阅读 http://www.iocoder.cn/Spring-Boot/Event/?onemall 文章
+ */
+package cn.iocoder.mall.system.biz.event;
diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/authorization/AuthorizationService.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/authorization/AuthorizationService.java
index 7f47c2c01..ba92ba8aa 100644
--- a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/authorization/AuthorizationService.java
+++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/authorization/AuthorizationService.java
@@ -2,6 +2,7 @@ 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.ResourceTreeNodeBO;
import cn.iocoder.mall.system.biz.dto.authorization.AuthorizationCheckPermissionsDTO;
import cn.iocoder.mall.system.biz.dto.authorization.AuthorizationGetResourcesByAccountIdDTO;
@@ -25,8 +26,18 @@ public interface AuthorizationService {
* 如果该账号为超级管理员,则返回所有资源
*
* @param getResourcesByAccountIdDTO 查询条件 DTO
- * @return 列表
+ * @return 资源列表
*/
List getResourcesByAccountId(AuthorizationGetResourcesByAccountIdDTO getResourcesByAccountIdDTO);
+ /**
+ * 获得指定账号的资源树
+ *
+ * 如果该账号为超级管理员,则返回所有资源
+ *
+ * @param getResourceTreeByAccountIdDTO 查询条件 DTO
+ * @return 资源树
+ */
+ List getResourceTreeByAccountId(AuthorizationGetResourcesByAccountIdDTO getResourceTreeByAccountIdDTO);
+
}
diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/authorization/AuthorizationServiceImpl.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/authorization/AuthorizationServiceImpl.java
index 40dabbbe7..4370d7e54 100644
--- a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/authorization/AuthorizationServiceImpl.java
+++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/authorization/AuthorizationServiceImpl.java
@@ -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.ServiceExceptionUtil;
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.RoleResourceMapper;
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.AuthorizationGetResourcesByAccountIdDTO;
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 org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import java.util.Collections;
@@ -89,8 +93,35 @@ public class AuthorizationServiceImpl implements AuthorizationService {
return Collections.emptyList();
}
Set resourceIds = CollectionUtil.convertSet(roleResourceDOs, RoleResourceDO::getResourceId);
- // 查询对应资源
+ // 查询对应资源列表
return resourceService.getResources(new ResourceGetListDTO().setIds(resourceIds).setType(getResourcesByAccountIdDTO.getType()));
}
+ @Override
+ public List getResourceTreeByAccountId(AuthorizationGetResourcesByAccountIdDTO getResourcesByAccountIdDTO) {
+ // 查询管理员拥有的角色关联数据
+ List accountRoleDOs = accountRoleMapper.selectByAccountId(getResourcesByAccountIdDTO.getAccountId());
+ if (CollectionUtil.isEmpty(accountRoleDOs)) {
+ return Collections.emptyList();
+ }
+ Set roleIds = CollectionUtil.convertSet(accountRoleDOs, AccountRoleDO::getRoleId);
+ // 判断是否为超管。若是超管,默认有所有权限
+ if (roleService.hasSuperAdmin(roleIds)) {
+ return resourceService.getResourceTree(new ResourceGetTreeDTO().setType(getResourcesByAccountIdDTO.getType()));
+ }
+ // 查询角色拥有的资源关联数据
+ List roleResourceDOs = roleResourceMapper.selectListByRoleIds(roleIds);
+ if (CollectionUtil.isEmpty(roleResourceDOs)) {
+ return Collections.emptyList();
+ }
+ Set 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());
+ }
+
}
diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/authorization/ResourceService.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/authorization/ResourceService.java
index 19ac4e6ec..ec7cdb877 100644
--- a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/authorization/ResourceService.java
+++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/authorization/ResourceService.java
@@ -1,15 +1,38 @@
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.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.List;
+/**
+ * 资源模块 - Service 接口
+ */
public interface ResourceService {
List getResourcesByPermissions(Collection permissions);
List getResources(ResourceGetListDTO getListDTO);
+ List getResourceTree(ResourceGetTreeDTO getTreeDTO);
+
+ Integer addResource(ResourceAddDTO addDTO);
+
+ /**
+ * 更新资源。如果更新失败,则抛出 {@link ServiceException} 异常
+ *
+ * @param updateDTO 更新资源
+ */
+ void updateResource(ResourceUpdateDTO updateDTO);
+
+ /**
+ * 删除资源。如果删除失败,则抛出 {@link ServiceException} 异常
+ *
+ * @param deleteDTO 删除资源
+ */
+ void deleteResource(ResourceDeleteDTO deleteDTO);
+
}
diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/authorization/ResourceServiceImpl.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/authorization/ResourceServiceImpl.java
index 637e5a053..e2088cd0e 100644
--- a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/authorization/ResourceServiceImpl.java
+++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/authorization/ResourceServiceImpl.java
@@ -1,19 +1,32 @@
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.ResourceTreeNodeBO;
import cn.iocoder.mall.system.biz.convert.authorization.ResourceConvert;
import cn.iocoder.mall.system.biz.dao.authorization.ResourceMapper;
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.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
-import java.util.Collection;
-import java.util.List;
+import java.util.*;
+import java.util.stream.Collectors;
@Service
+@Slf4j
public class ResourceServiceImpl implements ResourceService {
+ @Autowired
+ private ApplicationEventPublisher eventPublisher;
+
@Autowired
private ResourceMapper resourceMapper;
@@ -29,4 +42,122 @@ public class ResourceServiceImpl implements ResourceService {
return ResourceConvert.INSTANCE.convertList(resourceDOs);
}
+ @Override
+ public List getResourceTree(ResourceGetTreeDTO getTreeDTO) {
+ // 获得对应的资源列表
+ List resourceDOs = resourceMapper.selectListByIdsAndType(getTreeDTO.getIds(), getTreeDTO.getType());
+ // 拼装成树
+ // 使用 LinkedHashMap 的原因,是为了排序 。实际也可以用 Stream API ,就是太丑了。
+ Map 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);
+ }
+ }
+
}
diff --git a/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/controller/authorization/AdminsAuthorizationController.java b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/controller/authorization/AdminsAuthorizationController.java
index 3ca5f6500..03045773e 100644
--- a/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/controller/authorization/AdminsAuthorizationController.java
+++ b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/controller/authorization/AdminsAuthorizationController.java
@@ -4,8 +4,8 @@ import cn.iocoder.common.framework.constant.MallConstants;
import cn.iocoder.common.framework.vo.CommonResult;
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.ResourceTreeNodeBO;
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.service.authorization.AuthorizationService;
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.RestController;
-import java.util.*;
+import java.util.List;
+import java.util.Set;
import java.util.stream.Collectors;
@RestController
@@ -33,34 +34,9 @@ public class AdminsAuthorizationController {
@GetMapping("/menu-resource-tree")
@ApiOperation(value = "获得当前账号的菜单资源树", notes = "以树结构返回")
public CommonResult> menuResourceTree() {
- List resources = authorizationService.getResourcesByAccountId(new AuthorizationGetResourcesByAccountIdDTO()
- .setAccountId(AdminSecurityContextHolder.getAccountId()).setType(ResourceTypeEnum.MENU.getValue()));
- // 创建 AdminMenuTreeNodeVO Map
- // 使用 LinkedHashMap 的原因,是为了排序 。实际也可以用 Stream API ,就是太丑了。
- Map 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 rootNodes = treeNodeMap.values().stream()
- .filter(node -> node.getPid().equals(ResourceIdEnum.ROOT.getId()))
- .collect(Collectors.toList());
- return CommonResult.success(rootNodes);
+ List resourceTreeNodeBOs = authorizationService.getResourceTreeByAccountId(new AuthorizationGetResourcesByAccountIdDTO()
+ .setAccountId(AdminSecurityContextHolder.getAccountId()).setType(ResourceTypeEnum.MENU.getType()));
+ return CommonResult.success(AdminsAuthorizationConvert.INSTANCE.convertList(resourceTreeNodeBOs));
}
@GetMapping("/resource-permissions")
diff --git a/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/controller/authorization/AdminsResourceController.java b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/controller/authorization/AdminsResourceController.java
new file mode 100644
index 000000000..2be846d6e
--- /dev/null
+++ b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/controller/authorization/AdminsResourceController.java
@@ -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> tree() {
+ List resourceTreeNodeBOs = resourceService.getResourceTree(new ResourceGetTreeDTO());
+ return CommonResult.success(AdminsResourceConvert.INSTANCE.convertList(resourceTreeNodeBOs));
+ }
+
+ @PostMapping("/add")
+ @ApiOperation(value = "创建资源", notes = "例如说,菜单资源,按钮资源")
+ @RequiresPermissions("system:resource:add")
+ public CommonResult 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 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 delete(@RequestParam("id") Integer id) {
+ ResourceDeleteDTO deleteDTO = new ResourceDeleteDTO().setId(id)
+ .setAdminId(AdminSecurityContextHolder.getAdminId());
+ resourceService.deleteResource(deleteDTO);
+ return CommonResult.success(true);
+ }
+
+}
diff --git a/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/controller/datadict/AdminsDataDictController.java b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/controller/datadict/AdminsDataDictController.java
index 0c8e3d737..8a29ba8ed 100644
--- a/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/controller/datadict/AdminsDataDictController.java
+++ b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/controller/datadict/AdminsDataDictController.java
@@ -1,11 +1,7 @@
package cn.iocoder.mall.system.rest.controller.datadict;
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.ApiOperation;
-import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -17,13 +13,6 @@ public class AdminsDataDictController {
// @Reference(validation = "true", version = "${dubbo.provider.DataDictService.version}")
// private DataDictService dataDictService;
- @GetMapping("/demo")
- @ApiOperation(value = "数据字典全列表")
- @RequiresPermissions("system.dataDict.list")
- public CommonResult list() {
- return CommonResult.success(true);
- }
-
// @GetMapping("/list")
// @ApiOperation(value = "数据字典全列表")
// @RequiresPermissions("system.dataDict.list")
diff --git a/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/convert/authorization/AdminsAuthorizationConvert.java b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/convert/authorization/AdminsAuthorizationConvert.java
index 32f57595e..e9ee97df5 100644
--- a/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/convert/authorization/AdminsAuthorizationConvert.java
+++ b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/convert/authorization/AdminsAuthorizationConvert.java
@@ -1,10 +1,14 @@
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.ResourceTreeNodeBO;
import cn.iocoder.mall.system.rest.response.authorization.AdminsAuthorizationMenuTreeResponse;
import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
+import java.util.List;
+
@Mapper
public interface AdminsAuthorizationConvert {
@@ -12,4 +16,12 @@ public interface AdminsAuthorizationConvert {
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 convertList(List beans);
+
}
diff --git a/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/convert/authorization/AdminsResourceConvert.java b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/convert/authorization/AdminsResourceConvert.java
new file mode 100644
index 000000000..6e6b5939e
--- /dev/null
+++ b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/convert/authorization/AdminsResourceConvert.java
@@ -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 convertList(List beans);
+
+ ResourceAddDTO convert(AdminsResourceAddRequest bean);
+
+ ResourceUpdateDTO convert(AdminsResourceUpdateRequest bean);
+
+}
diff --git a/system/system-service-api/src/main/java/cn/iocoder/mall/system/api/dto/resource/ResourceAddDTO.java b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/authorization/AdminsResourceAddRequest.java
similarity index 60%
rename from system/system-service-api/src/main/java/cn/iocoder/mall/system/api/dto/resource/ResourceAddDTO.java
rename to system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/authorization/AdminsResourceAddRequest.java
index a2f99d010..0c740e0ea 100644
--- a/system/system-service-api/src/main/java/cn/iocoder/mall/system/api/dto/resource/ResourceAddDTO.java
+++ b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/authorization/AdminsResourceAddRequest.java
@@ -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.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 lombok.Data;
@@ -9,13 +9,11 @@ import lombok.experimental.Accessors;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
-import java.io.Serializable;
-import java.util.List;
-@ApiModel("资源添加 DTO")
+@ApiModel("管理员 - 资源模块 - 添加资源 Request")
@Data
@Accessors(chain = true)
-public class ResourceAddDTO implements Serializable {
+public class AdminsResourceAddRequest {
@ApiModelProperty(value = "资源类型。1 代表【菜单】;2 代表【按钮】", required = true, example = "1")
@NotNull(message = "类型不能为空")
@@ -26,21 +24,21 @@ public class ResourceAddDTO implements Serializable {
@NotNull(message = "类型不能为空")
private Integer sort;
- @ApiModelProperty(value = "菜单展示名", required = true, example = "商品管理")
- @NotEmpty(message = "资源名字不能为空")
- private String displayName;
+ @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 handler;
+ @ApiModelProperty(value = "前端路由", example = "/order/list")
+ private String route;
@ApiModelProperty(value = "图标", example = "add")
private String icon;
- @ApiModelProperty(value = "权限标识数组", example = "system.order.add,system.order.update")
- private List permissions;
+ @ApiModelProperty(value = "权限标识", example = "permission")
+ private String permission;
}
diff --git a/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/authorization/AdminsResourceUpdateRequest.java b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/authorization/AdminsResourceUpdateRequest.java
new file mode 100644
index 000000000..e33af44a8
--- /dev/null
+++ b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/authorization/AdminsResourceUpdateRequest.java
@@ -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;
+
+}
diff --git a/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/response/authorization/AdminsAuthorizationMenuTreeResponse.java b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/response/authorization/AdminsAuthorizationMenuTreeResponse.java
index 328c776b2..9b750ecd0 100644
--- a/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/response/authorization/AdminsAuthorizationMenuTreeResponse.java
+++ b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/response/authorization/AdminsAuthorizationMenuTreeResponse.java
@@ -16,13 +16,10 @@ public class AdminsAuthorizationMenuTreeResponse {
private Integer id;
@ApiModelProperty(value = "菜单名", required = true, example = "商品管理")
private String name;
-
- @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")
+ @ApiModelProperty(value = "前端路由", required = true, example = "/order/list")
private String route;
+ @ApiModelProperty(value = "菜单图标", required = true, example = "user")
+ private String icon;
@ApiModelProperty(value = "子节点数组")
private List children;
diff --git a/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/response/authorization/AdminsResourceTreeResponse.java b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/response/authorization/AdminsResourceTreeResponse.java
new file mode 100644
index 000000000..52b9cb964
--- /dev/null
+++ b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/response/authorization/AdminsResourceTreeResponse.java
@@ -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 children;
+
+}
diff --git a/system/system-service-api/src/main/java/cn/iocoder/mall/system/api/ResourceService.java b/system/system-service-api/src/main/java/cn/iocoder/mall/system/api/ResourceService.java
deleted file mode 100644
index 1ef996b47..000000000
--- a/system/system-service-api/src/main/java/cn/iocoder/mall/system/api/ResourceService.java
+++ /dev/null
@@ -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 getResourcesByTypeAndRoleIds(@Nullable Integer type, Set roleIds);
-
- /**
- * 查询指定类型的资源列表
- *
- * @param type 指定类型。可以为空,此时不做为过滤条件
- * @return 资源列表
- */
- List getResourcesByType(@Nullable Integer type);
-
- ResourceBO addResource(Integer adminId, ResourceAddDTO resourceAddDTO);
-
- Boolean updateResource(Integer adminId, ResourceUpdateDTO resourceUpdateDTO);
-
- Boolean deleteResource(Integer adminId, Integer resourceId);
-
-}
diff --git a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/ResourceServiceImpl.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/ResourceServiceImpl.java
deleted file mode 100644
index 382e8d674..000000000
--- a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/ResourceServiceImpl.java
+++ /dev/null
@@ -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 getResourceListByPermission(String permission) {
- List 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 getResourcesByTypeAndRoleIds(Integer type, Set roleIds) {
- if (roleIds == null || roleIds.isEmpty()) {
- return Collections.emptyList();
- }
- return ResourceConvert.INSTANCE.convert(resourceMapper.selectListByTypeAndRoleIds(type, roleIds));
- }
-
- @Override
- public List 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 getResources(Set 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);
- }
- }
-
-}
diff --git a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/RoleServiceImpl.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/RoleServiceImpl.java
index 1c60a2319..bb3662035 100644
--- a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/RoleServiceImpl.java
+++ b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/RoleServiceImpl.java
@@ -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.dto.role.RoleAddDTO;
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.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.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -150,34 +141,4 @@ public class RoleServiceImpl implements RoleService {
return roleMapper.selectBatchIds(roleIds);
}
- /**
- * 获得权限与角色的映射关系。
- *
- * TODO 芋艿,等以后有 redis ,优化成从缓存读取。每个 permission ,哪些角色可以访问
- *
- * @param permissions 权限标识数组
- * @return 映射关系。KEY:权限标识;VALUE:角色编号数组
- */
- public Map> getPermissionRoleMap(List permissions) {
- if (CollectionUtil.isEmpty(permissions)) {
- return Collections.emptyMap();
- }
- Map> result = Maps.newHashMapWithExpectedSize(permissions.size());
- for (String permission : permissions) {
- List resources = resourceService.getResourceListByPermission(permission);
- if (resources.isEmpty()) { // 无需授权
- result.put(permission, Collections.emptyList());
- } else {
- List 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;
- }
-
}