From 71132842515d9acfb58cce5f3f9aec66ccd9e5cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Thu, 22 Aug 2024 16:14:15 +0800 Subject: [PATCH 01/27] =?UTF-8?q?feat(REQ-2899):=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=E8=B5=84=E6=BA=90=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...PermissionRelationOperateLogSceneEnum.java | 15 ++ .../axzo/tyr/client/feign/PageElementApi.java | 25 +++ .../req/DeletePageElementCategoryReq.java | 31 +++ .../model/req/PageQueryElementV2Req.java | 53 +++++ .../SaveOrUpdatePageElementCategoryReq.java | 40 ++++ .../SaveOrUpdatePageElementComponentReq.java | 42 ++++ .../req/SaveOrUpdatePageElementPageReq.java | 59 ++++++ .../res/ListPageElementCategoryResp.java | 39 ++++ .../tyr/client/model/res/PageElementResp.java | 5 + .../permission/PageElementController.java | 43 +++- .../dao/SaasPageElementCategoryDao.java | 15 ++ .../repository/dao/SaasPageElementDao.java | 40 ++++ ...PageElementFeatureResourceRelationDao.java | 21 ++ .../entity/SaasPageElementCategory.java | 45 ++++ .../mapper/SaasPageElementCategoryMapper.java | 9 + .../SaasPageElementCategoryService.java | 21 ++ .../service/SaasPageElementService.java | 13 +- .../SaasPageElementCategoryServiceImpl.java | 174 ++++++++++++++++ .../impl/SaasPageElementServiceImpl.java | 194 ++++++++++++++++-- 19 files changed, 854 insertions(+), 30 deletions(-) create mode 100644 tyr-api/src/main/java/cn/axzo/tyr/client/model/req/DeletePageElementCategoryReq.java create mode 100644 tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PageQueryElementV2Req.java create mode 100644 tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementCategoryReq.java create mode 100644 tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementComponentReq.java create mode 100644 tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementPageReq.java create mode 100644 tyr-api/src/main/java/cn/axzo/tyr/client/model/res/ListPageElementCategoryResp.java create mode 100644 tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasPageElementCategoryDao.java create mode 100644 tyr-server/src/main/java/cn/axzo/tyr/server/repository/entity/SaasPageElementCategory.java create mode 100644 tyr-server/src/main/java/cn/axzo/tyr/server/repository/mapper/SaasPageElementCategoryMapper.java create mode 100644 tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementCategoryService.java create mode 100644 tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementCategoryServiceImpl.java diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/PermissionRelationOperateLogSceneEnum.java b/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/PermissionRelationOperateLogSceneEnum.java index 0568aa27..7f04e26e 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/PermissionRelationOperateLogSceneEnum.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/PermissionRelationOperateLogSceneEnum.java @@ -58,6 +58,21 @@ public enum PermissionRelationOperateLogSceneEnum { */ OMS_API_SYNC("OMS_API_SYNC", "oms后台同步API"), + /** + * oms新增、编辑元素类型 + */ + OMS_UPSERT_PAGE_ELEMENT_CATEGORY("OMS_UPSERT_PAGE_ELEMENT_CATEGORY", "oms新增、编辑元素类型"), + + /** + * oms删除元素类型 + */ + OMS_DELETE_PAGE_ELEMENT_CATEGORY("OMS_DELETE_PAGE_ELEMENT_CATEGORY", "oms删除元素类型"), + + /** + * oms新增、编辑页面元素 + */ + OMS_UPSERT_PAGE_ELEMENT("OMS_UPSERT_PAGE_ELEMENT", "oms新增、编辑页面元素"), + ; @EnumValue diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java index 87e5015a..eefc626d 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java @@ -5,6 +5,7 @@ import cn.axzo.framework.domain.web.result.ApiPageResult; import cn.axzo.framework.domain.web.result.ApiResult; import cn.axzo.tyr.client.model.req.*; import cn.axzo.tyr.client.model.res.GetUserHasPermissionPageElementResp; +import cn.axzo.tyr.client.model.res.ListPageElementCategoryResp; import cn.axzo.tyr.client.model.res.PageElementResp; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PostMapping; @@ -45,4 +46,28 @@ public interface PageElementApi { @PostMapping("/api/pageElement/list") ApiResult> list(PageElementReq param); + + /** 查询页面元素类型(按端分组) **/ + @PostMapping("/api/pageElementCategory/list") + ApiResult> listPageElementCategory(); + + /** 新增、编辑页面元素类型 **/ + @PostMapping("/api/pageElementCategory/saveOrUpdate") + ApiResult saveOrUpdateCategory(@RequestBody @Valid SaveOrUpdatePageElementCategoryReq req); + + /** 删除页面元素类型 **/ + @PostMapping("/api/pageElementCategory/delete") + ApiResult deleteCategory(@RequestBody @Valid DeletePageElementCategoryReq req); + + /** 分页查询页面资源V2 **/ + @PostMapping("/api/pageElement/pageV2") + ApiPageResult pageV2(@RequestBody @Valid PageQueryElementV2Req req); + + /** 新增、编辑页面元素类型 **/ + @PostMapping("/api/pageElement/saveOrUpdatePage") + ApiResult saveOrUpdatePage(@RequestBody @Valid SaveOrUpdatePageElementPageReq req); + + /** 新增、编辑页面组件元素类型 **/ + @PostMapping("/api/pageElement/saveOrUpdateComponent") + ApiResult saveOrUpdateComponent(@RequestBody @Valid SaveOrUpdatePageElementComponentReq req); } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/DeletePageElementCategoryReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/DeletePageElementCategoryReq.java new file mode 100644 index 00000000..274d0938 --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/DeletePageElementCategoryReq.java @@ -0,0 +1,31 @@ +package cn.axzo.tyr.client.model.req; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * @author likunpeng + * @version 1.0 + * @date 2024/8/21 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DeletePageElementCategoryReq { + + @NotNull(message = "ID不能为空") + @Min(value = 1, message = "ID有误") + private Long id; + + /** 操作人personId **/ + @NotNull(message = "操作人不能为空") + @Min(value = 1, message = "操作人有误") + private Long operatorId; +} diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PageQueryElementV2Req.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PageQueryElementV2Req.java new file mode 100644 index 00000000..8779107e --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PageQueryElementV2Req.java @@ -0,0 +1,53 @@ +package cn.axzo.tyr.client.model.req; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; +import java.util.List; + +/** + * @author likunpeng + * @version 1.0 + * @date 2024/6/14 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PageQueryElementV2Req { + + /** + * 端 + */ + private String terminal; + + /** + * 页面元素组件类型 + */ + private List elementTypes; + + /** + * 页面元素名称 + */ + private String pageElementCodeOrName; + + /** + * 页面元素名称 + */ + private String pageElementGroupCodeOrName; + + /** + * 页码 + */ + @Builder.Default + private Long page = 1L; + + /** + * 每页大小 + */ + @Builder.Default + private Long pageSize = 20L; +} diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementCategoryReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementCategoryReq.java new file mode 100644 index 00000000..e274380d --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementCategoryReq.java @@ -0,0 +1,40 @@ +package cn.axzo.tyr.client.model.req; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * @author likunpeng + * @version 1.0 + * @date 2024/8/21 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class SaveOrUpdatePageElementCategoryReq { + + private Long id; + + /** 项目编码 **/ + private String itemCode; + + /** 项目名称 **/ + @NotBlank(message = "项目名称不能为空") + private String itemName; + + /** 登录端 **/ + @NotBlank(message = "所属端不能为空") + private String terminal; + + /** 操作人personId **/ + @NotNull(message = "操作人不能为空") + @Min(value = 1, message = "操作人有误") + private Long operatorId; +} diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementComponentReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementComponentReq.java new file mode 100644 index 00000000..18843682 --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementComponentReq.java @@ -0,0 +1,42 @@ +package cn.axzo.tyr.client.model.req; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * @author likunpeng + * @version 1.0 + * @date 2024/8/21 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class SaveOrUpdatePageElementComponentReq { + + private Long id; + + /** 分组ID **/ + @NotNull(message = "分组ID不能为空") + @Min(value = 1, message = "分组ID有误") + private Long pageId; + + /** 项目编码 **/ + @NotBlank(message = "项目编码不能为空") + private String code; + + /** 元素名称 **/ + @NotBlank(message = "元素名称不能为空") + private String name; + + /** 操作人personId **/ + @NotNull(message = "操作人不能为空") + @Min(value = 1, message = "操作人有误") + private Long operatorId; +} diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementPageReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementPageReq.java new file mode 100644 index 00000000..e4313a01 --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementPageReq.java @@ -0,0 +1,59 @@ +package cn.axzo.tyr.client.model.req; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * @author likunpeng + * @version 1.0 + * @date 2024/8/21 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class SaveOrUpdatePageElementPageReq { + + private Long id; + + /** 项目编码 **/ + @NotBlank(message = "项目编码不能为空") + private String itemCode; + + /** 项目编码 **/ + @NotBlank(message = "项目编码不能为空") + private String code; + + /** 元素名称 **/ + @NotBlank(message = "元素名称不能为空") + private String name; + + /** app类型(APP:原生,H5:h5页面, PC:web页面) **/ + private String appType; + + /** H5的appId **/ + private String appId; + + /** pc/h5路由地址 **/ + private String linkUrl; + + /** ios挑战地址 **/ + private String iosRouterUrl; + + /** android挑战地址 **/ + private String androidRouterUrl; + + /** 版本号 **/ + private Integer version; + + /** 操作人personId **/ + @NotNull(message = "操作人不能为空") + @Min(value = 1, message = "操作人有误") + private Long operatorId; +} diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/ListPageElementCategoryResp.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/ListPageElementCategoryResp.java new file mode 100644 index 00000000..0ccf85bd --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/ListPageElementCategoryResp.java @@ -0,0 +1,39 @@ +package cn.axzo.tyr.client.model.res; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * @author likunpeng + * @version 1.0 + * @date 2024/8/20 + */ + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ListPageElementCategoryResp { + + /** 端 **/ + private String terminal; + /** 页面元素类型列表 **/ + private List pageElementCategories; + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class PageElementCategoryDTO { + /** 主键 **/ + private Long id; + /** 项目编码 **/ + private String itemCode; + /** 项目名称 **/ + private String itemName; + } +} diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/PageElementResp.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/PageElementResp.java index 9a697094..3b76766b 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/PageElementResp.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/PageElementResp.java @@ -32,6 +32,11 @@ public class PageElementResp { */ private String groupCode; + /** + * 元素的组编码 + */ + private String groupName; + /** * 元素编码 */ diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java index bf9e5191..e1504269 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java @@ -3,14 +3,11 @@ package cn.axzo.tyr.server.controller.permission; import cn.axzo.framework.domain.web.result.ApiPageResult; import cn.axzo.framework.domain.web.result.ApiResult; import cn.axzo.tyr.client.feign.PageElementApi; -import cn.axzo.tyr.client.model.req.GetPageElementReq; -import cn.axzo.tyr.client.model.req.GetUserHasPermissionPageElementReq; -import cn.axzo.tyr.client.model.req.ModifyPageElementRelationDTO; -import cn.axzo.tyr.client.model.req.PageElementReportReq; -import cn.axzo.tyr.client.model.req.PageElementReq; -import cn.axzo.tyr.client.model.req.PageQueryElementReq; +import cn.axzo.tyr.client.model.req.*; import cn.axzo.tyr.client.model.res.GetUserHasPermissionPageElementResp; +import cn.axzo.tyr.client.model.res.ListPageElementCategoryResp; import cn.axzo.tyr.client.model.res.PageElementResp; +import cn.axzo.tyr.server.service.SaasPageElementCategoryService; import cn.axzo.tyr.server.service.SaasPageElementService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -29,6 +26,7 @@ import java.util.List; public class PageElementController implements PageElementApi { private final SaasPageElementService saasPageElementService; + private final SaasPageElementCategoryService saasPageElementCategoryService; @Override public ApiResult report(PageElementReportReq req) { @@ -61,4 +59,37 @@ public class PageElementController implements PageElementApi { public ApiResult> list(PageElementReq param) { return ApiResult.ok(saasPageElementService.list(param)); } + + @Override + public ApiResult> listPageElementCategory() { + return ApiResult.ok(saasPageElementCategoryService.listGroupByTerminal()); + } + + @Override + public ApiResult saveOrUpdateCategory(SaveOrUpdatePageElementCategoryReq req) { + return ApiResult.ok(saasPageElementCategoryService.saveOrUpdate(req)); + } + + @Override + public ApiResult deleteCategory(DeletePageElementCategoryReq req) { + saasPageElementCategoryService.delete(req); + return ApiResult.ok(); + } + + @Override + public ApiPageResult pageV2(PageQueryElementV2Req req) { + return ApiPageResult.ok(saasPageElementService.pageV2(req)); + } + + @Override + public ApiResult saveOrUpdatePage(SaveOrUpdatePageElementPageReq req) { + saasPageElementService.saveOrUpdatePage(req); + return ApiResult.ok(); + } + + @Override + public ApiResult saveOrUpdateComponent(SaveOrUpdatePageElementComponentReq req) { + saasPageElementService.saveOrUpdateComponent(req); + return ApiResult.ok(); + } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasPageElementCategoryDao.java b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasPageElementCategoryDao.java new file mode 100644 index 00000000..621c047c --- /dev/null +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasPageElementCategoryDao.java @@ -0,0 +1,15 @@ +package cn.axzo.tyr.server.repository.dao; + +import cn.axzo.tyr.server.repository.entity.SaasPageElementCategory; +import cn.axzo.tyr.server.repository.mapper.SaasPageElementCategoryMapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Repository; + +/** + * @author likunpeng + * @version 1.0 + * @date 2024/8/20 + */ +@Repository +public class SaasPageElementCategoryDao extends ServiceImpl { +} diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasPageElementDao.java b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasPageElementDao.java index cefcefed..cb52412f 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasPageElementDao.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasPageElementDao.java @@ -1,6 +1,8 @@ package cn.axzo.tyr.server.repository.dao; import cn.axzo.basics.common.constant.enums.DeleteEnum; +import cn.axzo.pokonyan.config.mybatisplus.BaseEntity; +import cn.axzo.tyr.client.common.enums.PageElementTypeEnum; import cn.axzo.tyr.server.repository.entity.SaasPageElement; import cn.axzo.tyr.server.repository.entity.SaasPageElementFeatureResourceRelation; import cn.axzo.tyr.server.repository.mapper.SaasPageElementMapper; @@ -41,4 +43,42 @@ public class SaasPageElementDao extends ServiceImpl listByItemCodeAndTerminal(String itemCode, String terminal) { + return lambdaQuery() + .eq(SaasPageElement::getIsDelete, DeleteEnum.NORMAL.getValue()) + .eq(SaasPageElement::getTerminal, terminal) + .eq(SaasPageElement::getItemCode, itemCode) + .list(); + } + + public void deleteIdsByTerminal(List ids, String terminal) { + if (CollectionUtils.isEmpty(ids)) { + return; + } + lambdaUpdate() + .eq(SaasPageElement::getTerminal, terminal) + .in(BaseEntity::getId, ids) + .set(SaasPageElement::getIsDelete, DeleteEnum.DELETE.getValue()) + .update(); + } + + public void updateComponentsGroupCode(String oldGroupCode, String newGroupCode, String terminal) { + lambdaUpdate() + .eq(SaasPageElement::getIsDelete, DeleteEnum.NORMAL.getValue()) + .eq(SaasPageElement::getTerminal, terminal) + .eq(SaasPageElement::getType, PageElementTypeEnum.COMPONENT.getCode()) + .eq(SaasPageElement::getGroupCode, oldGroupCode) + .set(SaasPageElement::getGroupCode, newGroupCode) + .update(); + } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasPageElementFeatureResourceRelationDao.java b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasPageElementFeatureResourceRelationDao.java index c52bc145..a1b0cacc 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasPageElementFeatureResourceRelationDao.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasPageElementFeatureResourceRelationDao.java @@ -2,6 +2,8 @@ package cn.axzo.tyr.server.repository.dao; import cn.axzo.basics.common.constant.enums.DeleteEnum; import cn.axzo.pokonyan.config.mybatisplus.BaseEntity; +import cn.axzo.tyr.client.common.enums.PageElementTypeEnum; +import cn.axzo.tyr.server.repository.entity.SaasPageElement; import cn.axzo.tyr.server.repository.entity.SaasPageElementFeatureResourceRelation; import cn.axzo.tyr.server.repository.mapper.SaasPageElementFeatureResourceRelationMapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -46,4 +48,23 @@ public class SaasPageElementFeatureResourceRelationDao extends ServiceImpl pageElementCodes, Long operatorId) { + lambdaUpdate() + .eq(SaasPageElementFeatureResourceRelation::getIsDelete, DeleteEnum.NORMAL.getValue()) + .eq(SaasPageElementFeatureResourceRelation::getTerminal, terminal) + .in(SaasPageElementFeatureResourceRelation::getPageElementCode, pageElementCodes) + .set(SaasPageElementFeatureResourceRelation::getIsDelete, DeleteEnum.DELETE.getValue()) + .set(Objects.nonNull(operatorId), SaasPageElementFeatureResourceRelation::getUpdateBy, operatorId) + .update(); + } + + public void updateGroupCode(String oldGroupCode, String newGroupCode, String terminal) { + lambdaUpdate() + .eq(SaasPageElementFeatureResourceRelation::getIsDelete, DeleteEnum.NORMAL.getValue()) + .eq(SaasPageElementFeatureResourceRelation::getTerminal, terminal) + .eq(SaasPageElementFeatureResourceRelation::getPageElementCode, oldGroupCode) + .set(SaasPageElementFeatureResourceRelation::getPageElementCode, newGroupCode) + .update(); + } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/entity/SaasPageElementCategory.java b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/entity/SaasPageElementCategory.java new file mode 100644 index 00000000..c4c2ca8d --- /dev/null +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/entity/SaasPageElementCategory.java @@ -0,0 +1,45 @@ +package cn.axzo.tyr.server.repository.entity; + +import cn.axzo.pokonyan.config.mybatisplus.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 页面元素表 + * + * @author likunpeng + * @version 1.0 + * @date 2024/6/18 + */ +@Getter +@Setter +@ToString +@Builder +@EqualsAndHashCode(callSuper = true) +@TableName(value = "saas_page_element_category", autoResultMap = true) +public class SaasPageElementCategory extends BaseEntity { + /** + * 创建人 + */ + private Long createBy; + + /** + * 更新人 + */ + private Long updateBy; + + /** + * 项目code(H5会拉取项目下所有的元素) + */ + private String itemCode; + + /** + * 项目名称 + */ + private String itemName; + + /** + * 所属端 + */ + private String terminal; +} diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/mapper/SaasPageElementCategoryMapper.java b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/mapper/SaasPageElementCategoryMapper.java new file mode 100644 index 00000000..d65ccbd4 --- /dev/null +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/mapper/SaasPageElementCategoryMapper.java @@ -0,0 +1,9 @@ +package cn.axzo.tyr.server.repository.mapper; + +import cn.axzo.tyr.server.repository.entity.SaasPageElementCategory; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +public interface SaasPageElementCategoryMapper extends BaseMapper { + +} + diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementCategoryService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementCategoryService.java new file mode 100644 index 00000000..dc0b35fd --- /dev/null +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementCategoryService.java @@ -0,0 +1,21 @@ +package cn.axzo.tyr.server.service; + +import cn.axzo.tyr.client.model.req.DeletePageElementCategoryReq; +import cn.axzo.tyr.client.model.req.SaveOrUpdatePageElementCategoryReq; +import cn.axzo.tyr.client.model.res.ListPageElementCategoryResp; + +import java.util.List; + +/** + * @author likunpeng + * @version 1.0 + * @date 2024/8/20 + */ +public interface SaasPageElementCategoryService { + + List listGroupByTerminal(); + + Long saveOrUpdate(SaveOrUpdatePageElementCategoryReq req); + + void delete(DeletePageElementCategoryReq req); +} diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java index 9ea72575..d4497533 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java @@ -1,12 +1,7 @@ package cn.axzo.tyr.server.service; import cn.axzo.framework.domain.page.PageResp; -import cn.axzo.tyr.client.model.req.GetPageElementReq; -import cn.axzo.tyr.client.model.req.GetUserHasPermissionPageElementReq; -import cn.axzo.tyr.client.model.req.ModifyPageElementRelationDTO; -import cn.axzo.tyr.client.model.req.PageElementReportReq; -import cn.axzo.tyr.client.model.req.PageElementReq; -import cn.axzo.tyr.client.model.req.PageQueryElementReq; +import cn.axzo.tyr.client.model.req.*; import cn.axzo.tyr.client.model.res.GetUserHasPermissionPageElementResp; import cn.axzo.tyr.client.model.res.PageElementBasicDTO; import cn.axzo.tyr.client.model.res.PageElementResp; @@ -82,4 +77,10 @@ public interface SaasPageElementService extends IService { List list(PageElementReq param); cn.axzo.foundation.page.PageResp page(PageElementReq param); + + PageResp pageV2(PageQueryElementV2Req req); + + Long saveOrUpdatePage(SaveOrUpdatePageElementPageReq req); + + Long saveOrUpdateComponent(SaveOrUpdatePageElementComponentReq req); } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementCategoryServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementCategoryServiceImpl.java new file mode 100644 index 00000000..3d4c77d6 --- /dev/null +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementCategoryServiceImpl.java @@ -0,0 +1,174 @@ +package cn.axzo.tyr.server.service.impl; + +import cn.axzo.basics.common.constant.enums.DeleteEnum; +import cn.axzo.basics.common.util.AssertUtil; +import cn.axzo.pokonyan.config.mybatisplus.BaseEntity; +import cn.axzo.tyr.client.common.enums.PermissionRelationOperateLogSceneEnum; +import cn.axzo.tyr.client.model.req.DeletePageElementCategoryReq; +import cn.axzo.tyr.client.model.req.PermissionOperateLogReq; +import cn.axzo.tyr.client.model.req.SaveOrUpdatePageElementCategoryReq; +import cn.axzo.tyr.client.model.res.ListPageElementCategoryResp; +import cn.axzo.tyr.server.repository.dao.SaasPageElementCategoryDao; +import cn.axzo.tyr.server.repository.dao.SaasPageElementDao; +import cn.axzo.tyr.server.repository.dao.SaasPageElementFeatureResourceRelationDao; +import cn.axzo.tyr.server.repository.entity.SaasPageElement; +import cn.axzo.tyr.server.repository.entity.SaasPageElementCategory; +import cn.axzo.tyr.server.service.SaasPageElementCategoryService; +import cn.axzo.tyr.server.service.SaasPgroupPermissionRelationOperateLogService; +import com.google.common.collect.Lists; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * @author likunpeng + * @version 1.0 + * @date 2024/8/20 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SaasPageElementCategoryServiceImpl implements SaasPageElementCategoryService { + + public static final String PAGE_ELEMENT_CATEGORY_TABLE_NAME = "saas_page_element_category"; + + private final SaasPageElementCategoryDao saasPageElementCategoryDao; + private final SaasPageElementDao saasPageElementDao; + private final SaasPageElementFeatureResourceRelationDao saasPageElementFeatureResourceRelationDao; + private final SaasPgroupPermissionRelationOperateLogService saasPgroupPermissionRelationOperateLogService; + + @Override + public List listGroupByTerminal() { + List categoryResps = Lists.newArrayList(); + List categories = saasPageElementCategoryDao.lambdaQuery() + .eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.value) + .list(); + if (CollectionUtils.isEmpty(categories)) { + return categoryResps; + } + Map> categoryMap = categories.stream().collect(Collectors.groupingBy(SaasPageElementCategory::getTerminal)); + categoryMap.forEach((key, value) -> { + categoryResps.add(ListPageElementCategoryResp.builder().terminal(key) + .pageElementCategories(value.stream().map(c -> ListPageElementCategoryResp.PageElementCategoryDTO + .builder() + .id(c.getId()) + .itemCode(c.getItemCode()) + .itemName(c.getItemName()) + .build()).collect(Collectors.toList())).build()); + }); + return categoryResps; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Long saveOrUpdate(SaveOrUpdatePageElementCategoryReq req) { + SaasPageElementCategory baseCategory = SaasPageElementCategory.builder() + .itemName(req.getItemName()) + .createBy(req.getOperatorId()) + .updateBy(req.getOperatorId()) + .build(); + validItemName(req.getItemName(), req.getId()); + + if (Objects.nonNull(req.getId())) { + // 不允许编辑itemCoe,不然端上查询权限点出问题 + SaasPageElementCategory dbCategory = saasPageElementCategoryDao.getById(req.getId()); + AssertUtil.notNull(dbCategory, "页面元素分类不存在"); + baseCategory.setId(req.getId()); + if (!dbCategory.getItemName().equals(req.getItemName())) { + // 更新saas_page_element的item_name + saasPageElementDao.updateItemNameByItemCode(dbCategory.getItemCode(), req.getItemName(), dbCategory.getTerminal()); + } + saasPageElementCategoryDao.updateById(baseCategory); + } else { + AssertUtil.notEmpty(req.getItemCode(), "项目编码不能为空"); + validItemCode(req.getItemCode()); + baseCategory.setItemCode(req.getItemCode()); + baseCategory.setTerminal(req.getTerminal()); + saasPageElementCategoryDao.save(baseCategory); + } + + try { + saveOrUpdateOperateLog(req, baseCategory); + } catch (Exception e) { + log.warn("save operate log error", e); + } + + return baseCategory.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delete(DeletePageElementCategoryReq req) { + SaasPageElementCategory dbCategory = saasPageElementCategoryDao.getById(req.getId()); + AssertUtil.notNull(dbCategory, "页面元素分类不存在"); + saasPageElementCategoryDao.lambdaUpdate() + .eq(BaseEntity::getId, req.getId()) + .set(SaasPageElementCategory::getIsDelete, DeleteEnum.DELETE.getValue()) + .set(SaasPageElementCategory::getUpdateBy, req.getOperatorId()) + .update(); + + // 删除页面元素 + List pageElements = saasPageElementDao.listByItemCodeAndTerminal(dbCategory.getItemCode(), dbCategory.getTerminal()); + if (CollectionUtils.isEmpty(pageElements)) { + return; + } + List pageElementIds = pageElements.stream().map(BaseEntity::getId).collect(Collectors.toList()); + saasPageElementDao.deleteIdsByTerminal(pageElementIds, dbCategory.getTerminal()); + + // 删除页面元素绑定关系 + List pageElementCodes = pageElements.stream().map(SaasPageElement::getCode).collect(Collectors.toList()); + saasPageElementFeatureResourceRelationDao.deleteByTerminalAndPageElementCodes(dbCategory.getTerminal(), pageElementCodes, req.getOperatorId()); + + try { + saveDeleteOperateLog(req, dbCategory); + } catch (Exception e) { + log.warn("save operate log error", e); + } + } + + private void validItemCode(String itemCode) { + List categories = saasPageElementCategoryDao.lambdaQuery() + .eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.value) + .eq(SaasPageElementCategory::getItemCode, itemCode) + .list(); + AssertUtil.isEmpty(categories, "项目编码已存在"); + } + + private void validItemName(String itemName, Long categoryId) { + List categories = saasPageElementCategoryDao.lambdaQuery() + .eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.value) + .eq(SaasPageElementCategory::getItemName, itemName) + .ne(Objects.nonNull(categoryId), BaseEntity::getId, categoryId) + .list(); + AssertUtil.isEmpty(categories, "项目名称已存在"); + } + + private void saveOrUpdateOperateLog(SaveOrUpdatePageElementCategoryReq req, SaasPageElementCategory baseCategory) { + saasPgroupPermissionRelationOperateLogService.save(PermissionOperateLogReq.builder() + .tableName(PAGE_ELEMENT_CATEGORY_TABLE_NAME) + .operatorId(req.getOperatorId()) + .scene(PermissionRelationOperateLogSceneEnum.OMS_UPSERT_PAGE_ELEMENT_CATEGORY.getValue()) + .sceneId(baseCategory.getId().toString()) + .requestData(req) + .operateData(baseCategory) + .build()); + } + + private void saveDeleteOperateLog(DeletePageElementCategoryReq req, SaasPageElementCategory baseCategory) { + saasPgroupPermissionRelationOperateLogService.save(PermissionOperateLogReq.builder() + .tableName(PAGE_ELEMENT_CATEGORY_TABLE_NAME) + .operatorId(req.getOperatorId()) + .scene(PermissionRelationOperateLogSceneEnum.OMS_DELETE_PAGE_ELEMENT_CATEGORY.getValue()) + .sceneId(baseCategory.getId().toString()) + .requestData(req) + .operateData(baseCategory) + .build()); + } +} diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java index 45440782..ecfd952b 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java @@ -1,6 +1,7 @@ package cn.axzo.tyr.server.service.impl; import cn.axzo.basics.common.BeanMapper; +import cn.axzo.basics.common.constant.enums.DeleteEnum; import cn.axzo.basics.common.util.AssertUtil; import cn.axzo.basics.common.util.StopWatchUtil; import cn.axzo.basics.profiles.api.UserProfileServiceApi; @@ -15,15 +16,7 @@ import cn.axzo.tyr.client.common.enums.FeatureResourceType; import cn.axzo.tyr.client.common.enums.PageElementFeatureResourceRelationTypeEnum; import cn.axzo.tyr.client.common.enums.PageElementTypeEnum; import cn.axzo.tyr.client.common.enums.PermissionRelationOperateLogSceneEnum; -import cn.axzo.tyr.client.model.req.GetPageElementReq; -import cn.axzo.tyr.client.model.req.GetUserHasPermissionPageElementReq; -import cn.axzo.tyr.client.model.req.IdentityAuthReq; -import cn.axzo.tyr.client.model.req.ModifyPageElementRelationDTO; -import cn.axzo.tyr.client.model.req.PageElementFeatureResourceRelationReq; -import cn.axzo.tyr.client.model.req.PageElementReportReq; -import cn.axzo.tyr.client.model.req.PageElementReq; -import cn.axzo.tyr.client.model.req.PageQueryElementReq; -import cn.axzo.tyr.client.model.req.PageSaasFeatureResourceReq; +import cn.axzo.tyr.client.model.req.*; import cn.axzo.tyr.client.model.res.GetUserHasPermissionPageElementResp; import cn.axzo.tyr.client.model.res.IdentityAuthRes; import cn.axzo.tyr.client.model.res.PageElementBasicDTO; @@ -33,12 +26,10 @@ import cn.axzo.tyr.server.config.MqProducer; import cn.axzo.tyr.server.event.payload.PageElementFeatureResourceUpsertPayload; import cn.axzo.tyr.server.model.RelationOperateLogResourceBindElementDO; import cn.axzo.tyr.server.repository.dao.SaasFeatureResourceDao; +import cn.axzo.tyr.server.repository.dao.SaasPageElementCategoryDao; import cn.axzo.tyr.server.repository.dao.SaasPageElementDao; import cn.axzo.tyr.server.repository.dao.SaasPageElementFeatureResourceRelationDao; -import cn.axzo.tyr.server.repository.entity.SaasFeatureResource; -import cn.axzo.tyr.server.repository.entity.SaasPageElement; -import cn.axzo.tyr.server.repository.entity.SaasPageElementFeatureResourceRelation; -import cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelationOperateLog; +import cn.axzo.tyr.server.repository.entity.*; import cn.axzo.tyr.server.repository.mapper.SaasPageElementMapper; import cn.axzo.tyr.server.service.SaasFeatureResourceService; import cn.axzo.tyr.server.service.SaasPageElementFeatureResourceRelationService; @@ -53,6 +44,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import lombok.RequiredArgsConstructor; @@ -69,11 +61,7 @@ import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; +import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.function.Function; @@ -102,6 +90,7 @@ public class SaasPageElementServiceImpl extends ServiceImpl reportSecretKeys; private static final String TARGET_TYPE = "pageElementFeatureResourceId"; + public static final String PAGE_ELEMENT_TABLE_NAME = "saas_page_element"; @Override @Transactional(rollbackFor = Exception.class) @@ -503,6 +493,123 @@ public class SaasPageElementServiceImpl extends ServiceImpl from(e, featureResources)); } + @Override + public PageResp pageV2(PageQueryElementV2Req request) { + IPage page = saasPageElementDao.lambdaQuery() + .eq(StringUtils.isNotBlank(request.getTerminal()), SaasPageElement::getTerminal, request.getTerminal()) + .in(CollectionUtils.isNotEmpty(request.getElementTypes()), SaasPageElement::getType, request.getElementTypes()) + .and(StringUtils.isNotBlank(request.getPageElementCodeOrName()), w -> w.like(SaasPageElement::getCode, request.getPageElementCodeOrName()) + .or().like(SaasPageElement::getName, request.getPageElementCodeOrName())) + .eq(StringUtils.isNotBlank(request.getPageElementGroupCodeOrName()), SaasPageElement::getType, PageElementTypeEnum.PAGE.getCode()) + .and(StringUtils.isNotBlank(request.getPageElementGroupCodeOrName()), + w -> w.like(SaasPageElement::getGroupCode, request.getPageElementGroupCodeOrName()) + .or().like(SaasPageElement::getName, request.getPageElementGroupCodeOrName())) + .orderByDesc(BaseEntity::getId) + .page(new Page<>(request.getPage(), request.getPageSize())); + List list = BeanMapper.copyList(page.getRecords(), PageElementResp.class); + fillGroupName(list); + return PageResp.list(page.getCurrent(), page.getSize(), page.getTotal(), list); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Long saveOrUpdatePage(SaveOrUpdatePageElementPageReq req) { + List categories = saasPageElementCategoryDao.lambdaQuery() + .eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.getValue()) + .eq(SaasPageElementCategory::getItemCode, req.getItemCode()).list(); + AssertUtil.notEmpty(categories, "元素分类不存在。"); + SaasPageElementCategory category = categories.get(0); + + SaasPageElement basePageElement = SaasPageElement.builder() + .version(req.getVersion()) + .groupCode(req.getCode()) + .code(req.getCode()) + .name(req.getName()) + .type(PageElementTypeEnum.PAGE.getCode()) + .linkUrl(req.getLinkUrl()) + .linkExt(getLinkExtStr(req.getIosRouterUrl(), req.getAndroidRouterUrl())) + .terminal(category.getTerminal()) + .appType(req.getAppType()) + .appId(req.getAppId()) + .itemCode(req.getItemCode()) + .itemName(category.getItemName()) + .build(); + + if (Objects.nonNull(req.getId())) { + SaasPageElement dbPageElement = saasPageElementDao.getById(req.getId()); + AssertUtil.notNull(dbPageElement, "页面元素不存在"); + basePageElement.setId(dbPageElement.getId()); + if (!dbPageElement.getCode().equals(basePageElement.getCode())) { + // 校验code唯一 + validCode(basePageElement.getCode()); + // 更新子元素的group_code + saasPageElementDao.updateComponentsGroupCode(dbPageElement.getCode(), basePageElement.getCode(), category.getTerminal()); + // 更新关联关系的page_element_code + saasPageElementFeatureResourceRelationDao.updateGroupCode(dbPageElement.getCode(), basePageElement.getCode(), category.getTerminal()); + } + saasPageElementDao.updateById(basePageElement); + } else { + validCode(basePageElement.getCode()); + saasPageElementDao.save(basePageElement); + } + + // 记录操作日志 + try { + saveOrUpdatePageOperateLog(req, basePageElement); + } catch (Exception e) { + log.warn("save operate log error", e); + } + + return basePageElement.getId(); + } + + @Override + public Long saveOrUpdateComponent(SaveOrUpdatePageElementComponentReq req) { + List pageElements = saasPageElementDao.lambdaQuery() + .eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.getValue()) + .eq(SaasPageElement::getId, req.getPageId()).list(); + AssertUtil.notEmpty(pageElements, "父级元素不存在。"); + SaasPageElement pageElement = pageElements.get(0); + + SaasPageElement basePageElement = SaasPageElement.builder() + .version(pageElement.getVersion()) + .groupCode(pageElement.getCode()) + .code(req.getCode()) + .name(req.getName()) + .type(PageElementTypeEnum.COMPONENT.getCode()) + .terminal(pageElement.getTerminal()) + .appType(pageElement.getAppType()) + .appId(pageElement.getAppId()) + .itemCode(pageElement.getItemCode()) + .itemName(pageElement.getItemName()) + .build(); + + if (Objects.nonNull(req.getId())) { + SaasPageElement dbPageElement = saasPageElementDao.getById(req.getId()); + AssertUtil.notNull(dbPageElement, "页面组件元素不存在"); + basePageElement.setId(dbPageElement.getId()); + if (!dbPageElement.getCode().equals(basePageElement.getCode())) { + // 校验code唯一 + validCode(basePageElement.getCode()); + // 更新关联关系的page_element_code + saasPageElementFeatureResourceRelationDao.updateGroupCode(dbPageElement.getCode(), basePageElement.getCode(), pageElement.getTerminal()); + } + saasPageElementDao.updateById(basePageElement); + } else { + validCode(basePageElement.getCode()); + saasPageElementDao.save(basePageElement); + } + + // 记录操作日志 + try { + saveOrUpdateComponentOperateLog(req, basePageElement); + } catch (Exception e) { + log.warn("save operate log error", e); + } + + return basePageElement.getId(); + } + private PageElementResp from(SaasPageElement saasPageElement, Map> featureResources) { PageElementResp pageElementResp = PageElementResp.builder().build(); @@ -549,4 +656,55 @@ public class SaasPageElementServiceImpl extends ServiceImpl featureResources.get(e.getFeatureResourceUniCode()), Collectors.toList()))); } + + private void fillGroupName(List list) { + if (CollectionUtils.isEmpty(list)) { + return; + } + + Map elementMap = saasPageElementDao.lambdaQuery() + .eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.getValue()) + .in(SaasPageElement::getCode, list.stream().map(PageElementResp::getGroupCode).distinct().collect(Collectors.toList())) + .list().stream().collect(Collectors.toMap(SaasPageElement::getCode, Function.identity(), (v1, v2) -> v1)); + list.forEach(e -> e.setGroupName(Optional.ofNullable(elementMap.get(e.getGroupCode())).map(SaasPageElement::getName).orElse(StringUtils.EMPTY))); + } + + private void validCode(String code) { + List pageElements = saasPageElementDao.lambdaQuery() + .eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.value) + .eq(SaasPageElement::getCode, code) + .list(); + AssertUtil.isEmpty(pageElements, "featureCode已存在"); + } + + private String getLinkExtStr(String iosRouterUrl, String androidRouterUrl) { + if (StringUtils.isBlank(iosRouterUrl) && StringUtils.isBlank(androidRouterUrl)) { + return StringUtils.EMPTY; + } + List exts = Lists.newArrayList(PageElementResp.LinkExt.builder().system("ios").routerUrl(Strings.nullToEmpty(iosRouterUrl)).build(), + PageElementResp.LinkExt.builder().system("android").routerUrl(Strings.nullToEmpty(androidRouterUrl)).build()); + return JSONObject.toJSONString(exts); + } + + private void saveOrUpdatePageOperateLog(SaveOrUpdatePageElementPageReq req, SaasPageElement basePageElement) { + saasPgroupPermissionRelationOperateLogService.save(PermissionOperateLogReq.builder() + .tableName(PAGE_ELEMENT_TABLE_NAME) + .operatorId(req.getOperatorId()) + .scene(PermissionRelationOperateLogSceneEnum.OMS_UPSERT_PAGE_ELEMENT.getValue()) + .sceneId(basePageElement.getId().toString()) + .requestData(req) + .operateData(basePageElement) + .build()); + } + + private void saveOrUpdateComponentOperateLog(SaveOrUpdatePageElementComponentReq req, SaasPageElement basePageElement) { + saasPgroupPermissionRelationOperateLogService.save(PermissionOperateLogReq.builder() + .tableName(PAGE_ELEMENT_TABLE_NAME) + .operatorId(req.getOperatorId()) + .scene(PermissionRelationOperateLogSceneEnum.OMS_UPSERT_PAGE_ELEMENT.getValue()) + .sceneId(basePageElement.getId().toString()) + .requestData(req) + .operateData(basePageElement) + .build()); + } } From cc28bb554ab87be8ae0b385d16a916a7cbe25080 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Fri, 23 Aug 2024 08:50:33 +0800 Subject: [PATCH 02/27] =?UTF-8?q?feat(REQ-2899):=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=E8=B5=84=E6=BA=90=E6=96=B0=E5=A2=9E=E3=80=81=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../axzo/tyr/client/feign/PageElementApi.java | 9 +- .../SaveOrUpdatePageElementComponentReq.java | 42 ------- ...q.java => SaveOrUpdatePageElementReq.java} | 10 +- .../permission/PageElementController.java | 10 +- .../service/SaasPageElementService.java | 4 +- .../impl/SaasPageElementServiceImpl.java | 108 ++++++------------ 6 files changed, 48 insertions(+), 135 deletions(-) delete mode 100644 tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementComponentReq.java rename tyr-api/src/main/java/cn/axzo/tyr/client/model/req/{SaveOrUpdatePageElementPageReq.java => SaveOrUpdatePageElementReq.java} (84%) diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java index eefc626d..49867907 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java @@ -1,6 +1,5 @@ package cn.axzo.tyr.client.feign; -import cn.axzo.framework.domain.page.Page; import cn.axzo.framework.domain.web.result.ApiPageResult; import cn.axzo.framework.domain.web.result.ApiResult; import cn.axzo.tyr.client.model.req.*; @@ -64,10 +63,6 @@ public interface PageElementApi { ApiPageResult pageV2(@RequestBody @Valid PageQueryElementV2Req req); /** 新增、编辑页面元素类型 **/ - @PostMapping("/api/pageElement/saveOrUpdatePage") - ApiResult saveOrUpdatePage(@RequestBody @Valid SaveOrUpdatePageElementPageReq req); - - /** 新增、编辑页面组件元素类型 **/ - @PostMapping("/api/pageElement/saveOrUpdateComponent") - ApiResult saveOrUpdateComponent(@RequestBody @Valid SaveOrUpdatePageElementComponentReq req); + @PostMapping("/api/pageElement/saveOrUpdate") + ApiResult saveOrUpdate(@RequestBody @Valid SaveOrUpdatePageElementReq req); } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementComponentReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementComponentReq.java deleted file mode 100644 index 18843682..00000000 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementComponentReq.java +++ /dev/null @@ -1,42 +0,0 @@ -package cn.axzo.tyr.client.model.req; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.Min; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; - -/** - * @author likunpeng - * @version 1.0 - * @date 2024/8/21 - */ -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class SaveOrUpdatePageElementComponentReq { - - private Long id; - - /** 分组ID **/ - @NotNull(message = "分组ID不能为空") - @Min(value = 1, message = "分组ID有误") - private Long pageId; - - /** 项目编码 **/ - @NotBlank(message = "项目编码不能为空") - private String code; - - /** 元素名称 **/ - @NotBlank(message = "元素名称不能为空") - private String name; - - /** 操作人personId **/ - @NotNull(message = "操作人不能为空") - @Min(value = 1, message = "操作人有误") - private Long operatorId; -} diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementPageReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementReq.java similarity index 84% rename from tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementPageReq.java rename to tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementReq.java index e4313a01..51f391b0 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementPageReq.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementReq.java @@ -18,14 +18,20 @@ import javax.validation.constraints.NotNull; @Builder @NoArgsConstructor @AllArgsConstructor -public class SaveOrUpdatePageElementPageReq { +public class SaveOrUpdatePageElementReq { private Long id; /** 项目编码 **/ - @NotBlank(message = "项目编码不能为空") private String itemCode; + /** 分组ID **/ + private Long pageId; + + /** 页面元素类型:PAGE/COMPONENT **/ + @NotBlank(message = "页面元素类型不能为空") + private String type; + /** 项目编码 **/ @NotBlank(message = "项目编码不能为空") private String code; diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java index e1504269..5b56d023 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java @@ -82,14 +82,8 @@ public class PageElementController implements PageElementApi { } @Override - public ApiResult saveOrUpdatePage(SaveOrUpdatePageElementPageReq req) { - saasPageElementService.saveOrUpdatePage(req); - return ApiResult.ok(); - } - - @Override - public ApiResult saveOrUpdateComponent(SaveOrUpdatePageElementComponentReq req) { - saasPageElementService.saveOrUpdateComponent(req); + public ApiResult saveOrUpdate(SaveOrUpdatePageElementReq req) { + saasPageElementService.saveOrUpdate(req); return ApiResult.ok(); } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java index d4497533..8247864a 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java @@ -80,7 +80,5 @@ public interface SaasPageElementService extends IService { PageResp pageV2(PageQueryElementV2Req req); - Long saveOrUpdatePage(SaveOrUpdatePageElementPageReq req); - - Long saveOrUpdateComponent(SaveOrUpdatePageElementComponentReq req); + Long saveOrUpdate(SaveOrUpdatePageElementReq req); } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java index ecfd952b..36d32179 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java @@ -513,26 +513,18 @@ public class SaasPageElementServiceImpl extends ServiceImpl categories = saasPageElementCategoryDao.lambdaQuery() - .eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.getValue()) - .eq(SaasPageElementCategory::getItemCode, req.getItemCode()).list(); - AssertUtil.notEmpty(categories, "元素分类不存在。"); - SaasPageElementCategory category = categories.get(0); - + public Long saveOrUpdate(SaveOrUpdatePageElementReq req) { SaasPageElement basePageElement = SaasPageElement.builder() .version(req.getVersion()) .groupCode(req.getCode()) .code(req.getCode()) .name(req.getName()) - .type(PageElementTypeEnum.PAGE.getCode()) + .type(req.getType()) .linkUrl(req.getLinkUrl()) .linkExt(getLinkExtStr(req.getIosRouterUrl(), req.getAndroidRouterUrl())) - .terminal(category.getTerminal()) .appType(req.getAppType()) .appId(req.getAppId()) .itemCode(req.getItemCode()) - .itemName(category.getItemName()) .build(); if (Objects.nonNull(req.getId())) { @@ -542,67 +534,48 @@ public class SaasPageElementServiceImpl extends ServiceImpl categories = saasPageElementCategoryDao.lambdaQuery() + .eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.getValue()) + .eq(SaasPageElementCategory::getItemCode, req.getItemCode()).list(); + AssertUtil.notEmpty(categories, "元素分类不存在。"); + SaasPageElementCategory category = categories.get(0); + basePageElement.setTerminal(category.getTerminal()); + basePageElement.setItemName(category.getItemName()); + } else if (PageElementTypeEnum.COMPONENT.getCode().equals(req.getType())) { + AssertUtil.isTrue(Objects.nonNull(req.getPageId()) && req.getPageId() > 0, "页面元素不存在"); + List pageElements = saasPageElementDao.lambdaQuery() + .eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.getValue()) + .eq(SaasPageElement::getId, req.getPageId()).list(); + AssertUtil.notEmpty(pageElements, "父级元素不存在。"); + + SaasPageElement pageElement = pageElements.get(0); + basePageElement.setVersion(pageElement.getVersion()); + basePageElement.setGroupCode(pageElement.getCode()); + basePageElement.setTerminal(pageElement.getTerminal()); + basePageElement.setAppType(pageElement.getAppType()); + basePageElement.setAppId(pageElement.getAppId()); + basePageElement.setItemCode(pageElement.getItemCode()); + basePageElement.setItemName(pageElement.getItemName()); + } + // 校验code唯一 validCode(basePageElement.getCode()); saasPageElementDao.save(basePageElement); } // 记录操作日志 try { - saveOrUpdatePageOperateLog(req, basePageElement); - } catch (Exception e) { - log.warn("save operate log error", e); - } - - return basePageElement.getId(); - } - - @Override - public Long saveOrUpdateComponent(SaveOrUpdatePageElementComponentReq req) { - List pageElements = saasPageElementDao.lambdaQuery() - .eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.getValue()) - .eq(SaasPageElement::getId, req.getPageId()).list(); - AssertUtil.notEmpty(pageElements, "父级元素不存在。"); - SaasPageElement pageElement = pageElements.get(0); - - SaasPageElement basePageElement = SaasPageElement.builder() - .version(pageElement.getVersion()) - .groupCode(pageElement.getCode()) - .code(req.getCode()) - .name(req.getName()) - .type(PageElementTypeEnum.COMPONENT.getCode()) - .terminal(pageElement.getTerminal()) - .appType(pageElement.getAppType()) - .appId(pageElement.getAppId()) - .itemCode(pageElement.getItemCode()) - .itemName(pageElement.getItemName()) - .build(); - - if (Objects.nonNull(req.getId())) { - SaasPageElement dbPageElement = saasPageElementDao.getById(req.getId()); - AssertUtil.notNull(dbPageElement, "页面组件元素不存在"); - basePageElement.setId(dbPageElement.getId()); - if (!dbPageElement.getCode().equals(basePageElement.getCode())) { - // 校验code唯一 - validCode(basePageElement.getCode()); - // 更新关联关系的page_element_code - saasPageElementFeatureResourceRelationDao.updateGroupCode(dbPageElement.getCode(), basePageElement.getCode(), pageElement.getTerminal()); - } - saasPageElementDao.updateById(basePageElement); - } else { - validCode(basePageElement.getCode()); - saasPageElementDao.save(basePageElement); - } - - // 记录操作日志 - try { - saveOrUpdateComponentOperateLog(req, basePageElement); + saveOrUpdateOperateLog(req, basePageElement); } catch (Exception e) { log.warn("save operate log error", e); } @@ -686,18 +659,7 @@ public class SaasPageElementServiceImpl extends ServiceImpl Date: Fri, 23 Aug 2024 10:36:29 +0800 Subject: [PATCH 03/27] =?UTF-8?q?feat(REQ-2899):=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=E8=B5=84=E6=BA=90=E5=88=A0=E9=99=A4=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...PermissionRelationOperateLogSceneEnum.java | 5 +++ .../axzo/tyr/client/feign/PageElementApi.java | 6 ++- .../model/req/DeletePageElementReq.java | 31 +++++++++++++ .../permission/PageElementController.java | 6 +++ .../service/SaasPageElementService.java | 2 + .../impl/SaasPageElementServiceImpl.java | 43 ++++++++++++++++++- 6 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 tyr-api/src/main/java/cn/axzo/tyr/client/model/req/DeletePageElementReq.java diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/PermissionRelationOperateLogSceneEnum.java b/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/PermissionRelationOperateLogSceneEnum.java index 7f04e26e..d66d6b02 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/PermissionRelationOperateLogSceneEnum.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/PermissionRelationOperateLogSceneEnum.java @@ -73,6 +73,11 @@ public enum PermissionRelationOperateLogSceneEnum { */ OMS_UPSERT_PAGE_ELEMENT("OMS_UPSERT_PAGE_ELEMENT", "oms新增、编辑页面元素"), + /** + * oms删除页面元素 + */ + OMS_DELETE_PAGE_ELEMENT("OMS_DELETE_PAGE_ELEMENT", "oms删除页面元素"), + ; @EnumValue diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java index 49867907..047874b8 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java @@ -62,7 +62,11 @@ public interface PageElementApi { @PostMapping("/api/pageElement/pageV2") ApiPageResult pageV2(@RequestBody @Valid PageQueryElementV2Req req); - /** 新增、编辑页面元素类型 **/ + /** 新增、编辑页面元素 **/ @PostMapping("/api/pageElement/saveOrUpdate") ApiResult saveOrUpdate(@RequestBody @Valid SaveOrUpdatePageElementReq req); + + /** 删除页面元素 **/ + @PostMapping("/api/pageElement/delete") + ApiResult delete(@RequestBody @Valid DeletePageElementReq req); } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/DeletePageElementReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/DeletePageElementReq.java new file mode 100644 index 00000000..aac41833 --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/DeletePageElementReq.java @@ -0,0 +1,31 @@ +package cn.axzo.tyr.client.model.req; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * @author likunpeng + * @version 1.0 + * @date 2024/8/21 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DeletePageElementReq { + + @NotNull(message = "ID不能为空") + @Min(value = 1, message = "ID有误") + private Long id; + + /** 操作人personId **/ + @NotNull(message = "操作人不能为空") + @Min(value = 1, message = "操作人有误") + private Long operatorId; +} diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java index 5b56d023..d1ade634 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java @@ -86,4 +86,10 @@ public class PageElementController implements PageElementApi { saasPageElementService.saveOrUpdate(req); return ApiResult.ok(); } + + @Override + public ApiResult delete(DeletePageElementReq req) { + saasPageElementService.delete(req); + return ApiResult.ok(); + } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java index 8247864a..c55b3b33 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java @@ -81,4 +81,6 @@ public interface SaasPageElementService extends IService { PageResp pageV2(PageQueryElementV2Req req); Long saveOrUpdate(SaveOrUpdatePageElementReq req); + + void delete(DeletePageElementReq req); } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java index 36d32179..5f2adea1 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java @@ -47,6 +47,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; @@ -529,7 +530,7 @@ public class SaasPageElementServiceImpl extends ServiceImpl codes = Sets.newHashSet(dbPageElement.getCode()); + + if (PageElementTypeEnum.PAGE.getCode().equals(dbPageElement.getType())) { + // 删除页面的子元素 + List pageElements = saasPageElementDao.listByGroupCodesAndExcludeIds(Lists.newArrayList(dbPageElement.getGroupCode()), null, dbPageElement.getTerminal(), null); + saasPageElementDao.deleteIdsByTerminal(pageElements.stream().map(BaseEntity::getId).collect(Collectors.toList()), dbPageElement.getTerminal()); + codes.addAll(pageElements.stream().map(SaasPageElement::getCode).collect(Collectors.toSet())); + } else { + saasPageElementDao.deleteIdsByTerminal(Lists.newArrayList(req.getId()), dbPageElement.getTerminal()); + } + + // 删除绑定关系 + if (CollectionUtils.isNotEmpty(codes)) { + saasPageElementFeatureResourceRelationDao.deleteByTerminalAndPageElementCodes(dbPageElement.getTerminal(), Lists.newArrayList(codes), req.getOperatorId()); + } + + // 记录操作日志 + try { + saveDeleteOperateLog(req, dbPageElement); + } catch (Exception e) { + log.warn("save operate log error", e); + } + } + private PageElementResp from(SaasPageElement saasPageElement, Map> featureResources) { PageElementResp pageElementResp = PageElementResp.builder().build(); @@ -669,4 +699,15 @@ public class SaasPageElementServiceImpl extends ServiceImpl Date: Mon, 26 Aug 2024 16:07:47 +0800 Subject: [PATCH 04/27] =?UTF-8?q?feat(REQ-2899):=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=E8=B5=84=E6=BA=90=E5=88=A0=E9=99=A4=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../axzo/tyr/client/feign/PageElementApi.java | 5 + .../cn/axzo/tyr/client/model/req/IdReq.java | 25 +++ .../model/req/PageQueryElementV2Req.java | 2 + ...reResourcePageElementRelationViewResp.java | 97 ++++++++++ .../tyr/client/model/res/PageElementResp.java | 5 + .../permission/PageElementController.java | 6 + .../service/SaasPageElementService.java | 3 + .../impl/SaasPageElementServiceImpl.java | 180 +++++++++++++++++- 8 files changed, 318 insertions(+), 5 deletions(-) create mode 100644 tyr-api/src/main/java/cn/axzo/tyr/client/model/req/IdReq.java create mode 100644 tyr-api/src/main/java/cn/axzo/tyr/client/model/res/FeatureResourcePageElementRelationViewResp.java diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java index 047874b8..e57ad4b5 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java @@ -3,6 +3,7 @@ package cn.axzo.tyr.client.feign; import cn.axzo.framework.domain.web.result.ApiPageResult; import cn.axzo.framework.domain.web.result.ApiResult; import cn.axzo.tyr.client.model.req.*; +import cn.axzo.tyr.client.model.res.FeatureResourcePageElementRelationViewResp; import cn.axzo.tyr.client.model.res.GetUserHasPermissionPageElementResp; import cn.axzo.tyr.client.model.res.ListPageElementCategoryResp; import cn.axzo.tyr.client.model.res.PageElementResp; @@ -69,4 +70,8 @@ public interface PageElementApi { /** 删除页面元素 **/ @PostMapping("/api/pageElement/delete") ApiResult delete(@RequestBody @Valid DeletePageElementReq req); + + /** 删除页面元素 **/ + @PostMapping("/api/pageElement/getFeatureResourceRelations") + ApiResult getFeatureResourceRelations(@RequestBody @Valid IdReq req); } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/IdReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/IdReq.java new file mode 100644 index 00000000..a17fe876 --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/IdReq.java @@ -0,0 +1,25 @@ +package cn.axzo.tyr.client.model.req; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; + +/** + * @author likunpeng + * @version 1.0 + * @date 2024/8/21 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class IdReq { + + @NotNull(message = "ID不能为空") + @Min(value = 1, message = "ID有误") + private Long id; +} diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PageQueryElementV2Req.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PageQueryElementV2Req.java index 8779107e..a2643372 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PageQueryElementV2Req.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PageQueryElementV2Req.java @@ -19,6 +19,8 @@ import java.util.List; @AllArgsConstructor public class PageQueryElementV2Req { + private Long id; + /** * 端 */ diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/FeatureResourcePageElementRelationViewResp.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/FeatureResourcePageElementRelationViewResp.java new file mode 100644 index 00000000..d8f2479e --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/FeatureResourcePageElementRelationViewResp.java @@ -0,0 +1,97 @@ +package cn.axzo.tyr.client.model.res; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * @author likunpeng + * @version 1.0 + * @date 2024/8/23 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class FeatureResourcePageElementRelationViewResp { + + /** 菜单资源列表 **/ + private List featureResources; + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class FeatureResourceBasicDTO { + + private Long id; + + /** + * 资源编码-权限码 + */ + private String uniCode; + + /** + * 资源名称 + */ + private String featureName; + + /** + * 资源类型1-菜单 2-页面 3-应用入口 4-组件 5-root 6-分组 + */ + private Integer featureType; + + /** 前端元素资源列表 **/ + private PageElementBasicDTO pageElement; + + private List children; + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class PageElementBasicDTO { + private Long id; + /** + * 元素的组编码 + */ + private String groupCode; + + /** + * 元素的组编码 + */ + private String groupName; + + /** + * 元素编码 + */ + private String code; + + /** + * 元素名称 + */ + private String name; + + /** + * 元素类型 + */ + private String type; + + /** + * 是否关联 + */ + private Boolean hasRelation; + + /** + * 1:路由页面 + */ + private Integer relationType; + + + private List children; + } +} diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/PageElementResp.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/PageElementResp.java index 3b76766b..5f51c072 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/PageElementResp.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/PageElementResp.java @@ -86,6 +86,11 @@ public class PageElementResp { */ private List featureResources; + /** ios挑战地址 **/ + private String iosRouterUrl; + + /** android挑战地址 **/ + private String androidRouterUrl; @Data @Builder diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java index d1ade634..2875c85c 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java @@ -4,6 +4,7 @@ import cn.axzo.framework.domain.web.result.ApiPageResult; import cn.axzo.framework.domain.web.result.ApiResult; import cn.axzo.tyr.client.feign.PageElementApi; import cn.axzo.tyr.client.model.req.*; +import cn.axzo.tyr.client.model.res.FeatureResourcePageElementRelationViewResp; import cn.axzo.tyr.client.model.res.GetUserHasPermissionPageElementResp; import cn.axzo.tyr.client.model.res.ListPageElementCategoryResp; import cn.axzo.tyr.client.model.res.PageElementResp; @@ -92,4 +93,9 @@ public class PageElementController implements PageElementApi { saasPageElementService.delete(req); return ApiResult.ok(); } + + @Override + public ApiResult getFeatureResourceRelations(IdReq req) { + return ApiResult.ok(saasPageElementService.getFeatureResourceRelations(req.getId())); + } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java index c55b3b33..1ecc29c6 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java @@ -2,6 +2,7 @@ package cn.axzo.tyr.server.service; import cn.axzo.framework.domain.page.PageResp; import cn.axzo.tyr.client.model.req.*; +import cn.axzo.tyr.client.model.res.FeatureResourcePageElementRelationViewResp; import cn.axzo.tyr.client.model.res.GetUserHasPermissionPageElementResp; import cn.axzo.tyr.client.model.res.PageElementBasicDTO; import cn.axzo.tyr.client.model.res.PageElementResp; @@ -83,4 +84,6 @@ public interface SaasPageElementService extends IService { Long saveOrUpdate(SaveOrUpdatePageElementReq req); void delete(DeletePageElementReq req); + + FeatureResourcePageElementRelationViewResp getFeatureResourceRelations(Long pageElementId); } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java index 5f2adea1..378d22b1 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java @@ -17,11 +17,7 @@ import cn.axzo.tyr.client.common.enums.PageElementFeatureResourceRelationTypeEnu import cn.axzo.tyr.client.common.enums.PageElementTypeEnum; import cn.axzo.tyr.client.common.enums.PermissionRelationOperateLogSceneEnum; import cn.axzo.tyr.client.model.req.*; -import cn.axzo.tyr.client.model.res.GetUserHasPermissionPageElementResp; -import cn.axzo.tyr.client.model.res.IdentityAuthRes; -import cn.axzo.tyr.client.model.res.PageElementBasicDTO; -import cn.axzo.tyr.client.model.res.PageElementResp; -import cn.axzo.tyr.client.model.res.SaasFeatureResourceResp; +import cn.axzo.tyr.client.model.res.*; import cn.axzo.tyr.server.config.MqProducer; import cn.axzo.tyr.server.event.payload.PageElementFeatureResourceUpsertPayload; import cn.axzo.tyr.server.model.RelationOperateLogResourceBindElementDO; @@ -497,6 +493,7 @@ public class SaasPageElementServiceImpl extends ServiceImpl pageV2(PageQueryElementV2Req request) { IPage page = saasPageElementDao.lambdaQuery() + .eq(Objects.nonNull(request.getId()), SaasPageElement::getId, request.getId()) .eq(StringUtils.isNotBlank(request.getTerminal()), SaasPageElement::getTerminal, request.getTerminal()) .in(CollectionUtils.isNotEmpty(request.getElementTypes()), SaasPageElement::getType, request.getElementTypes()) .and(StringUtils.isNotBlank(request.getPageElementCodeOrName()), w -> w.like(SaasPageElement::getCode, request.getPageElementCodeOrName()) @@ -508,7 +505,10 @@ public class SaasPageElementServiceImpl extends ServiceImpl(request.getPage(), request.getPageSize())); List list = BeanMapper.copyList(page.getRecords(), PageElementResp.class); + // 补充元素组名 fillGroupName(list); + // 补充元素ios、android路由地址 + fillIosAndAndroidRouteUrl(list); return PageResp.list(page.getCurrent(), page.getSize(), page.getTotal(), list); } @@ -613,6 +613,34 @@ public class SaasPageElementServiceImpl extends ServiceImpl pageElements = saasPageElementDao.listByGroupCodesAndExcludeIds(Lists.newArrayList(dbPageElement.getGroupCode()), null, dbPageElement.getTerminal(), null); + FeatureResourcePageElementRelationViewResp.PageElementBasicDTO elementBasic = getPageElementBasic(pageElements); + if (Objects.isNull(elementBasic)) { + return null; + } + + List relations = saasPageElementFeatureResourceRelationDao.lambdaQuery() + .eq(SaasPageElementFeatureResourceRelation::getIsDelete, DeleteEnum.NORMAL.getValue()) + .in(SaasPageElementFeatureResourceRelation::getPageElementCode, pageElements.stream().map(SaasPageElement::getCode).collect(Collectors.toSet())) + .eq(SaasPageElementFeatureResourceRelation::getTerminal, dbPageElement.getTerminal()) + .list(); + if (CollectionUtils.isEmpty(relations)) { + return null; + } + List featureResourceBasics = getFeatureResourceBasic(relations.stream().map(SaasPageElementFeatureResourceRelation::getFeatureResourceUniCode).collect(Collectors.toList()), dbPageElement.getTerminal()); + if (CollectionUtils.isEmpty(featureResourceBasics)) { + return null; + } + + fillElementToResource(featureResourceBasics, relations, elementBasic); + + return FeatureResourcePageElementRelationViewResp.builder().featureResources(featureResourceBasics).build(); + } + private PageElementResp from(SaasPageElement saasPageElement, Map> featureResources) { PageElementResp pageElementResp = PageElementResp.builder().build(); @@ -689,6 +717,19 @@ public class SaasPageElementServiceImpl extends ServiceImpl list) { + if (CollectionUtils.isEmpty(list)) { + return; + } + for (PageElementResp resp : list) { + if (StringUtils.isBlank(resp.getLinkExt())) { + continue; + } + resp.setIosRouterUrl(resp.resolveIosRouterUrl()); + resp.setAndroidRouterUrl(resp.resolveAndroidRouterUrl()); + } + } + private void saveOrUpdateOperateLog(SaveOrUpdatePageElementReq req, SaasPageElement basePageElement) { saasPgroupPermissionRelationOperateLogService.save(PermissionOperateLogReq.builder() .tableName(PAGE_ELEMENT_TABLE_NAME) @@ -710,4 +751,133 @@ public class SaasPageElementServiceImpl extends ServiceImpl pageElements) { + SaasPageElement pageTypeElement = pageElements.stream().filter(e -> PageElementTypeEnum.PAGE.getCode().equals(e.getType())).findFirst().orElse(null); + if (Objects.isNull(pageTypeElement)) { + return null; + } + + return FeatureResourcePageElementRelationViewResp.PageElementBasicDTO.builder() + .id(pageTypeElement.getId()) + .groupCode(pageTypeElement.getGroupCode()) + .groupName(pageTypeElement.getName()) + .code(pageTypeElement.getCode()) + .name(pageTypeElement.getName()) + .type(pageTypeElement.getType()) + .children(pageElements.stream().filter(e -> PageElementTypeEnum.COMPONENT.getCode().equals(e.getType())).map(e -> FeatureResourcePageElementRelationViewResp.PageElementBasicDTO.builder() + .id(e.getId()) + .groupCode(pageTypeElement.getGroupCode()) + .groupName(pageTypeElement.getName()) + .code(e.getCode()) + .name(e.getName()) + .type(e.getType()).build()).collect(Collectors.toList())) + .build(); + } + + private List getFeatureResourceBasic(List uniCodes, String terminal) { + List featureResources = saasFeatureResourceDao.lambdaQuery() + .eq(SaasFeatureResource::getTerminal, terminal) + .in(SaasFeatureResource::getUniCode, uniCodes) + .eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.getValue()) + .list(); + + List parentFrs = featureResources.stream().filter(e -> { + if (Objects.isNull(e.getFeatureType())) { + return false; + } + return FeatureResourceType.PAGE.getCode().equals(e.getFeatureType()); + }).collect(Collectors.toList()); + List componentAndAppEntityParentIds = featureResources.stream().filter(e -> { + if (Objects.isNull(e.getFeatureType())) { + return false; + } + return FeatureResourceType.COMPONENT.getCode().equals(e.getFeatureType()) || FeatureResourceType.APP_ENTRY.getCode().equals(e.getFeatureType()); + }).map(SaasFeatureResource::getParentId).collect(Collectors.toList()); + + if (CollectionUtils.isNotEmpty(componentAndAppEntityParentIds)) { + List parentResources = saasFeatureResourceDao.lambdaQuery() + .eq(SaasFeatureResource::getTerminal, terminal) + .in(SaasFeatureResource::getId, componentAndAppEntityParentIds) + .eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.getValue()) + .list(); + if (CollectionUtils.isNotEmpty(parentResources)) { + parentFrs.addAll(parentResources); + } + } + parentFrs = parentFrs.stream().distinct().collect(Collectors.toList()); + + Map> childrenMap = featureResources.stream().filter(e -> FeatureResourceType.COMPONENT.getCode().equals(e.getFeatureType()) + || FeatureResourceType.APP_ENTRY.getCode().equals(e.getFeatureType())).collect(Collectors.groupingBy(SaasFeatureResource::getParentId)); + List allParents = parentFrs.stream().map(e -> FeatureResourcePageElementRelationViewResp.FeatureResourceBasicDTO.builder() + .id(e.getId()) + .uniCode(e.getUniCode()) + .featureName(e.getFeatureName()) + .featureType(e.getFeatureType()) + .children(Lists.newArrayList()) + .build()).distinct().collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(allParents)) { + return null; + } + for (FeatureResourcePageElementRelationViewResp.FeatureResourceBasicDTO basic : allParents) { + List children = childrenMap.get(basic.getId()); + if (CollectionUtils.isEmpty(children)) { + continue; + } + basic.setChildren(children.stream().map(e -> FeatureResourcePageElementRelationViewResp.FeatureResourceBasicDTO.builder() + .id(e.getId()) + .uniCode(e.getUniCode()) + .featureName(e.getFeatureName()) + .featureType(e.getFeatureType()) + .build()).collect(Collectors.toList())); + } + + return allParents; + } + + private void fillElementToResource(List resources, List relations, + FeatureResourcePageElementRelationViewResp.PageElementBasicDTO elementBasic) { + Map relationMap = relations.stream().collect(Collectors.toMap(r -> r.getFeatureResourceUniCode() + "_" + r.getPageElementCode(), Function.identity(), (v1, v2) -> v1)); + for (FeatureResourcePageElementRelationViewResp.FeatureResourceBasicDTO resource : resources) { + recursiveSetElementToResource(resource, relationMap, elementBasic); + } + } + + private void recursiveSetElementToResource(FeatureResourcePageElementRelationViewResp.FeatureResourceBasicDTO resource, Map relationMap, + FeatureResourcePageElementRelationViewResp.PageElementBasicDTO elementBasic) { + if (Objects.isNull(resource)) { + return; + } + if (!FeatureResourceType.GROUP.getCode().equals(resource.getFeatureType())) { + FeatureResourcePageElementRelationViewResp.PageElementBasicDTO newPageElementBasic = FeatureResourcePageElementRelationViewResp.PageElementBasicDTO.builder() + .id(elementBasic.getId()) + .groupCode(elementBasic.getGroupCode()) + .groupName(elementBasic.getGroupName()) + .code(elementBasic.getCode()) + .name(elementBasic.getName()) + .type(elementBasic.getType()) + .hasRelation(Optional.ofNullable(relationMap.get(resource.getUniCode() + "_" + elementBasic.getCode())).isPresent()) + .relationType(Optional.ofNullable(relationMap.get(resource.getUniCode() + "_" + elementBasic.getCode())).map(SaasPageElementFeatureResourceRelation::getType).orElse(0)) + .build(); + if (CollectionUtils.isNotEmpty(elementBasic.getChildren())) { + newPageElementBasic.setChildren(elementBasic.getChildren().stream().map(e -> FeatureResourcePageElementRelationViewResp.PageElementBasicDTO.builder() + .id(e.getId()) + .groupCode(e.getGroupCode()) + .groupName(e.getGroupName()) + .code(e.getCode()) + .name(e.getName()) + .type(e.getType()) + .hasRelation(Optional.ofNullable(relationMap.get(resource.getUniCode() + "_" + e.getCode())).isPresent()) + .relationType(Optional.ofNullable(relationMap.get(resource.getUniCode() + "_" + e.getCode())).map(SaasPageElementFeatureResourceRelation::getType).orElse(0)) + .build()).collect(Collectors.toList())); + } + resource.setPageElement(newPageElementBasic); + } + + if (CollectionUtils.isNotEmpty(resource.getChildren())) { + resource.getChildren().forEach(e -> recursiveSetElementToResource(e, relationMap, elementBasic)); + } + + } } From 59f0748d2c55b8e31f1f2f75df765b6b732c42c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Mon, 26 Aug 2024 19:34:45 +0800 Subject: [PATCH 05/27] =?UTF-8?q?feat(REQ-2899):=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=E8=B5=84=E6=BA=90=E5=88=A0=E9=99=A4=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/model/req/GetPageElementReq.java | 6 ++++++ .../impl/SaasPageElementServiceImpl.java | 18 +++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/GetPageElementReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/GetPageElementReq.java index 56d0c85d..cdf95126 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/GetPageElementReq.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/GetPageElementReq.java @@ -40,4 +40,10 @@ public class GetPageElementReq { */ @Builder.Default private List relationTypes = Lists.newArrayList(0, 1); + + /** + * 是否按组分组返回 + */ + @Builder.Default + private Boolean returnWithGroup = Boolean.FALSE; } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java index 378d22b1..829f5f6d 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java @@ -151,7 +151,8 @@ public class SaasPageElementServiceImpl extends ServiceImpl resps = change2PageElementResp(selectedPageElements, selectedIds); + return Boolean.TRUE.equals(request.getReturnWithGroup()) ? changeElementsWithGroup(resps) : resps; } @Override @@ -880,4 +881,19 @@ public class SaasPageElementServiceImpl extends ServiceImpl changeElementsWithGroup(List resps) { + if (CollectionUtils.isEmpty(resps)) { + return Collections.emptyList(); + } + Map groupCodeEntityMap = resps.stream().collect(Collectors.toMap(PageElementResp::getGroupCode, Function.identity(), (v1, v2) -> v1)); + Map> groupCodesMap = resps.stream().collect(Collectors.groupingBy(PageElementResp::getGroupCode)); + List result = Lists.newArrayList(); + groupCodesMap.forEach((k, v) -> { + PageElementResp groupEntity = groupCodeEntityMap.get(k); + result.add(PageElementResp.builder().groupCode(k).groupName(groupEntity.getGroupName()).children(v).build()); + }); + + return result; + } } From bfa8a18432b72d2f97c736ea7d544b33b47fe3d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Tue, 27 Aug 2024 14:47:21 +0800 Subject: [PATCH 06/27] =?UTF-8?q?feat(REQ-2899):=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=E8=B5=84=E6=BA=90=E5=88=A0=E9=99=A4=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../axzo/tyr/client/feign/PageElementApi.java | 9 ++-- .../client/model/req/GetPageElementReq.java | 6 --- .../PageElementCategoryAndElementResp.java | 26 ++++++++++++ .../tyr/client/model/res/PageElementResp.java | 3 ++ .../permission/PageElementController.java | 7 +--- .../service/SaasPageElementService.java | 7 +--- .../impl/SaasPageElementServiceImpl.java | 42 ++++++++++++------- 7 files changed, 62 insertions(+), 38 deletions(-) create mode 100644 tyr-api/src/main/java/cn/axzo/tyr/client/model/res/PageElementCategoryAndElementResp.java diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java index e57ad4b5..c6bdb2bc 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java @@ -3,10 +3,7 @@ package cn.axzo.tyr.client.feign; import cn.axzo.framework.domain.web.result.ApiPageResult; import cn.axzo.framework.domain.web.result.ApiResult; import cn.axzo.tyr.client.model.req.*; -import cn.axzo.tyr.client.model.res.FeatureResourcePageElementRelationViewResp; -import cn.axzo.tyr.client.model.res.GetUserHasPermissionPageElementResp; -import cn.axzo.tyr.client.model.res.ListPageElementCategoryResp; -import cn.axzo.tyr.client.model.res.PageElementResp; +import cn.axzo.tyr.client.model.res.*; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -38,7 +35,7 @@ public interface PageElementApi { /** 分页查询页面资源 **/ @PostMapping("/api/pageElement/page") - ApiPageResult page(@RequestBody @Valid PageQueryElementReq req); + ApiPageResult page(@RequestBody @Valid PageQueryElementReq req); /** 根据用户传入的页面code,查询用户有权限的元素code **/ @PostMapping("/api/pageElement/getUserHasPermissionPageElement") @@ -71,7 +68,7 @@ public interface PageElementApi { @PostMapping("/api/pageElement/delete") ApiResult delete(@RequestBody @Valid DeletePageElementReq req); - /** 删除页面元素 **/ + /** 查询页面元素关联关系 **/ @PostMapping("/api/pageElement/getFeatureResourceRelations") ApiResult getFeatureResourceRelations(@RequestBody @Valid IdReq req); } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/GetPageElementReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/GetPageElementReq.java index cdf95126..56d0c85d 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/GetPageElementReq.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/GetPageElementReq.java @@ -40,10 +40,4 @@ public class GetPageElementReq { */ @Builder.Default private List relationTypes = Lists.newArrayList(0, 1); - - /** - * 是否按组分组返回 - */ - @Builder.Default - private Boolean returnWithGroup = Boolean.FALSE; } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/PageElementCategoryAndElementResp.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/PageElementCategoryAndElementResp.java new file mode 100644 index 00000000..fcda3eee --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/PageElementCategoryAndElementResp.java @@ -0,0 +1,26 @@ +package cn.axzo.tyr.client.model.res; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * @author likunpeng + * @version 1.0 + * @date 2024/8/27 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PageElementCategoryAndElementResp { + /** 项目编码 **/ + private String itemCode; + /** 项目名称 **/ + private String itemName; + /** 元素列表 **/ + private List pageElements; +} diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/PageElementResp.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/PageElementResp.java index 5f51c072..8fae72f1 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/PageElementResp.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/PageElementResp.java @@ -72,7 +72,10 @@ public class PageElementResp { */ private Boolean selected; + /** 业务编码 **/ private String itemCode; + /** 业务名称 **/ + private String itemName; private String linkExt; diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java index 2875c85c..27dd384e 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java @@ -4,10 +4,7 @@ import cn.axzo.framework.domain.web.result.ApiPageResult; import cn.axzo.framework.domain.web.result.ApiResult; import cn.axzo.tyr.client.feign.PageElementApi; import cn.axzo.tyr.client.model.req.*; -import cn.axzo.tyr.client.model.res.FeatureResourcePageElementRelationViewResp; -import cn.axzo.tyr.client.model.res.GetUserHasPermissionPageElementResp; -import cn.axzo.tyr.client.model.res.ListPageElementCategoryResp; -import cn.axzo.tyr.client.model.res.PageElementResp; +import cn.axzo.tyr.client.model.res.*; import cn.axzo.tyr.server.service.SaasPageElementCategoryService; import cn.axzo.tyr.server.service.SaasPageElementService; import lombok.RequiredArgsConstructor; @@ -47,7 +44,7 @@ public class PageElementController implements PageElementApi { } @Override - public ApiPageResult page(PageQueryElementReq req) { + public ApiPageResult page(PageQueryElementReq req) { return ApiPageResult.ok(saasPageElementService.page(req)); } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java index 1ecc29c6..cabd9946 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java @@ -2,10 +2,7 @@ package cn.axzo.tyr.server.service; import cn.axzo.framework.domain.page.PageResp; import cn.axzo.tyr.client.model.req.*; -import cn.axzo.tyr.client.model.res.FeatureResourcePageElementRelationViewResp; -import cn.axzo.tyr.client.model.res.GetUserHasPermissionPageElementResp; -import cn.axzo.tyr.client.model.res.PageElementBasicDTO; -import cn.axzo.tyr.client.model.res.PageElementResp; +import cn.axzo.tyr.client.model.res.*; import cn.axzo.tyr.server.repository.entity.SaasPageElement; import com.baomidou.mybatisplus.extension.service.IService; @@ -64,7 +61,7 @@ public interface SaasPageElementService extends IService { * @param request 查询条件 * @return */ - PageResp page(PageQueryElementReq request); + PageResp page(PageQueryElementReq request); /** * 根据用户传入的页面code,查询用户有权限的元素code diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java index 829f5f6d..02ce55da 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java @@ -151,8 +151,7 @@ public class SaasPageElementServiceImpl extends ServiceImpl resps = change2PageElementResp(selectedPageElements, selectedIds); - return Boolean.TRUE.equals(request.getReturnWithGroup()) ? changeElementsWithGroup(resps) : resps; + return change2PageElementResp(selectedPageElements, selectedIds); } @Override @@ -231,17 +230,21 @@ public class SaasPageElementServiceImpl extends ServiceImpl page(PageQueryElementReq request) { + public PageResp page(PageQueryElementReq request) { IPage page = saasPageElementDao.lambdaQuery() .eq(SaasPageElement::getTerminal, request.getTerminal()) .in(CollectionUtils.isNotEmpty(request.getElementTypes()), SaasPageElement::getType, request.getElementTypes()) .and(StringUtils.isNotBlank(request.getSearchKey()), w -> w.like(SaasPageElement::getCode, request.getSearchKey()) .or().like(SaasPageElement::getName, request.getSearchKey()) - .or().like(SaasPageElement::getLinkUrl, request.getSearchKey())) + .or().like(SaasPageElement::getLinkUrl, request.getSearchKey()) + .or().like(SaasPageElement::getItemCode, request.getSearchKey()) + .or().like(SaasPageElement::getItemName, request.getSearchKey())) .page(new Page<>(request.getPage(), request.getPageSize())); List list = BeanMapper.copyList(page.getRecords(), PageElementResp.class); addComponentElement2Page(request.getTerminal(), list); - return PageResp.list(page.getCurrent(), page.getSize(), page.getTotal(), list); + + List categoryAndElementResps = changeElementWithCategories(list); + return PageResp.list(page.getCurrent(), page.getSize(), page.getTotal(), categoryAndElementResps); } @Override @@ -366,6 +369,8 @@ public class SaasPageElementServiceImpl extends ServiceImpl pageTypeElements = pageElements.stream().filter(e -> PageElementTypeEnum.PAGE.getCode().equals(e.getType())) .map(e -> PageElementResp.builder() .id(e.getId()) + .groupCode(e.getGroupCode()) + .groupName(e.getName()) .code(e.getCode()) .name(e.getName()) .type(e.getType()) @@ -383,6 +388,8 @@ public class SaasPageElementServiceImpl extends ServiceImpl recursiveSetElementToResource(e, relationMap, elementBasic)); } - } - private List changeElementsWithGroup(List resps) { - if (CollectionUtils.isEmpty(resps)) { - return Collections.emptyList(); + private List changeElementWithCategories(List list) { + List resps = Lists.newArrayList(); + if (CollectionUtils.isEmpty(list)) { + return resps; } - Map groupCodeEntityMap = resps.stream().collect(Collectors.toMap(PageElementResp::getGroupCode, Function.identity(), (v1, v2) -> v1)); - Map> groupCodesMap = resps.stream().collect(Collectors.groupingBy(PageElementResp::getGroupCode)); - List result = Lists.newArrayList(); - groupCodesMap.forEach((k, v) -> { - PageElementResp groupEntity = groupCodeEntityMap.get(k); - result.add(PageElementResp.builder().groupCode(k).groupName(groupEntity.getGroupName()).children(v).build()); + Map itemCodeAndElementMap = list.stream().collect(Collectors.toMap(PageElementResp::getItemCode, Function.identity(), (v1, v2) -> v1)); + Map> groupingByItemCodes = list.stream().collect(Collectors.groupingBy(PageElementResp::getItemCode)); + groupingByItemCodes.forEach((k, v) -> { + PageElementResp resp = itemCodeAndElementMap.get(k); + resps.add(PageElementCategoryAndElementResp.builder() + .itemCode(k) + .itemName(resp.getItemName()) + .pageElements(v) + .build()); }); - return result; + return resps; } } From d643dae9c40ce79c956eedbeb681216e83d5c555 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Tue, 27 Aug 2024 16:59:56 +0800 Subject: [PATCH 07/27] =?UTF-8?q?feat(REQ-2899):=E8=8F=9C=E5=8D=95?= =?UTF-8?q?=E8=B5=84=E6=BA=90=E6=94=AF=E6=8C=81=E4=BF=AE=E6=94=B9=E7=88=B6?= =?UTF-8?q?=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/req/DeletePageElementCategoryReq.java | 2 -- .../tyr/client/model/req/DeletePageElementReq.java | 2 -- .../req/SaveOrUpdatePageElementCategoryReq.java | 2 -- .../client/model/req/SaveOrUpdatePageElementReq.java | 2 -- .../service/impl/SaasFeatureResourceServiceImpl.java | 12 +++++++++--- 5 files changed, 9 insertions(+), 11 deletions(-) diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/DeletePageElementCategoryReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/DeletePageElementCategoryReq.java index 274d0938..b0942aa8 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/DeletePageElementCategoryReq.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/DeletePageElementCategoryReq.java @@ -25,7 +25,5 @@ public class DeletePageElementCategoryReq { private Long id; /** 操作人personId **/ - @NotNull(message = "操作人不能为空") - @Min(value = 1, message = "操作人有误") private Long operatorId; } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/DeletePageElementReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/DeletePageElementReq.java index aac41833..eef88523 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/DeletePageElementReq.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/DeletePageElementReq.java @@ -25,7 +25,5 @@ public class DeletePageElementReq { private Long id; /** 操作人personId **/ - @NotNull(message = "操作人不能为空") - @Min(value = 1, message = "操作人有误") private Long operatorId; } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementCategoryReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementCategoryReq.java index e274380d..8b48c48c 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementCategoryReq.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementCategoryReq.java @@ -34,7 +34,5 @@ public class SaveOrUpdatePageElementCategoryReq { private String terminal; /** 操作人personId **/ - @NotNull(message = "操作人不能为空") - @Min(value = 1, message = "操作人有误") private Long operatorId; } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementReq.java index 51f391b0..97ad2f9a 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementReq.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementReq.java @@ -59,7 +59,5 @@ public class SaveOrUpdatePageElementReq { private Integer version; /** 操作人personId **/ - @NotNull(message = "操作人不能为空") - @Min(value = 1, message = "操作人有误") private Long operatorId; } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceServiceImpl.java index 940cc68b..e62f504b 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceServiceImpl.java @@ -270,8 +270,13 @@ public class SaasFeatureResourceServiceImpl extends ServiceImpl Date: Thu, 29 Aug 2024 16:57:35 +0800 Subject: [PATCH 08/27] =?UTF-8?q?feat(REQ-2899):=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=AF=BC=E5=85=A5=E6=8E=A5=E5=8F=A3=EF=BC=8C=E6=9A=82=E6=B2=A1?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E3=80=82=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../axzo/tyr/client/feign/PageElementApi.java | 4 + .../model/req/PageElementImportDataReq.java | 86 +++++++++++++++++++ .../model/req/SaveOrUpdatePageElementReq.java | 4 +- .../permission/PageElementController.java | 6 ++ .../service/SaasPageElementService.java | 2 + .../impl/SaasPageElementServiceImpl.java | 7 ++ 6 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PageElementImportDataReq.java diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java index c6bdb2bc..073ea5c4 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java @@ -71,4 +71,8 @@ public interface PageElementApi { /** 查询页面元素关联关系 **/ @PostMapping("/api/pageElement/getFeatureResourceRelations") ApiResult getFeatureResourceRelations(@RequestBody @Valid IdReq req); + + /** 查询页面元素关联关系 **/ + @PostMapping("/api/pageElement/importData") + ApiResult importData(@RequestBody @Valid PageElementImportDataReq req); } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PageElementImportDataReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PageElementImportDataReq.java new file mode 100644 index 00000000..2cf3acf5 --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PageElementImportDataReq.java @@ -0,0 +1,86 @@ +package cn.axzo.tyr.client.model.req; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; + +/** + * @author likunpeng + * @version 1.0 + * @date 2024/8/29 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PageElementImportDataReq implements Serializable { + + /** + * 端 + */ + @NotBlank(message = "端信息不能为空") + private String terminal; + + /** + * 元素分类 + */ + @NotBlank(message = "元素分类不能为空") + private String itemCode; + + /** + * 元素组编码 + */ + @NotBlank(message = "元素组编码不能为空") + private String groupCode; + + /** + * 元素编码 + */ + @NotBlank(message = "元素编码不能为空") + private String code; + + /** + * 元素名称 + */ + @NotBlank(message = "元素名称不能为空") + private String name; + + /** + * 元素类型(PAGE:页面,COMPONENT:页面里的组件) + */ + @NotBlank(message = "元素类型不能为空") + private String type; + + /** + * 元素资源类型:APP、H5、PC + */ + @NotBlank(message = "元素资源类型不能为空") + private String appType; + + /** + * H5的appId + */ + private String appId; + + /** + * 元素支持的最低版本号 + */ + private Integer version; + + /** + * 路由地址 + */ + private String linkUrl; + + /** ios跳转地址 **/ + private String iosRouterUrl; + + /** android跳转地址 **/ + private String androidRouterUrl; + + private Long operatorId; +} diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementReq.java index 97ad2f9a..2b9a38ae 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementReq.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementReq.java @@ -49,10 +49,10 @@ public class SaveOrUpdatePageElementReq { /** pc/h5路由地址 **/ private String linkUrl; - /** ios挑战地址 **/ + /** ios跳转地址 **/ private String iosRouterUrl; - /** android挑战地址 **/ + /** android跳转地址 **/ private String androidRouterUrl; /** 版本号 **/ diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java index 27dd384e..8ac431b1 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java @@ -95,4 +95,10 @@ public class PageElementController implements PageElementApi { public ApiResult getFeatureResourceRelations(IdReq req) { return ApiResult.ok(saasPageElementService.getFeatureResourceRelations(req.getId())); } + + @Override + public ApiResult importData(PageElementImportDataReq req) { + saasPageElementService.importData(req); + return ApiResult.ok(); + } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java index cabd9946..b23f79b9 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java @@ -83,4 +83,6 @@ public interface SaasPageElementService extends IService { void delete(DeletePageElementReq req); FeatureResourcePageElementRelationViewResp getFeatureResourceRelations(Long pageElementId); + + void importData(PageElementImportDataReq req); } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java index 02ce55da..00d8cbc3 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java @@ -649,6 +649,13 @@ public class SaasPageElementServiceImpl extends ServiceImpl> featureResources) { PageElementResp pageElementResp = PageElementResp.builder().build(); From 293897e6978443363ed64566ac57e0b39b22cca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Fri, 30 Aug 2024 20:24:48 +0800 Subject: [PATCH 09/27] =?UTF-8?q?feat(REQ-2899):=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=AF=BC=E5=85=A5=E6=8E=A5=E5=8F=A3=EF=BC=8C=E6=9A=82=E6=B2=A1?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E3=80=82=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../axzo/tyr/client/feign/PageElementApi.java | 4 +- .../model/req/SaveOrUpdatePageElementReq.java | 2 +- ...reResourcePageElementRelationViewResp.java | 97 -------- .../res/ListPageElementCategoryResp.java | 2 + ...ageElementRelationFeatureResourceResp.java | 82 +++++++ .../tyr/server/TyrServerDevApplication.java | 1 + .../permission/PageElementController.java | 4 +- .../service/SaasPageElementService.java | 4 +- .../SaasPageElementCategoryServiceImpl.java | 1 + .../impl/SaasPageElementServiceImpl.java | 222 ++++++------------ 10 files changed, 169 insertions(+), 250 deletions(-) delete mode 100644 tyr-api/src/main/java/cn/axzo/tyr/client/model/res/FeatureResourcePageElementRelationViewResp.java create mode 100644 tyr-api/src/main/java/cn/axzo/tyr/client/model/res/PageElementRelationFeatureResourceResp.java diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java index 073ea5c4..c42e63d2 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PageElementApi.java @@ -70,9 +70,9 @@ public interface PageElementApi { /** 查询页面元素关联关系 **/ @PostMapping("/api/pageElement/getFeatureResourceRelations") - ApiResult getFeatureResourceRelations(@RequestBody @Valid IdReq req); + ApiResult> getFeatureResourceRelations(@RequestBody @Valid IdReq req); /** 查询页面元素关联关系 **/ @PostMapping("/api/pageElement/importData") - ApiResult importData(@RequestBody @Valid PageElementImportDataReq req); + ApiResult importData(@RequestBody @Valid List req); } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementReq.java index 2b9a38ae..c483477b 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementReq.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaveOrUpdatePageElementReq.java @@ -26,7 +26,7 @@ public class SaveOrUpdatePageElementReq { private String itemCode; /** 分组ID **/ - private Long pageId; + private String groupCode; /** 页面元素类型:PAGE/COMPONENT **/ @NotBlank(message = "页面元素类型不能为空") diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/FeatureResourcePageElementRelationViewResp.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/FeatureResourcePageElementRelationViewResp.java deleted file mode 100644 index d8f2479e..00000000 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/FeatureResourcePageElementRelationViewResp.java +++ /dev/null @@ -1,97 +0,0 @@ -package cn.axzo.tyr.client.model.res; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.List; - -/** - * @author likunpeng - * @version 1.0 - * @date 2024/8/23 - */ -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class FeatureResourcePageElementRelationViewResp { - - /** 菜单资源列表 **/ - private List featureResources; - - @Data - @Builder - @NoArgsConstructor - @AllArgsConstructor - public static class FeatureResourceBasicDTO { - - private Long id; - - /** - * 资源编码-权限码 - */ - private String uniCode; - - /** - * 资源名称 - */ - private String featureName; - - /** - * 资源类型1-菜单 2-页面 3-应用入口 4-组件 5-root 6-分组 - */ - private Integer featureType; - - /** 前端元素资源列表 **/ - private PageElementBasicDTO pageElement; - - private List children; - } - - @Data - @Builder - @NoArgsConstructor - @AllArgsConstructor - public static class PageElementBasicDTO { - private Long id; - /** - * 元素的组编码 - */ - private String groupCode; - - /** - * 元素的组编码 - */ - private String groupName; - - /** - * 元素编码 - */ - private String code; - - /** - * 元素名称 - */ - private String name; - - /** - * 元素类型 - */ - private String type; - - /** - * 是否关联 - */ - private Boolean hasRelation; - - /** - * 1:路由页面 - */ - private Integer relationType; - - - private List children; - } -} diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/ListPageElementCategoryResp.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/ListPageElementCategoryResp.java index 0ccf85bd..7a269fba 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/ListPageElementCategoryResp.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/ListPageElementCategoryResp.java @@ -35,5 +35,7 @@ public class ListPageElementCategoryResp { private String itemCode; /** 项目名称 **/ private String itemName; + /** 端 **/ + private String terminal; } } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/PageElementRelationFeatureResourceResp.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/PageElementRelationFeatureResourceResp.java new file mode 100644 index 00000000..cf6df342 --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/PageElementRelationFeatureResourceResp.java @@ -0,0 +1,82 @@ +package cn.axzo.tyr.client.model.res; + +import cn.axzo.basics.common.model.IBaseTree; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** +* @author likunpeng +* @date 2024/8/30 +* @version 1.0 +*/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PageElementRelationFeatureResourceResp implements IBaseTree { + + private Long id; + + /** + * 上级资源ID + */ + private Long parentId; + + /** + * 资源编码-权限码 + */ + private String uniCode; + + /** + * 资源名称 + */ + private String featureName; + + /** + * 资源类型1-菜单 2-页面 3-应用入口 4-组件 5-root 6-分组 + */ + private Integer featureType; + + /** + * 子节点 + */ + private List children; + + /** + * 是否关联 + */ + private Boolean hasRelation; + + /** + * 1:路由页面 + */ + private Integer relationType; + + @JsonIgnore + @Override + public Long getNodeCode() { + return this.getId(); + } + + @JsonIgnore + @Override + public Long getParentNodeCode() { + return this.getParentId(); + } + + @JsonIgnore + @Override + public List getNodeChildren() { + return this.children; + } + + @Override + public void setNodeChildren(List nodeChildren) { + this.children = nodeChildren; + } +} diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/TyrServerDevApplication.java b/tyr-server/src/main/java/cn/axzo/tyr/server/TyrServerDevApplication.java index b15ee22a..e18dedb6 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/TyrServerDevApplication.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/TyrServerDevApplication.java @@ -31,6 +31,7 @@ public class TyrServerDevApplication { System.setProperty("spring.redis.host","172.16.2.23"); System.setProperty("xxl.job.admin.addresses","http://dev-xxl-job.axzo.cn/xxl-job-admin"); System.setProperty("rocketmq.name-server", "172.16.2.82:9876"); + System.setProperty("spring.datasource.url", "jdbc:mysql://172.16.2.171:3306/pudge?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=Asia/Shanghai&useSSL=true&verifyServerCertificate=false&rewriteBatchedStatements=true"); SpringApplication application = new SpringApplication(TyrServerDevApplication.class); ApplicationContext applicationContext = application.run(args); Environment env = applicationContext.getEnvironment(); diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java index 8ac431b1..83c37734 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PageElementController.java @@ -92,12 +92,12 @@ public class PageElementController implements PageElementApi { } @Override - public ApiResult getFeatureResourceRelations(IdReq req) { + public ApiResult> getFeatureResourceRelations(IdReq req) { return ApiResult.ok(saasPageElementService.getFeatureResourceRelations(req.getId())); } @Override - public ApiResult importData(PageElementImportDataReq req) { + public ApiResult importData(List req) { saasPageElementService.importData(req); return ApiResult.ok(); } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java index b23f79b9..c7097a19 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasPageElementService.java @@ -82,7 +82,7 @@ public interface SaasPageElementService extends IService { void delete(DeletePageElementReq req); - FeatureResourcePageElementRelationViewResp getFeatureResourceRelations(Long pageElementId); + List getFeatureResourceRelations(Long pageElementId); - void importData(PageElementImportDataReq req); + void importData(List req); } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementCategoryServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementCategoryServiceImpl.java index 3d4c77d6..09120600 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementCategoryServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementCategoryServiceImpl.java @@ -61,6 +61,7 @@ public class SaasPageElementCategoryServiceImpl implements SaasPageElementCatego .id(c.getId()) .itemCode(c.getItemCode()) .itemName(c.getItemName()) + .terminal(c.getTerminal()) .build()).collect(Collectors.toList())).build()); }); return categoryResps; diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java index 00d8cbc3..9f03e121 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java @@ -4,6 +4,7 @@ import cn.axzo.basics.common.BeanMapper; import cn.axzo.basics.common.constant.enums.DeleteEnum; import cn.axzo.basics.common.util.AssertUtil; import cn.axzo.basics.common.util.StopWatchUtil; +import cn.axzo.basics.common.util.TreeUtil; import cn.axzo.basics.profiles.api.UserProfileServiceApi; import cn.axzo.basics.profiles.dto.basic.PersonProfileDto; import cn.axzo.foundation.dao.support.converter.PageConverter; @@ -562,10 +563,10 @@ public class SaasPageElementServiceImpl extends ServiceImpl 0, "页面元素不存在"); + AssertUtil.isTrue(StringUtils.isNotBlank(req.getGroupCode()), "页面元素不存在"); List pageElements = saasPageElementDao.lambdaQuery() .eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.getValue()) - .eq(SaasPageElement::getId, req.getPageId()).list(); + .eq(SaasPageElement::getCode, req.getGroupCode()).list(); AssertUtil.notEmpty(pageElements, "父级元素不存在。"); SaasPageElement pageElement = pageElements.get(0); @@ -622,38 +623,95 @@ public class SaasPageElementServiceImpl extends ServiceImpl getFeatureResourceRelations(Long pageElementId) { SaasPageElement dbPageElement = saasPageElementDao.getById(pageElementId); AssertUtil.notNull(dbPageElement, "页面元素资源不存在"); - List pageElements = saasPageElementDao.listByGroupCodesAndExcludeIds(Lists.newArrayList(dbPageElement.getGroupCode()), null, dbPageElement.getTerminal(), null); - FeatureResourcePageElementRelationViewResp.PageElementBasicDTO elementBasic = getPageElementBasic(pageElements); - if (Objects.isNull(elementBasic)) { - return null; - } List relations = saasPageElementFeatureResourceRelationDao.lambdaQuery() .eq(SaasPageElementFeatureResourceRelation::getIsDelete, DeleteEnum.NORMAL.getValue()) - .in(SaasPageElementFeatureResourceRelation::getPageElementCode, pageElements.stream().map(SaasPageElement::getCode).collect(Collectors.toSet())) + .eq(SaasPageElementFeatureResourceRelation::getPageElementCode, dbPageElement.getCode()) .eq(SaasPageElementFeatureResourceRelation::getTerminal, dbPageElement.getTerminal()) .list(); if (CollectionUtils.isEmpty(relations)) { - return null; - } - List featureResourceBasics = getFeatureResourceBasic(relations.stream().map(SaasPageElementFeatureResourceRelation::getFeatureResourceUniCode).collect(Collectors.toList()), dbPageElement.getTerminal()); - if (CollectionUtils.isEmpty(featureResourceBasics)) { - return null; + return Collections.emptyList(); } - fillElementToResource(featureResourceBasics, relations, elementBasic); + List pageFeatureResources = saasFeatureResourceDao.lambdaQuery() + .eq(SaasFeatureResource::getTerminal, dbPageElement.getTerminal()) + .in(SaasFeatureResource::getUniCode, relations.stream().map(SaasPageElementFeatureResourceRelation::getFeatureResourceUniCode).collect(Collectors.toSet())) + .in(SaasFeatureResource::getFeatureType, Lists.newArrayList(FeatureResourceType.PAGE.getCode(), FeatureResourceType.APP_ENTRY.getCode())) + .eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.getValue()) + .list(); + if (CollectionUtils.isEmpty(pageFeatureResources)) { + return Collections.emptyList(); + } + List pageParentFeatureResources = saasFeatureResourceDao.lambdaQuery() + .eq(SaasFeatureResource::getTerminal, dbPageElement.getTerminal()) + .in(SaasFeatureResource::getId, pageFeatureResources.stream().map(SaasFeatureResource::getParentId).collect(Collectors.toSet())) + .eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.getValue()) + .list(); + List pageChildrenFeatureResources = saasFeatureResourceDao.lambdaQuery() + .eq(BaseEntity::getIsDelete,0) + .and(i -> pageFeatureResources.forEach(f -> i.or().likeRight(SaasFeatureResource::getPath, f.getPath()))) + .list(); + List allFeatureResources = Lists.newArrayList(pageFeatureResources); + if (CollectionUtils.isNotEmpty(pageParentFeatureResources)) { + allFeatureResources.addAll(pageParentFeatureResources); + } + if (CollectionUtils.isNotEmpty(pageChildrenFeatureResources)) { + allFeatureResources.addAll(pageChildrenFeatureResources); + } - return FeatureResourcePageElementRelationViewResp.builder().featureResources(featureResourceBasics).build(); + Map uniCodeRelationMap = relations.stream() + .collect(Collectors.toMap(SaasPageElementFeatureResourceRelation::getFeatureResourceUniCode, Function.identity(), (v1, v2) -> v1)); + List reps = allFeatureResources.stream().map(e -> PageElementRelationFeatureResourceResp.builder() + .id(e.getId()) + .parentId(e.getParentId()) + .uniCode(e.getUniCode()) + .featureName(e.getFeatureName()) + .featureType(e.getFeatureType()) + .hasRelation(uniCodeRelationMap.containsKey(e.getUniCode())) + .relationType(Optional.ofNullable(uniCodeRelationMap.get(e.getUniCode())).map(SaasPageElementFeatureResourceRelation::getType).orElse(null)) + .build()).distinct().collect(Collectors.toList()); + + return TreeUtil.buildTree(reps); } @Override - public void importData(PageElementImportDataReq req) { - saasPageElementDao.lambdaQuery() + public void importData(List req) { + Integer codeCount = saasPageElementDao.lambdaQuery() .eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.getValue()) + .in(SaasPageElement::getCode, req.stream().map(PageElementImportDataReq::getCode).collect(Collectors.toList())) .count(); + AssertUtil.isTrue(codeCount <= 0, "导入的资源编码已存在。"); + + Set itemCodes = req.stream().map(PageElementImportDataReq::getItemCode).collect(Collectors.toSet()); + List categories = saasPageElementCategoryDao.lambdaQuery() + .eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.getValue()) + .in(SaasPageElementCategory::getItemCode, itemCodes) + .list(); + AssertUtil.isTrue(itemCodes.size() == categories.size(), "元素分类编码系统中有未存在的。"); + Map categoryMap = categories.stream().collect(Collectors.toMap(SaasPageElementCategory::getItemCode, Function.identity(), (v1, v2) -> v1)); + + List elements = req.stream().map(e -> { + SaasPageElementCategory category = categoryMap.get(e.getItemCode()); + AssertUtil.notNull(category, e.getItemCode() + "不存在。"); + return SaasPageElement.builder() + .version(e.getVersion()) + .groupCode(e.getGroupCode()) + .code(e.getCode()) + .name(e.getName()) + .type(e.getType()) + .linkUrl(e.getLinkUrl()) + .terminal(e.getTerminal()) + .appType(e.getAppType()) + .itemCode(e.getItemCode()) + .itemName(category.getItemName()) + .createName(Optional.ofNullable(e.getOperatorId()).map(Objects::toString).orElse(StringUtils.EMPTY)) + .appId(e.getAppId()) + .build(); + }).collect(Collectors.toList()); + Lists.partition(elements,500).forEach(saasPageElementDao::saveBatch); } private PageElementResp from(SaasPageElement saasPageElement, @@ -767,134 +825,6 @@ public class SaasPageElementServiceImpl extends ServiceImpl pageElements) { - SaasPageElement pageTypeElement = pageElements.stream().filter(e -> PageElementTypeEnum.PAGE.getCode().equals(e.getType())).findFirst().orElse(null); - if (Objects.isNull(pageTypeElement)) { - return null; - } - - return FeatureResourcePageElementRelationViewResp.PageElementBasicDTO.builder() - .id(pageTypeElement.getId()) - .groupCode(pageTypeElement.getGroupCode()) - .groupName(pageTypeElement.getName()) - .code(pageTypeElement.getCode()) - .name(pageTypeElement.getName()) - .type(pageTypeElement.getType()) - .children(pageElements.stream().filter(e -> PageElementTypeEnum.COMPONENT.getCode().equals(e.getType())).map(e -> FeatureResourcePageElementRelationViewResp.PageElementBasicDTO.builder() - .id(e.getId()) - .groupCode(pageTypeElement.getGroupCode()) - .groupName(pageTypeElement.getName()) - .code(e.getCode()) - .name(e.getName()) - .type(e.getType()).build()).collect(Collectors.toList())) - .build(); - } - - private List getFeatureResourceBasic(List uniCodes, String terminal) { - List featureResources = saasFeatureResourceDao.lambdaQuery() - .eq(SaasFeatureResource::getTerminal, terminal) - .in(SaasFeatureResource::getUniCode, uniCodes) - .eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.getValue()) - .list(); - - List parentFrs = featureResources.stream().filter(e -> { - if (Objects.isNull(e.getFeatureType())) { - return false; - } - return FeatureResourceType.PAGE.getCode().equals(e.getFeatureType()); - }).collect(Collectors.toList()); - List componentAndAppEntityParentIds = featureResources.stream().filter(e -> { - if (Objects.isNull(e.getFeatureType())) { - return false; - } - return FeatureResourceType.COMPONENT.getCode().equals(e.getFeatureType()) || FeatureResourceType.APP_ENTRY.getCode().equals(e.getFeatureType()); - }).map(SaasFeatureResource::getParentId).collect(Collectors.toList()); - - if (CollectionUtils.isNotEmpty(componentAndAppEntityParentIds)) { - List parentResources = saasFeatureResourceDao.lambdaQuery() - .eq(SaasFeatureResource::getTerminal, terminal) - .in(SaasFeatureResource::getId, componentAndAppEntityParentIds) - .eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.getValue()) - .list(); - if (CollectionUtils.isNotEmpty(parentResources)) { - parentFrs.addAll(parentResources); - } - } - parentFrs = parentFrs.stream().distinct().collect(Collectors.toList()); - - Map> childrenMap = featureResources.stream().filter(e -> FeatureResourceType.COMPONENT.getCode().equals(e.getFeatureType()) - || FeatureResourceType.APP_ENTRY.getCode().equals(e.getFeatureType())).collect(Collectors.groupingBy(SaasFeatureResource::getParentId)); - List allParents = parentFrs.stream().map(e -> FeatureResourcePageElementRelationViewResp.FeatureResourceBasicDTO.builder() - .id(e.getId()) - .uniCode(e.getUniCode()) - .featureName(e.getFeatureName()) - .featureType(e.getFeatureType()) - .children(Lists.newArrayList()) - .build()).distinct().collect(Collectors.toList()); - - if (CollectionUtils.isEmpty(allParents)) { - return null; - } - for (FeatureResourcePageElementRelationViewResp.FeatureResourceBasicDTO basic : allParents) { - List children = childrenMap.get(basic.getId()); - if (CollectionUtils.isEmpty(children)) { - continue; - } - basic.setChildren(children.stream().map(e -> FeatureResourcePageElementRelationViewResp.FeatureResourceBasicDTO.builder() - .id(e.getId()) - .uniCode(e.getUniCode()) - .featureName(e.getFeatureName()) - .featureType(e.getFeatureType()) - .build()).collect(Collectors.toList())); - } - - return allParents; - } - - private void fillElementToResource(List resources, List relations, - FeatureResourcePageElementRelationViewResp.PageElementBasicDTO elementBasic) { - Map relationMap = relations.stream().collect(Collectors.toMap(r -> r.getFeatureResourceUniCode() + "_" + r.getPageElementCode(), Function.identity(), (v1, v2) -> v1)); - for (FeatureResourcePageElementRelationViewResp.FeatureResourceBasicDTO resource : resources) { - recursiveSetElementToResource(resource, relationMap, elementBasic); - } - } - - private void recursiveSetElementToResource(FeatureResourcePageElementRelationViewResp.FeatureResourceBasicDTO resource, Map relationMap, - FeatureResourcePageElementRelationViewResp.PageElementBasicDTO elementBasic) { - if (Objects.isNull(resource)) { - return; - } - if (!FeatureResourceType.GROUP.getCode().equals(resource.getFeatureType())) { - FeatureResourcePageElementRelationViewResp.PageElementBasicDTO newPageElementBasic = FeatureResourcePageElementRelationViewResp.PageElementBasicDTO.builder() - .id(elementBasic.getId()) - .groupCode(elementBasic.getGroupCode()) - .groupName(elementBasic.getGroupName()) - .code(elementBasic.getCode()) - .name(elementBasic.getName()) - .type(elementBasic.getType()) - .hasRelation(Optional.ofNullable(relationMap.get(resource.getUniCode() + "_" + elementBasic.getCode())).isPresent()) - .relationType(Optional.ofNullable(relationMap.get(resource.getUniCode() + "_" + elementBasic.getCode())).map(SaasPageElementFeatureResourceRelation::getType).orElse(0)) - .build(); - if (CollectionUtils.isNotEmpty(elementBasic.getChildren())) { - newPageElementBasic.setChildren(elementBasic.getChildren().stream().map(e -> FeatureResourcePageElementRelationViewResp.PageElementBasicDTO.builder() - .id(e.getId()) - .groupCode(e.getGroupCode()) - .groupName(e.getGroupName()) - .code(e.getCode()) - .name(e.getName()) - .type(e.getType()) - .hasRelation(Optional.ofNullable(relationMap.get(resource.getUniCode() + "_" + e.getCode())).isPresent()) - .relationType(Optional.ofNullable(relationMap.get(resource.getUniCode() + "_" + e.getCode())).map(SaasPageElementFeatureResourceRelation::getType).orElse(0)) - .build()).collect(Collectors.toList())); - } - resource.setPageElement(newPageElementBasic); - } - - if (CollectionUtils.isNotEmpty(resource.getChildren())) { - resource.getChildren().forEach(e -> recursiveSetElementToResource(e, relationMap, elementBasic)); - } - } - private List changeElementWithCategories(List list) { List resps = Lists.newArrayList(); if (CollectionUtils.isEmpty(list)) { From 3efcffff7510ef61de32ec7ba7225dd9897d1716 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Mon, 2 Sep 2024 12:47:06 +0800 Subject: [PATCH 10/27] =?UTF-8?q?feat(REQ-2899):=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=AF=BC=E5=85=A5=E6=8E=A5=E5=8F=A3=EF=BC=8C=E6=9A=82=E6=B2=A1?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E3=80=82=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/axzo/tyr/client/model/req/PageQueryElementV2Req.java | 5 +++++ .../tyr/server/service/impl/SaasPageElementServiceImpl.java | 1 + 2 files changed, 6 insertions(+) diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PageQueryElementV2Req.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PageQueryElementV2Req.java index a2643372..47b9abab 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PageQueryElementV2Req.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PageQueryElementV2Req.java @@ -21,6 +21,11 @@ public class PageQueryElementV2Req { private Long id; + /** + * 业务编码 + */ + private String itemCode; + /** * 端 */ diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java index 9f03e121..7d3139aa 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java @@ -504,6 +504,7 @@ public class SaasPageElementServiceImpl extends ServiceImpl page = saasPageElementDao.lambdaQuery() .eq(Objects.nonNull(request.getId()), SaasPageElement::getId, request.getId()) .eq(StringUtils.isNotBlank(request.getTerminal()), SaasPageElement::getTerminal, request.getTerminal()) + .eq(StringUtils.isNotBlank(request.getItemCode()), SaasPageElement::getItemCode, request.getItemCode()) .in(CollectionUtils.isNotEmpty(request.getElementTypes()), SaasPageElement::getType, request.getElementTypes()) .and(StringUtils.isNotBlank(request.getPageElementCodeOrName()), w -> w.like(SaasPageElement::getCode, request.getPageElementCodeOrName()) .or().like(SaasPageElement::getName, request.getPageElementCodeOrName())) From bf389fa81ae8f72f3c3f9156d8ca507cd61e7671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Tue, 3 Sep 2024 12:56:33 +0800 Subject: [PATCH 11/27] =?UTF-8?q?feat(REQ-2899):=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=AF=BC=E5=85=A5=E6=8E=A5=E5=8F=A3=EF=BC=8C=E6=9A=82=E6=B2=A1?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E3=80=82=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java index 7d3139aa..1124f9fc 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java @@ -680,6 +680,7 @@ public class SaasPageElementServiceImpl extends ServiceImpl req) { + log.info("导入资源的数量:{}", req.size()); Integer codeCount = saasPageElementDao.lambdaQuery() .eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.getValue()) .in(SaasPageElement::getCode, req.stream().map(PageElementImportDataReq::getCode).collect(Collectors.toList())) From ab3e0b5ef97dc42d5a96de01a966914a9f8d2b43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Tue, 3 Sep 2024 18:12:15 +0800 Subject: [PATCH 12/27] =?UTF-8?q?feat(REQ-2899):=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=AF=BC=E5=85=A5=E6=8E=A5=E5=8F=A3=EF=BC=8C=E6=9A=82=E6=B2=A1?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E3=80=82=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tyr/server/service/impl/SaasPageElementServiceImpl.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java index 1124f9fc..223d8efc 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java @@ -692,9 +692,8 @@ public class SaasPageElementServiceImpl extends ServiceImpl categoryMap = categories.stream().collect(Collectors.toMap(SaasPageElementCategory::getItemCode, Function.identity(), (v1, v2) -> v1)); - List elements = req.stream().map(e -> { SaasPageElementCategory category = categoryMap.get(e.getItemCode()); AssertUtil.notNull(category, e.getItemCode() + "不存在。"); From 991661c1fc631aa691ac3f6ad37417828bbdbc89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Wed, 4 Sep 2024 11:18:26 +0800 Subject: [PATCH 13/27] =?UTF-8?q?feat(REQ-2899):=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E5=85=83=E7=B4=A0=E5=88=86=E7=B1=BB=E3=80=81=E5=85=83=E7=B4=A0?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8F=91=E9=80=81mq=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/SaasPageElementCategoryServiceImpl.java | 16 ++++++++++++++++ .../service/impl/SaasPageElementServiceImpl.java | 9 +++++++++ 2 files changed, 25 insertions(+) diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementCategoryServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementCategoryServiceImpl.java index 09120600..3cbabbeb 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementCategoryServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementCategoryServiceImpl.java @@ -2,12 +2,15 @@ package cn.axzo.tyr.server.service.impl; import cn.axzo.basics.common.constant.enums.DeleteEnum; import cn.axzo.basics.common.util.AssertUtil; +import cn.axzo.framework.rocketmq.Event; import cn.axzo.pokonyan.config.mybatisplus.BaseEntity; import cn.axzo.tyr.client.common.enums.PermissionRelationOperateLogSceneEnum; import cn.axzo.tyr.client.model.req.DeletePageElementCategoryReq; import cn.axzo.tyr.client.model.req.PermissionOperateLogReq; import cn.axzo.tyr.client.model.req.SaveOrUpdatePageElementCategoryReq; import cn.axzo.tyr.client.model.res.ListPageElementCategoryResp; +import cn.axzo.tyr.server.config.MqProducer; +import cn.axzo.tyr.server.event.payload.PageElementFeatureResourceUpsertPayload; import cn.axzo.tyr.server.repository.dao.SaasPageElementCategoryDao; import cn.axzo.tyr.server.repository.dao.SaasPageElementDao; import cn.axzo.tyr.server.repository.dao.SaasPageElementFeatureResourceRelationDao; @@ -27,6 +30,8 @@ import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; +import static cn.axzo.tyr.server.event.inner.EventTypeEnum.PAGE_ELEMENT_FEATURE_RESOURCE_UPSERT; + /** * @author likunpeng * @version 1.0 @@ -38,11 +43,13 @@ import java.util.stream.Collectors; public class SaasPageElementCategoryServiceImpl implements SaasPageElementCategoryService { public static final String PAGE_ELEMENT_CATEGORY_TABLE_NAME = "saas_page_element_category"; + private static final String TARGET_TYPE = "pageElementFeatureResourceId"; private final SaasPageElementCategoryDao saasPageElementCategoryDao; private final SaasPageElementDao saasPageElementDao; private final SaasPageElementFeatureResourceRelationDao saasPageElementFeatureResourceRelationDao; private final SaasPgroupPermissionRelationOperateLogService saasPgroupPermissionRelationOperateLogService; + private final MqProducer mqProducer; @Override public List listGroupByTerminal() { @@ -132,6 +139,15 @@ public class SaasPageElementCategoryServiceImpl implements SaasPageElementCatego } catch (Exception e) { log.warn("save operate log error", e); } + + Event event = Event.builder() + .targetType(TARGET_TYPE) + .eventCode(PAGE_ELEMENT_FEATURE_RESOURCE_UPSERT.getEventCode()) + .data(PageElementFeatureResourceUpsertPayload.builder() + .terminal(dbCategory.getTerminal()) + .build()) + .build(); + mqProducer.send(event); } private void validItemCode(String itemCode) { diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java index 223d8efc..0835ef13 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java @@ -621,6 +621,15 @@ public class SaasPageElementServiceImpl extends ServiceImpl Date: Thu, 5 Sep 2024 09:34:54 +0800 Subject: [PATCH 14/27] =?UTF-8?q?feat(REQ-2899):cms=E4=B8=8A=E6=8A=A5?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=88=86=E7=B1=BBcode=E5=92=8C=E5=90=8D?= =?UTF-8?q?=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tyr/server/service/impl/SaasPageElementServiceImpl.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java index 0835ef13..0602c9f7 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java @@ -318,6 +318,8 @@ public class SaasPageElementServiceImpl extends ServiceImpl Date: Thu, 5 Sep 2024 14:10:11 +0800 Subject: [PATCH 15/27] =?UTF-8?q?feat(REQ-2899):cms=E4=B8=8A=E6=8A=A5?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=B5=84=E6=BA=90appType?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tyr/server/service/impl/SaasPageElementServiceImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java index 0602c9f7..b9a9d192 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java @@ -318,6 +318,7 @@ public class SaasPageElementServiceImpl extends ServiceImpl Date: Thu, 5 Sep 2024 14:25:52 +0800 Subject: [PATCH 16/27] =?UTF-8?q?feat(REQ-2899):cms=E4=B8=8A=E6=8A=A5?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=B5=84=E6=BA=90appType?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/enums/PageElementAppTypeEnum.java | 16 ++++++++++++++++ .../service/impl/SaasPageElementServiceImpl.java | 9 +++------ 2 files changed, 19 insertions(+), 6 deletions(-) create mode 100644 tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/PageElementAppTypeEnum.java diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/PageElementAppTypeEnum.java b/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/PageElementAppTypeEnum.java new file mode 100644 index 00000000..484edad4 --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/PageElementAppTypeEnum.java @@ -0,0 +1,16 @@ +package cn.axzo.tyr.client.common.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author likunpeng + * @version 1.0 + * @date 2024/9/5 + */ +@Getter +@AllArgsConstructor +public enum PageElementAppTypeEnum { + + PC,H5,APP; +} diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java index b9a9d192..413c9387 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java @@ -13,10 +13,7 @@ import cn.axzo.foundation.exception.BusinessException; import cn.axzo.framework.domain.page.PageResp; import cn.axzo.framework.rocketmq.Event; import cn.axzo.pokonyan.config.mybatisplus.BaseEntity; -import cn.axzo.tyr.client.common.enums.FeatureResourceType; -import cn.axzo.tyr.client.common.enums.PageElementFeatureResourceRelationTypeEnum; -import cn.axzo.tyr.client.common.enums.PageElementTypeEnum; -import cn.axzo.tyr.client.common.enums.PermissionRelationOperateLogSceneEnum; +import cn.axzo.tyr.client.common.enums.*; import cn.axzo.tyr.client.model.req.*; import cn.axzo.tyr.client.model.res.*; import cn.axzo.tyr.server.config.MqProducer; @@ -318,7 +315,7 @@ public class SaasPageElementServiceImpl extends ServiceImpl Date: Fri, 6 Sep 2024 11:28:51 +0800 Subject: [PATCH 17/27] =?UTF-8?q?feat:(HOTFIX)=20=E5=A4=84=E7=90=86?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E6=B2=A1=E6=9C=89=E6=9C=8D=E5=8A=A1=E5=8C=85?= =?UTF-8?q?=E5=AF=B9=E5=BA=94=E7=9A=84=E4=BA=A7=E5=93=81=E7=9A=84=E6=83=85?= =?UTF-8?q?=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/service/impl/WorkspaceProductServiceImpl.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/WorkspaceProductServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/WorkspaceProductServiceImpl.java index ecf78d73..0c3b6463 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/WorkspaceProductServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/WorkspaceProductServiceImpl.java @@ -240,9 +240,11 @@ public class WorkspaceProductServiceImpl implements WorkspaceProductService { List workspaceProductDTOS = Lists.newArrayList(); servicePkgDetailRes.forEach(e -> { - Set workpsaceProductIds = e.getProducts().stream() - .map(ServicePkgProduct::getProductId) - .collect(Collectors.toSet()); + Set workpsaceProductIds = Optional.ofNullable(e.getProducts()) + .map(products -> products.stream() + .map(ServicePkgProduct::getProductId) + .collect(Collectors.toSet())) + .orElse(null); if (CollectionUtils.isEmpty(workpsaceProductIds)) { return; } From 5b99747ed097be48587fd21b352830c1b933022a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Fri, 6 Sep 2024 14:44:00 +0800 Subject: [PATCH 18/27] =?UTF-8?q?feat(REQ-2899):=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E5=85=B3=E8=81=94=E5=85=B3=E7=B3=BB=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/SaasPageElementServiceImpl.java | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java index 413c9387..9a1f533c 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java @@ -649,15 +649,11 @@ public class SaasPageElementServiceImpl extends ServiceImpl pageFeatureResources = saasFeatureResourceDao.lambdaQuery() - .eq(SaasFeatureResource::getTerminal, dbPageElement.getTerminal()) - .in(SaasFeatureResource::getUniCode, relations.stream().map(SaasPageElementFeatureResourceRelation::getFeatureResourceUniCode).collect(Collectors.toSet())) - .in(SaasFeatureResource::getFeatureType, Lists.newArrayList(FeatureResourceType.PAGE.getCode(), FeatureResourceType.APP_ENTRY.getCode())) - .eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.getValue()) - .list(); + List pageFeatureResources = getPageFeatureResources(dbPageElement.getTerminal(), relations.stream().map(SaasPageElementFeatureResourceRelation::getFeatureResourceUniCode).collect(Collectors.toList())); if (CollectionUtils.isEmpty(pageFeatureResources)) { return Collections.emptyList(); } + List pageParentFeatureResources = saasFeatureResourceDao.lambdaQuery() .eq(SaasFeatureResource::getTerminal, dbPageElement.getTerminal()) .in(SaasFeatureResource::getId, pageFeatureResources.stream().map(SaasFeatureResource::getParentId).collect(Collectors.toSet())) @@ -856,4 +852,22 @@ public class SaasPageElementServiceImpl extends ServiceImpl getPageFeatureResources(String terminal, List uniCodes) { + List pageFeatureResources = saasFeatureResourceDao.lambdaQuery() + .eq(SaasFeatureResource::getTerminal, terminal) + .in(SaasFeatureResource::getUniCode, uniCodes) + .eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.getValue()) + .list(); + + List allIds = pageFeatureResources.stream().map(e -> Arrays.stream(e.getPath().split(",")).filter(StringUtils::isNotBlank).map(Long::valueOf) + .collect(Collectors.toList())).flatMap(List::stream).distinct().collect(Collectors.toList()); + + return saasFeatureResourceDao.lambdaQuery() + .eq(SaasFeatureResource::getTerminal, terminal) + .in(SaasFeatureResource::getId, allIds) + .in(SaasFeatureResource::getFeatureType, Lists.newArrayList(FeatureResourceType.PAGE.getCode(), FeatureResourceType.APP_ENTRY.getCode())) + .eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.getValue()) + .list(); + } } From 8a8c40be9e61a510312bbf79381b41023a8a6f64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Fri, 6 Sep 2024 16:14:49 +0800 Subject: [PATCH 19/27] =?UTF-8?q?feat(REQ-2899):=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E5=85=B3=E8=81=94=E5=85=B3=E7=B3=BB=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/permission/FeatureResourceController.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/FeatureResourceController.java b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/FeatureResourceController.java index fff49fd2..7deb0210 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/FeatureResourceController.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/FeatureResourceController.java @@ -10,6 +10,7 @@ import cn.axzo.tyr.client.model.res.FeatureResourceTreeNode; import cn.axzo.tyr.server.service.FeatureResourceSyncService; import cn.axzo.tyr.server.service.SaasFeatureResourceService; import cn.hutool.core.collection.CollectionUtil; +import com.alibaba.fastjson.JSON; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.RestController; @@ -52,7 +53,7 @@ public class FeatureResourceController implements FeatureResourceApi { @Override public ApiResult saveMenu(FeatureResourceTreeSaveReq req) { - log.info("save feature resource req : " + req.toString()); + log.info("save feature resource req : " + JSON.toJSONString(req)); Long featureId = featureResourceService.saveOrUpdateMenu(req); log.info("save feature resource resp : " + featureId.toString()); return ApiResult.ok(featureId); From a033919e17d32b902ff9ec7471ae73d43442ed46 Mon Sep 17 00:00:00 2001 From: lilong Date: Wed, 11 Sep 2024 15:12:28 +0800 Subject: [PATCH 20/27] =?UTF-8?q?feat:(hotfix/20240906)=20=E6=8A=8A?= =?UTF-8?q?=E8=8F=9C=E5=8D=95=E3=80=81=E8=A7=92=E8=89=B2=E8=8F=9C=E5=8D=95?= =?UTF-8?q?=E3=80=81=E4=BA=A7=E5=93=81=E8=8F=9C=E5=8D=95=E3=80=81=E8=A7=92?= =?UTF-8?q?=E8=89=B2=E6=9D=83=E9=99=90=E3=80=81=E8=A7=92=E8=89=B2=E8=8F=9C?= =?UTF-8?q?=E5=8D=95=E4=BB=8Eredis=E7=BC=93=E5=AD=98=E5=88=87=E6=8D=A2?= =?UTF-8?q?=E5=88=B0=E6=9C=AC=E5=9C=B0=E5=86=85=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/RocketMQEventConfiguration.java | 7 +- .../server/controller/PrivateController.java | 146 +++--- .../inner/CacheProductPermissionHandler.java | 284 +----------- ...acheProductSaasFeatureResourceHandler.java | 194 +------- .../inner/CacheRolePermissionHandler.java | 272 +---------- .../CacheRoleSaasFeatureResourceHandler.java | 174 +------ .../event/inner/CacheSaasFeatureHandler.java | 9 +- .../CacheSaasFeatureResourceHandler.java | 9 +- .../job/CacheProductFeatureResourceJob.java | 19 +- .../server/job/CacheProductPermissionJob.java | 20 +- .../job/CacheRoleFeatureResourceJob.java | 106 +---- .../server/job/CacheRolePermissionJob.java | 103 +--- .../tyr/server/job/CacheSaasFeatureJob.java | 74 +-- .../ProductPermissionCacheService.java | 19 +- ...roductSaasFeatureResourceCacheService.java | 10 +- .../service/RolePermissionCacheService.java | 21 +- .../RoleSaasFeatureResourceCacheService.java | 9 +- .../service/SaasFeatureResourceService.java | 12 +- .../ProductPermissionCacheServiceImpl.java | 438 +++++++++++------- ...ctSaasFeatureResourceCacheServiceImpl.java | 311 ++++++++----- .../impl/RolePermissionCacheServiceImpl.java | 425 +++++++++++------ ...leSaasFeatureResourceCacheServiceImpl.java | 298 +++++++----- .../impl/SaasFeatureResourceServiceImpl.java | 137 +++--- 23 files changed, 1260 insertions(+), 1837 deletions(-) diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/config/RocketMQEventConfiguration.java b/tyr-server/src/main/java/cn/axzo/tyr/server/config/RocketMQEventConfiguration.java index 86ff70f1..f418db02 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/config/RocketMQEventConfiguration.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/config/RocketMQEventConfiguration.java @@ -9,6 +9,7 @@ import cn.axzo.framework.rocketmq.RocketMQEventProducer; import lombok.extern.slf4j.Slf4j; import org.apache.rocketmq.common.message.MessageExt; import org.apache.rocketmq.spring.annotation.ConsumeMode; +import org.apache.rocketmq.spring.annotation.MessageModel; import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; import org.apache.rocketmq.spring.core.RocketMQListener; import org.apache.rocketmq.spring.core.RocketMQTemplate; @@ -67,7 +68,7 @@ public class RocketMQEventConfiguration { @Component @RocketMQMessageListener(topic = "topic_thrones_${spring.profiles.active}", consumerGroup = "GID_topic_thrones_${spring.application.name}_${spring.profiles.active}", - consumeMode = ConsumeMode.ORDERLY, + messageModel = MessageModel.BROADCASTING, nameServer = "${rocketmq.name-server}" ) public static class ThronesListener extends BaseListener implements RocketMQListener { @@ -85,7 +86,7 @@ public class RocketMQEventConfiguration { @Component @RocketMQMessageListener(topic = "topic_tyr_${spring.profiles.active}", consumerGroup = "GID_topic_tyr_${spring.application.name}_${spring.profiles.active}", - consumeMode = ConsumeMode.ORDERLY, + messageModel = MessageModel.BROADCASTING, nameServer = "${rocketmq.name-server}" ) public static class TyrListener extends BaseListener implements RocketMQListener { @@ -103,7 +104,7 @@ public class RocketMQEventConfiguration { @Component @RocketMQMessageListener(topic = "topic_apisix_plat_${spring.profiles.active}", consumerGroup = "GID_topic_apisix_plat_${spring.application.name}_${spring.profiles.active}", - consumeMode = ConsumeMode.ORDERLY, + messageModel = MessageModel.BROADCASTING, nameServer = "${rocketmq.name-server}" ) public static class ApiSixPlatListener extends BaseListener implements RocketMQListener { diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/PrivateController.java b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/PrivateController.java index fc1845b8..e0d94537 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/PrivateController.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/PrivateController.java @@ -180,6 +180,8 @@ public class PrivateController { private RoleSaasFeatureResourceCacheService roleSaasFeatureResourceCacheService; @Autowired private SendDingTalkHandler sendDingTalkHandler; + @Autowired + private ProductSaasFeatureResourceCacheService productSaasFeatureResourceCacheService; /** * 统一层级的roleGroup按照id升序,sort从1递增 @@ -363,22 +365,17 @@ public class PrivateController { }); } - @PostMapping("/api/private/productPermission/add") - public Object addProductPermission(@Validated @RequestBody ProductPermissionCacheService.StoreProductPermissionParam request) { - productPermissionCacheService.store(request); + @PostMapping("/api/private/productPermission/refresh") + public Object addProductPermission(@Validated @RequestBody ProductPermissionCacheService.RefreshProductPermissionCacheParam request) { + productPermissionCacheService.refreshCache(request); return "ok"; } - @PostMapping("/api/private/productPermission/get") + @PostMapping("/api/private/productPermission/list") public Object getProductPermission(@Validated @RequestBody ProductPermissionCacheService.ListProductPermissionParam request) { return productPermissionCacheService.list(request); } - @PostMapping("/api/private/productPermission/has") - public Object hasProductIds(@Validated @RequestBody ProductPermissionCacheService.HasProductPermissionParam request) { - return productPermissionCacheService.hasProductIds(request); - } - @PostMapping("/api/private/permission/auth") public Object authPermission(@Validated @RequestBody PermissionCheckReq request) { return tyrSaasAuthService.authPermission(request); @@ -634,6 +631,12 @@ public class PrivateController { return featureCodeUtil.resolveFeatureCode(request.getFeatureCodes()); } + /** + * 缓存产品权限 + * @param request + * @return + * @throws Exception + */ @PostMapping("/api/private/productPermission/store") public Object storeProductPermission(@RequestBody ProductSearchListReq request) throws Exception { cacheProductPermissionJob.execute(JSON.toJSONString(request)); @@ -666,104 +669,109 @@ public class PrivateController { return "ok"; } - @PostMapping("/api/private/role/insert") - public Object insertRole(@RequestPart("file") MultipartFile file) throws IOException { - - List importExcels = EasyExcel.read(file.getInputStream()) - .head(CreateRoleParam.class) - .sheet() - .doReadSync(); - - importExcels = importExcels.stream() - .filter(e -> Objects.equals(e.getType(), "c")) - .filter(e -> Objects.nonNull(e.getGroupId())) - .collect(Collectors.toList()); - - Set roleGroupIds = importExcels.stream() - .map(CreateRoleParam::getGroupId) - .collect(Collectors.toSet()); - - Map saasRoleGroups = saasRoleGroupDao.listByIds(roleGroupIds).stream() - .collect(Collectors.toMap(SaasRoleGroup::getId, Function.identity())); - - importExcels.forEach(e -> { - - SaasRoleGroup saasRoleGroup = saasRoleGroups.get(e.getGroupId()); - if (saasRoleGroup == null) { - log.info("not found saasRoleGroup,{}", e.getGroupId()); - return; - } - - SaveOrUpdateRoleVO.GroupInfoVO groupInfoVO = new SaveOrUpdateRoleVO.GroupInfoVO(); - groupInfoVO.setId(e.getGroupId()); - groupInfoVO.setWorkspaceTypeCode(saasRoleGroup.getWorkspaceTypeCode()); - SaveOrUpdateRoleVO saveOrUpdateRoleVO = SaveOrUpdateRoleVO.builder() - .name(e.getRoleName()) - .roleType("init") - .workspaceId(-1L) - .ownerOuId(-1L) - .operatorId(2007696L) - .operatorName("李龙") - .groupTree(Lists.newArrayList(groupInfoVO)) - .permissionGroupName("通用权限") - .permissionGroupType("feature") - .roleCode(e.getRoleCode()) - .isDisplay(true) - .enabled(true) - .build(); - try { - roleService.saveOrUpdate(saveOrUpdateRoleVO); - } catch (Exception ex) { - log.info("roleName {},ex:", e.getRoleName(), ex); - } - }); - return "ok"; - } - + /** + * 缓存角色权限 + * @param request + * @return + * @throws Exception + */ @PostMapping("/api/private/rolePermission/store") - public Object storeRolePermission(@RequestBody RoleService.PageSaasRoleParam request) throws Exception { + public Object storeRolePermission(@RequestBody RoleService.ListSaasRoleParam request) throws Exception { cacheRolePermissionJob.execute(JSON.toJSONString(request)); return "ok"; } + /** + * 缓存菜单 + * @param request + * @return + * @throws Exception + */ @PostMapping("/api/private/saasFeature/store") public Object storeSaasFeature(@RequestBody StoreFeatureParam request) throws Exception { cacheSaasFeatureJob.execute(JSON.toJSONString(request)); return "ok"; } + /** + * 缓存产品菜单 + * @param request + * @return + * @throws Exception + */ @PostMapping("/api/private/productSaasFeature/store") public Object storeProductSaasFeature(@RequestBody ProductSearchListReq request) throws Exception { cacheProductFeatureResourceJob.execute(JSON.toJSONString(request)); return "ok"; } + /** + * 缓存角色菜单 + * @param request + * @return + * @throws Exception + */ @PostMapping("/api/private/roleSaasFeature/store") public Object storeRoleSaasFeature(@RequestBody RoleService.PageSaasRoleParam request) throws Exception { cacheRoleFeatureResourceJob.execute(JSON.toJSONString(request)); return "ok"; } - @PostMapping("/api/private/saasFeature/list") - public Object listSaasFeature(@RequestBody SaasFeatureResourceService.ListSaasFeatureResourceCache request) throws Exception { - return saasFeatureResourceService.listCache(request); - } - @PostMapping("/api/private/workspaceProductCached/list") public Object workspaceProductCached(@RequestBody WorkspaceProductService.ListWorkspaceProductPermissionCacheParam request) { return workspaceProductService.listWorkspaceProductPermissionCached(request); } + /** + * 查询角色权限 + * @param request + * @return + */ @PostMapping("/api/private/rolePermissionCache/list") public Object rolePermissionCache(@RequestBody RolePermissionCacheService.ListRolePermissionParam request) { return rolePermissionCacheService.list(request); } + /** + * 查询产品权限 + * @param request + * @return + */ @PostMapping("/api/private/productPermissionCached/list") public Object productPermissionCached(@RequestBody ProductPermissionCacheService.ListProductPermissionParam request) { return productPermissionCacheService.list(request); } + /** + * 查询角色菜单 + * @param request + * @return + */ + @PostMapping("/api/private/roleSaasFeatureResourceCache/list") + public Object listRoleSaasFeatureResourceCache(@RequestBody RoleSaasFeatureResourceCacheService.ListRoleSaasFeatureResourceParam request) { + return roleSaasFeatureResourceCacheService.list(request); + } + + /** + * 查询产品菜单 + * @param request + * @return + */ + @PostMapping("/api/private/productFeatureResourceCached/list") + public Object listProductSaasFeatureResourceCache(@RequestBody ProductSaasFeatureResourceCacheService.ListProductFeatureResourceParam request) { + return productSaasFeatureResourceCacheService.list(request); + } + + /** + * 查询菜单树 + * @param request + * @return + */ + @PostMapping("/api/private/featureResourceCache/list") + public Object listSaasFeatureResourceCache(@RequestBody SaasFeatureResourceService.ListSaasFeatureResourceCache request) { + return saasFeatureResourceService.listCache(request); + } + @PostMapping("/api/private/saasPageElement/refreshCmpFeatureResourceLinkUrl") public ApiResult refreshCmpFeatureResourceLinkUrl(@RequestBody RefreshFeatureResourceLinkUrlParam request) { Long startId = 0L; diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheProductPermissionHandler.java b/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheProductPermissionHandler.java index a39257d2..3c5a48fa 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheProductPermissionHandler.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheProductPermissionHandler.java @@ -2,18 +2,12 @@ package cn.axzo.tyr.server.event.inner; import cn.axzo.framework.rocketmq.Event; import cn.axzo.framework.rocketmq.EventConsumer; -import cn.axzo.tyr.client.model.req.PageProductFeatureRelationReq; -import cn.axzo.tyr.client.model.req.PageSaasFeatureResourceReq; -import cn.axzo.tyr.client.model.res.SaasFeatureResourceResp; +import cn.axzo.tyr.client.model.product.ProductSearchListReq; +import cn.axzo.tyr.client.model.product.ProductVO; import cn.axzo.tyr.server.event.payload.PageElementFeatureResourceUpsertPayload; import cn.axzo.tyr.server.event.payload.ProductPermissionCreatedPayload; -import cn.axzo.tyr.server.repository.dao.SaasFeatureDao; -import cn.axzo.tyr.server.repository.entity.SaasFeature; -import cn.axzo.tyr.server.repository.entity.SaasProductModuleFeatureRelation; -import cn.axzo.tyr.server.service.ProductFeatureRelationService; import cn.axzo.tyr.server.service.ProductPermissionCacheService; -import cn.axzo.tyr.server.service.SaasFeatureResourceService; -import com.google.common.collect.Lists; +import cn.axzo.tyr.server.service.ProductService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.InitializingBean; @@ -21,18 +15,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Objects; import java.util.Set; -import java.util.function.Function; import java.util.stream.Collectors; -import static cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation.NEW_FEATURE; -import static cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation.OLD_FEATURE; - /** * 缓存产品的权限 */ @@ -45,29 +30,8 @@ public class CacheProductPermissionHandler implements InitializingBean { @Autowired private ProductPermissionCacheService productPermissionCacheService; @Autowired - private ProductFeatureRelationService productFeatureRelationService; - @Autowired - private SaasFeatureResourceService saasFeatureResourceService; - @Autowired - private SaasFeatureDao saasFeatureDao; + private ProductService productService; - private void storeProductPermission(List productFeatures) { - - if (CollectionUtils.isEmpty(productFeatures)) { - return; - } - - List productPermissions = resolveProductPermissions(productFeatures); - - if (CollectionUtils.isEmpty(productPermissions)) { - return; - } - - ProductPermissionCacheService.StoreProductPermissionParam storeProductPermissionParam = ProductPermissionCacheService.StoreProductPermissionParam.builder() - .productPermissions(productPermissions) - .build(); - productPermissionCacheService.store(storeProductPermissionParam); - } public void onProductPermissionUpsert(Event event, EventConsumer.Context context) { log.info("begin cached product permission handler rocketmq event: {}", event); @@ -76,16 +40,11 @@ public class CacheProductPermissionHandler implements InitializingBean { if (CollectionUtils.isEmpty(payload.getProductModuleIds())) { return; } - PageProductFeatureRelationReq pageProductFeatureRelationReq = PageProductFeatureRelationReq.builder() - .productModuleIds(payload.getProductModuleIds()) + + ProductPermissionCacheService.RefreshProductPermissionCacheParam param = ProductPermissionCacheService.RefreshProductPermissionCacheParam.builder() + .productIds(payload.getProductModuleIds()) .build(); - List productFeatures = productFeatureRelationService.list(pageProductFeatureRelationReq); - - if (CollectionUtils.isEmpty(productFeatures)) { - return; - } - - storeProductPermission(productFeatures); + productPermissionCacheService.refreshCache(param); log.info("end cached product permission handler rocketmq event: {}", event); } @@ -97,14 +56,17 @@ public class CacheProductPermissionHandler implements InitializingBean { return; } - PageProductFeatureRelationReq pageProductFeatureRelationReq = PageProductFeatureRelationReq.builder() - .build(); - List productFeatures = productFeatureRelationService.list(pageProductFeatureRelationReq); - - if (CollectionUtils.isEmpty(productFeatures)) { + Set productIds = productService.list(new ProductSearchListReq()).getData().stream() + .map(ProductVO::getId) + .collect(Collectors.toSet()); + if (CollectionUtils.isEmpty(productIds)) { return; } - storeProductPermission(productFeatures); + + ProductPermissionCacheService.RefreshProductPermissionCacheParam param = ProductPermissionCacheService.RefreshProductPermissionCacheParam.builder() + .productIds(productIds) + .build(); + productPermissionCacheService.refreshCache(param); log.info("end cached product permission handler rocketmq event: {}", event); } @@ -113,216 +75,4 @@ public class CacheProductPermissionHandler implements InitializingBean { eventConsumer.registerHandler(EventTypeEnum.PRODUCT_PERMISSION_CREATED.getEventCode(), this::onProductPermissionUpsert); eventConsumer.registerHandler(EventTypeEnum.PAGE_ELEMENT_FEATURE_RESOURCE_UPSERT.getEventCode(), this::onPageElementFeatureResourceUpsert); } - - public List resolveProductPermissions(List productPermissions) { - if (CollectionUtils.isEmpty(productPermissions)) { - return Collections.emptyList(); - } - - // 新的菜单树是是把有权限点的父节点也存进去了,所以直接解析 - Map featureResources = listSaasFeatureResource(productPermissions); - - Map parentFeatureResources = listParentSaasFeatureResource(featureResources); - - // 旧的菜单树只存储了权限点信息,没有把父节点存进去,需要解析父节点进行存储 - Map saasFeatures = listSaasFeature(productPermissions); - - Map parentSaasFeatures = listParentSaasFeature(saasFeatures); - - return productPermissions.stream() - .collect(Collectors.groupingBy(SaasProductModuleFeatureRelation::getProductModuleId)) - .entrySet() - .stream() - .map(e -> { - List productFeatureRelations = e.getValue(); - - if (CollectionUtils.isEmpty(productFeatureRelations)) { - return null; - } - - List permissions = productFeatureRelations.stream() - .map(relation -> { - if (Objects.equals(relation.getType(), NEW_FEATURE)) { - return resolveFeatureResourcePermission(relation, featureResources, parentFeatureResources); - } - - return resolveFeaturePermission(relation, saasFeatures, parentSaasFeatures); - }) - .filter(Objects::nonNull) - .flatMap(Collection::stream) - .distinct() - .collect(Collectors.toList()); - - if (CollectionUtils.isEmpty(permissions)) { - return null; - } - - return ProductPermissionCacheService.ProductPermission.builder() - .productId(e.getKey()) - .permissions(permissions) - .build(); - - }) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - } - - private List resolveFeaturePermission(SaasProductModuleFeatureRelation relation, Map saasFeatures, Map parentSaasFeatures) { - SaasFeature saasFeature = saasFeatures.get(relation.getFeatureId()); - if (Objects.isNull(saasFeature)) { - return null; - } - - List permissionDTOS = Lists.newArrayList(ProductPermissionCacheService.PermissionDTO.builder() - .featureId(saasFeature.getId()) - .featureCode(saasFeature.getFeatureCode()) - .featureType(saasFeature.getFeatureType()) - .terminal(saasFeature.getTerminal()) - .cooperateType(relation.getDictCode()) - .build()); - - List parentPermissions = saasFeature.splitPath().stream() - .map(parentSaasFeatures::get) - .filter(Objects::nonNull) - .map(f -> ProductPermissionCacheService.PermissionDTO.builder() - .featureId(f.getId()) - .featureCode(f.getFeatureCode()) - .featureType(f.getFeatureType()) - .terminal(f.getTerminal()) - .cooperateType(relation.getDictCode()) - .build()) - .collect(Collectors.toList()); - - permissionDTOS.addAll(parentPermissions); - return permissionDTOS; - } - - private List resolveFeatureResourcePermission(SaasProductModuleFeatureRelation relation, Map featureResources, Map parentFeatureResources) { - SaasFeatureResourceResp featureResource = featureResources.get(relation.getFeatureId()); - // 菜单节点是不会关联元素code,所以缓存的featureCode使用菜单编码 - if (Objects.isNull(featureResource)) { - return null; - } - - if (CollectionUtils.isEmpty(featureResource.getSaasPageElements())) { - return null; - } - - List permissionDTOS = featureResource.getSaasPageElements().stream() - .map(pageElement -> ProductPermissionCacheService.PermissionDTO.builder() - .featureId(featureResource.getId()) - .featureCode(pageElement.getCode()) - .featureType(featureResource.getFeatureType()) - .terminal(featureResource.getTerminal()) - .cooperateType(relation.getDictCode()) - .itemCode(pageElement.getItemCode()) - .version(pageElement.getVersion()) - .appType(pageElement.getAppType()) - .build()) - .collect(Collectors.toList()); - - List parentPermissions = featureResource.resolvePath().stream() - .map(parentFeatureResources::get) - .filter(Objects::nonNull) - .map(f -> { - if (CollectionUtils.isEmpty(f.getSaasPageElements())) { - return null; - } - - return f.getSaasPageElements().stream() - .map(pageElement -> ProductPermissionCacheService.PermissionDTO.builder() - .featureId(f.getId()) - .featureCode(pageElement.getCode()) - .featureType(f.getFeatureType()) - .terminal(f.getTerminal()) - .cooperateType(relation.getDictCode()) - .itemCode(pageElement.getItemCode()) - .version(pageElement.getVersion()) - .appType(pageElement.getAppType()) - .build()) - .collect(Collectors.toList()); - }) - .filter(Objects::nonNull) - .flatMap(Collection::stream) - .collect(Collectors.toList()); - - permissionDTOS.addAll(parentPermissions); - return permissionDTOS; - } - - - private Map listSaasFeatureResource(List productPermissions) { - - List featureIds = productPermissions.stream() - .filter(e -> Objects.equals(e.getType(), NEW_FEATURE)) - .map(SaasProductModuleFeatureRelation::getFeatureId) - .distinct() - .collect(Collectors.toList()); - - if (CollectionUtils.isEmpty(featureIds)) { - return Collections.emptyMap(); - } - - PageSaasFeatureResourceReq pageSaasFeatureResourceReq = PageSaasFeatureResourceReq.builder() - .ids(featureIds) - .needPageElement(true) - .build(); - return saasFeatureResourceService.list(pageSaasFeatureResourceReq).stream() - .collect(Collectors.toMap(SaasFeatureResourceResp::getId, Function.identity(), (f, s) -> s)); - } - - private Map listParentSaasFeatureResource(Map productPermissions) { - - List parentIds = productPermissions.values().stream() - .map(SaasFeatureResourceResp::resolvePath) - .flatMap(Collection::stream) - .distinct() - .collect(Collectors.toList()); - - if (CollectionUtils.isEmpty(parentIds)) { - return Collections.emptyMap(); - } - - PageSaasFeatureResourceReq pageSaasFeatureResourceReq = PageSaasFeatureResourceReq.builder() - .ids(parentIds) - .needPageElement(true) - .build(); - return saasFeatureResourceService.list(pageSaasFeatureResourceReq).stream() - .collect(Collectors.toMap(SaasFeatureResourceResp::getId, Function.identity(), (f, s) -> s)); - } - - private Map listSaasFeature(List productPermissions) { - - Set featureIds = productPermissions.stream() - .filter(e -> Objects.equals(e.getType(), OLD_FEATURE)) - .map(SaasProductModuleFeatureRelation::getFeatureId) - .collect(Collectors.toSet()); - - if (CollectionUtils.isEmpty(featureIds)) { - return Collections.emptyMap(); - } - - return saasFeatureDao.listByIds(featureIds).stream() - .collect(Collectors.toMap(SaasFeature::getId, Function.identity())); - } - - private Map listParentSaasFeature(Map saasFeatures) { - - if (CollectionUtils.isEmpty(saasFeatures)) { - return Collections.emptyMap(); - } - - List parentIds = saasFeatures.values().stream() - .map(SaasFeature::splitPath) - .flatMap(Collection::stream) - .distinct() - .collect(Collectors.toList()); - - if (CollectionUtils.isEmpty(parentIds)) { - return Collections.emptyMap(); - } - - return saasFeatureDao.listByIds(parentIds).stream() - .collect(Collectors.toMap(SaasFeature::getId, Function.identity())); - } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheProductSaasFeatureResourceHandler.java b/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheProductSaasFeatureResourceHandler.java index 113ca793..56c680e8 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheProductSaasFeatureResourceHandler.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheProductSaasFeatureResourceHandler.java @@ -2,20 +2,12 @@ package cn.axzo.tyr.server.event.inner; import cn.axzo.framework.rocketmq.Event; import cn.axzo.framework.rocketmq.EventConsumer; -import cn.axzo.tyr.client.common.enums.FeatureResourceType; -import cn.axzo.tyr.client.common.enums.PageElementFeatureResourceRelationTypeEnum; -import cn.axzo.tyr.client.model.req.PageProductFeatureRelationReq; -import cn.axzo.tyr.client.model.req.PageSaasFeatureResourceReq; -import cn.axzo.tyr.client.model.res.PageElementResp; -import cn.axzo.tyr.client.model.res.SaasFeatureResourceResp; +import cn.axzo.tyr.client.model.product.ProductSearchListReq; +import cn.axzo.tyr.client.model.product.ProductVO; import cn.axzo.tyr.server.event.payload.PageElementFeatureResourceUpsertPayload; import cn.axzo.tyr.server.event.payload.ProductPermissionCreatedPayload; -import cn.axzo.tyr.server.repository.entity.SaasProductModuleFeatureRelation; -import cn.axzo.tyr.server.service.ProductFeatureRelationService; import cn.axzo.tyr.server.service.ProductSaasFeatureResourceCacheService; -import cn.axzo.tyr.server.service.SaasFeatureResourceService; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; +import cn.axzo.tyr.server.service.ProductService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.InitializingBean; @@ -23,18 +15,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; import java.util.Set; -import java.util.function.Function; import java.util.stream.Collectors; -import static cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation.NEW_FEATURE; - @Slf4j @Component public class CacheProductSaasFeatureResourceHandler implements InitializingBean { @@ -42,36 +25,9 @@ public class CacheProductSaasFeatureResourceHandler implements InitializingBean @Autowired private EventConsumer eventConsumer; @Autowired - private ProductFeatureRelationService productFeatureRelationService; - @Autowired private ProductSaasFeatureResourceCacheService productSaasFeatureResourceCacheService; @Autowired - private SaasFeatureResourceService saasFeatureResourceService; - - public static final Set FEATURE_RESOURCE_TYPES = Sets.newHashSet(FeatureResourceType.MENU.getCode(), - FeatureResourceType.PAGE.getCode(), - FeatureResourceType.MENU_PARTITION_GROUP.getCode(), - FeatureResourceType.GROUP.getCode(), - FeatureResourceType.APP_ENTRY.getCode()); - - private void storeProductFeatureResource(List productFeatures) { - - if (CollectionUtils.isEmpty(productFeatures)) { - return; - } - - List productFeatureResources = resolveProductFeatureResources(productFeatures); - - if (CollectionUtils.isEmpty(productFeatureResources)) { - return; - } - - ProductSaasFeatureResourceCacheService.StoreProductFeatureResourceParam storeProductFeatureResourceParam = ProductSaasFeatureResourceCacheService.StoreProductFeatureResourceParam.builder() - .productFeatureResources(productFeatureResources) - .build(); - productSaasFeatureResourceCacheService.store(storeProductFeatureResourceParam); - - } + private ProductService productService; public void onProductPermissionUpsert(Event event, EventConsumer.Context context) { log.info("begin cached product featureResource handler rocketmq event: {}", event); @@ -81,13 +37,10 @@ public class CacheProductSaasFeatureResourceHandler implements InitializingBean return; } - PageProductFeatureRelationReq pageProductFeatureRelationReq = PageProductFeatureRelationReq.builder() - .productModuleIds(payload.getProductModuleIds()) - .type(NEW_FEATURE) + ProductSaasFeatureResourceCacheService.RefreshProductFeatureResourceCacheParam param = ProductSaasFeatureResourceCacheService.RefreshProductFeatureResourceCacheParam.builder() + .productIds(payload.getProductModuleIds()) .build(); - List productFeatures = productFeatureRelationService.list(pageProductFeatureRelationReq); - - storeProductFeatureResource(productFeatures); + productSaasFeatureResourceCacheService.refreshCache(param); log.info("end cached product featureResource handler rocketmq event: {}", event); } @@ -99,15 +52,17 @@ public class CacheProductSaasFeatureResourceHandler implements InitializingBean return; } - PageProductFeatureRelationReq pageProductFeatureRelationReq = PageProductFeatureRelationReq.builder() - .type(NEW_FEATURE) - .build(); - List productFeatures = productFeatureRelationService.list(pageProductFeatureRelationReq); - - if (CollectionUtils.isEmpty(productFeatures)) { + Set productIds = productService.list(new ProductSearchListReq()).getData().stream() + .map(ProductVO::getId) + .collect(Collectors.toSet()); + if (CollectionUtils.isEmpty(productIds)) { return; } - storeProductFeatureResource(productFeatures); + + ProductSaasFeatureResourceCacheService.RefreshProductFeatureResourceCacheParam param = ProductSaasFeatureResourceCacheService.RefreshProductFeatureResourceCacheParam.builder() + .productIds(productIds) + .build(); + productSaasFeatureResourceCacheService.refreshCache(param); log.info("end cached product featureResource handler rocketmq event: {}", event); } @@ -117,121 +72,4 @@ public class CacheProductSaasFeatureResourceHandler implements InitializingBean eventConsumer.registerHandler(EventTypeEnum.PAGE_ELEMENT_FEATURE_RESOURCE_UPSERT.getEventCode(), this::onPageElementFeatureResourceUpsert); } - - public List resolveProductFeatureResources(List productPermissions) { - if (CollectionUtils.isEmpty(productPermissions)) { - return Collections.emptyList(); - } - - Map featureResources = listSaasFeatureResource(productPermissions); - - Map parentFeatureResources = listParentSaasFeatureResource(featureResources); - - return productPermissions.stream() - .collect(Collectors.groupingBy(SaasProductModuleFeatureRelation::getProductModuleId)) - .entrySet() - .stream() - .map(e -> { - List productFeatureRelations = e.getValue(); - - if (CollectionUtils.isEmpty(productFeatureRelations)) { - return null; - } - - List productFeatureResources = productFeatureRelations.stream() - .map(relation -> { - SaasFeatureResourceResp featureResource = featureResources.get(relation.getFeatureId()); - if (Objects.isNull(featureResource) || StringUtils.isBlank(featureResource.getUniCode())) { - return null; - } - - ProductSaasFeatureResourceCacheService.FeatureResourceDTO featureResourceDTO = from(featureResource, relation); - List featureResourceDTOS = Lists.newArrayList(featureResourceDTO); - - List parentPermissions = featureResource.resolvePath().stream() - .map(parentFeatureResources::get) - .filter(Objects::nonNull) - .map(f -> { - - if (StringUtils.isBlank(f.getUniCode())) { - return null; - } - - return from(featureResource, relation); - }) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - featureResourceDTOS.addAll(parentPermissions); - - return featureResourceDTOS; - }) - .filter(Objects::nonNull) - .flatMap(Collection::stream) - .distinct() - .filter(f -> FEATURE_RESOURCE_TYPES.contains(f.getFeatureType())) - .collect(Collectors.toList()); - - if (CollectionUtils.isEmpty(productFeatureResources)) { - return null; - } - - return ProductSaasFeatureResourceCacheService.ProductFeatureResource.builder() - .productId(e.getKey()) - .featureResources(productFeatureResources) - .build(); - - }) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - } - - private ProductSaasFeatureResourceCacheService.FeatureResourceDTO from(SaasFeatureResourceResp featureResource, - SaasProductModuleFeatureRelation relation) { - return ProductSaasFeatureResourceCacheService.FeatureResourceDTO.builder() - .featureId(featureResource.getId()) - .featureType(featureResource.getFeatureType()) - .terminal(featureResource.getTerminal()) - .uniCode(featureResource.getUniCode()) - .cooperateType(relation.getDictCode()) - .build(); - } - - private Map listSaasFeatureResource(List productPermissions) { - - List featureIds = productPermissions.stream() - .map(SaasProductModuleFeatureRelation::getFeatureId) - .distinct() - .collect(Collectors.toList()); - - if (CollectionUtils.isEmpty(featureIds)) { - return Collections.emptyMap(); - } - - // 存在pre环境更改了节点的父节点,可能导致产品没有父节点的权限,这里补齐父节点的权限 - PageSaasFeatureResourceReq pageSaasFeatureResourceReq = PageSaasFeatureResourceReq.builder() - .ids(featureIds) - .build(); - return saasFeatureResourceService.list(pageSaasFeatureResourceReq).stream() - .collect(Collectors.toMap(SaasFeatureResourceResp::getId, Function.identity(), (f, s) -> s)); - } - - private Map listParentSaasFeatureResource(Map productPermissions) { - - List parentIds = productPermissions.values().stream() - .map(SaasFeatureResourceResp::resolvePath) - .flatMap(Collection::stream) - .distinct() - .collect(Collectors.toList()); - - if (CollectionUtils.isEmpty(parentIds)) { - return Collections.emptyMap(); - } - - // 存在pre环境更改了节点的父节点,可能导致产品没有父节点的权限,这里补齐父节点的权限 - PageSaasFeatureResourceReq pageSaasFeatureResourceReq = PageSaasFeatureResourceReq.builder() - .ids(parentIds) - .build(); - return saasFeatureResourceService.list(pageSaasFeatureResourceReq).stream() - .collect(Collectors.toMap(SaasFeatureResourceResp::getId, Function.identity(), (f, s) -> s)); - } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheRolePermissionHandler.java b/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheRolePermissionHandler.java index b902d524..b0a66cc4 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheRolePermissionHandler.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheRolePermissionHandler.java @@ -2,17 +2,11 @@ package cn.axzo.tyr.server.event.inner; import cn.axzo.framework.rocketmq.Event; import cn.axzo.framework.rocketmq.EventConsumer; -import cn.axzo.tyr.client.model.req.PageSaasFeatureResourceReq; -import cn.axzo.tyr.client.model.res.SaasFeatureResourceResp; -import cn.axzo.tyr.client.model.res.SaasPermissionRelationRes; import cn.axzo.tyr.client.model.res.SaasRoleRes; import cn.axzo.tyr.server.event.payload.PageElementFeatureResourceUpsertPayload; import cn.axzo.tyr.server.event.payload.RolePermissionCreatedPayload; -import cn.axzo.tyr.server.repository.dao.SaasFeatureDao; -import cn.axzo.tyr.server.repository.entity.SaasFeature; import cn.axzo.tyr.server.service.RolePermissionCacheService; import cn.axzo.tyr.server.service.RoleService; -import cn.axzo.tyr.server.service.SaasFeatureResourceService; import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -21,19 +15,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Objects; import java.util.Optional; import java.util.Set; -import java.util.function.Function; import java.util.stream.Collectors; -import static cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation.NEW_FEATURE; -import static cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation.OLD_FEATURE; - /** * 缓存角色的权限 */ @@ -47,28 +32,6 @@ public class CacheRolePermissionHandler implements InitializingBean { private RolePermissionCacheService rolePermissionCacheService; @Autowired private RoleService roleService; - @Autowired - private SaasFeatureResourceService saasFeatureResourceService; - @Autowired - private SaasFeatureDao saasFeatureDao; - - private void storeRolePermission(List roles) { - - if (CollectionUtils.isEmpty(roles)) { - return; - } - - List rolePermissions = resolveRolePermission(roles); - - if (CollectionUtils.isEmpty(rolePermissions)) { - return; - } - - RolePermissionCacheService.StoreRolePermissionParam storeRolePermissionParam = RolePermissionCacheService.StoreRolePermissionParam.builder() - .rolePermissions(rolePermissions) - .build(); - rolePermissionCacheService.store(storeRolePermissionParam); - } public void onRolePermissionUpsert(Event event, EventConsumer.Context context) { log.info("begin cached role permission handler rocketmq event: {}", event); @@ -84,11 +47,19 @@ public class CacheRolePermissionHandler implements InitializingBean { .roleIds(Optional.ofNullable(payload.getRoleIds()) .map(Lists::newArrayList) .orElse(null)) - .needPermissionRelation(true) .build(); - List roles = roleService.list(listSaasRoleParam); + Set roleIds = roleService.list(listSaasRoleParam).stream() + .map(SaasRoleRes::getId) + .collect(Collectors.toSet()); + if (CollectionUtils.isEmpty(roleIds)) { + return; + } + + RolePermissionCacheService.RefreshRolePermissionCacheParam refreshRolePermissionCacheParam = RolePermissionCacheService.RefreshRolePermissionCacheParam.builder() + .roleIds(roleIds) + .build(); + rolePermissionCacheService.refreshCache(refreshRolePermissionCacheParam); - storeRolePermission(roles); log.info("end cached role permission handler rocketmq event: {}", event); } @@ -99,12 +70,18 @@ public class CacheRolePermissionHandler implements InitializingBean { return; } - RoleService.ListSaasRoleParam listSaasRoleParam = RoleService.ListSaasRoleParam.builder() - .needPermissionRelation(true) - .build(); - List roles = roleService.list(listSaasRoleParam); + RoleService.ListSaasRoleParam listSaasRoleParam = RoleService.ListSaasRoleParam.builder().build(); + Set roleIds = roleService.list(listSaasRoleParam).stream() + .map(SaasRoleRes::getId) + .collect(Collectors.toSet()); + if (CollectionUtils.isEmpty(roleIds)) { + return; + } - storeRolePermission(roles); + RolePermissionCacheService.RefreshRolePermissionCacheParam refreshRolePermissionCacheParam = RolePermissionCacheService.RefreshRolePermissionCacheParam.builder() + .roleIds(roleIds) + .build(); + rolePermissionCacheService.refreshCache(refreshRolePermissionCacheParam); } @Override @@ -112,209 +89,4 @@ public class CacheRolePermissionHandler implements InitializingBean { eventConsumer.registerHandler(EventTypeEnum.ROLE_PERMISSION_CREATED.getEventCode(), this::onRolePermissionUpsert); eventConsumer.registerHandler(EventTypeEnum.PAGE_ELEMENT_FEATURE_RESOURCE_UPSERT.getEventCode(), this::onPageElementFeatureResourceUpsert); } - - public List resolveRolePermission(List roles) { - - - Map featureResources = listSaasFeatureResource(roles); - - Map parentFeatureResources = listParentSaasFeatureResource(featureResources); - - Map saasFeatures = listSaasFeature(roles); - - Map parentSaasFeatures = listParentSaasFeature(saasFeatures); - - - return roles.stream() - .map(e -> { - if (CollectionUtils.isEmpty(e.getPermissionRelations())) { - return null; - } - - List permissions = e.getPermissionRelations().stream() - .distinct() - .map(permissionRelation -> { - if (Objects.equals(permissionRelation.getType(), NEW_FEATURE)) { - return resolveFeatureResourcePermission(permissionRelation, featureResources, parentFeatureResources); - } - return resolveFeaturePermission(permissionRelation, saasFeatures, parentSaasFeatures); - }) - .filter(Objects::nonNull) - .flatMap(Collection::stream) - .distinct() - .collect(Collectors.toList()); - - if (CollectionUtils.isEmpty(permissions)) { - return null; - } - - return RolePermissionCacheService.RolePermission.builder() - .roleId(e.getId()) - .permissions(permissions) - .build(); - - }) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - } - - private static List resolveFeaturePermission(SaasPermissionRelationRes permissionRelation, Map saasFeatures, Map parentSaasFeatures) { - SaasFeature saasFeature = saasFeatures.get(permissionRelation.getFeatureId()); - if (Objects.isNull(saasFeature)) { - return null; - } - - List permissionDTOS = Lists.newArrayList(RolePermissionCacheService.PermissionDTO.builder() - .featureId(saasFeature.getId()) - .featureCode(saasFeature.getFeatureCode()) - .featureType(saasFeature.getFeatureType()) - .terminal(saasFeature.getTerminal()) - .build()); - - List parentPermissions = saasFeature.splitPath().stream() - .map(parentSaasFeatures::get) - .filter(Objects::nonNull) - .map(f -> RolePermissionCacheService.PermissionDTO.builder() - .featureId(f.getId()) - .featureCode(f.getFeatureCode()) - .featureType(f.getFeatureType()) - .terminal(f.getTerminal()) - .build()) - .collect(Collectors.toList()); - - permissionDTOS.addAll(parentPermissions); - return permissionDTOS; - } - - private static List resolveFeatureResourcePermission(SaasPermissionRelationRes permissionRelation, Map featureResources, Map parentFeatureResources) { - SaasFeatureResourceResp featureResource = featureResources.get(permissionRelation.getFeatureId()); - // 菜单节点是不会关联元素code,所以缓存的featureCode使用菜单编码 - if (Objects.isNull(featureResource)) { - return null; - } - - if (CollectionUtils.isEmpty(featureResource.getSaasPageElements())) { - return null; - } - - List permissionDTOS = featureResource.getSaasPageElements().stream() - .map(pageElement -> RolePermissionCacheService.PermissionDTO.builder() - .featureId(featureResource.getId()) - .featureCode(pageElement.getCode()) - .featureType(featureResource.getFeatureType()) - .terminal(featureResource.getTerminal()) - .build()) - .collect(Collectors.toList()); - - List parentPermissions = featureResource.resolvePath().stream() - .map(parentFeatureResources::get) - .filter(Objects::nonNull) - .map(f -> { - - if (CollectionUtils.isEmpty(featureResource.getSaasPageElements())) { - return null; - } - - return featureResource.getSaasPageElements().stream() - .map(pageElement -> RolePermissionCacheService.PermissionDTO.builder() - .featureId(f.getId()) - .featureCode(pageElement.getCode()) - .featureType(f.getFeatureType()) - .terminal(f.getTerminal()) - .build()) - .collect(Collectors.toList()); - }) - .filter(Objects::nonNull) - .flatMap(Collection::stream) - .collect(Collectors.toList()); - - permissionDTOS.addAll(parentPermissions); - - return permissionDTOS; - } - - - private Map listSaasFeatureResource(List roles) { - - List featureIds = roles.stream() - .filter(e -> !CollectionUtils.isEmpty(e.getPermissionRelations())) - .map(SaasRoleRes::getPermissionRelations) - .flatMap(Collection::stream) - .filter(e -> Objects.equals(e.getType(), NEW_FEATURE)) - .map(SaasPermissionRelationRes::getFeatureId) - .distinct() - .collect(Collectors.toList()); - - if (CollectionUtils.isEmpty(featureIds)) { - return Collections.emptyMap(); - } - - - PageSaasFeatureResourceReq pageSaasFeatureResourceReq = PageSaasFeatureResourceReq.builder() - .ids(featureIds) - .needPageElement(true) - .build(); - return saasFeatureResourceService.list(pageSaasFeatureResourceReq).stream() - .collect(Collectors.toMap(SaasFeatureResourceResp::getId, Function.identity(), (f, s) -> s)); - } - - private Map listParentSaasFeatureResource(Map productPermissions) { - - List parentIds = productPermissions.values().stream() - .map(SaasFeatureResourceResp::resolvePath) - .flatMap(Collection::stream) - .distinct() - .collect(Collectors.toList()); - - if (CollectionUtils.isEmpty(parentIds)) { - return Collections.emptyMap(); - } - - // 存在pre环境更改了节点的父节点,可能导致产品没有父节点的权限,这里补齐父节点的权限 - PageSaasFeatureResourceReq pageSaasFeatureResourceReq = PageSaasFeatureResourceReq.builder() - .ids(parentIds) - .needPageElement(true) - .build(); - return saasFeatureResourceService.list(pageSaasFeatureResourceReq).stream() - .collect(Collectors.toMap(SaasFeatureResourceResp::getId, Function.identity(), (f, s) -> s)); - } - - private Map listSaasFeature(List roles) { - - Set featureIds = roles.stream() - .filter(e -> !CollectionUtils.isEmpty(e.getPermissionRelations())) - .map(SaasRoleRes::getPermissionRelations) - .flatMap(Collection::stream) - .filter(e -> Objects.equals(e.getType(), OLD_FEATURE)) - .map(SaasPermissionRelationRes::getFeatureId) - .collect(Collectors.toSet()); - - if (CollectionUtils.isEmpty(featureIds)) { - return Collections.emptyMap(); - } - - return saasFeatureDao.listByIds(featureIds) - .stream() - .collect(Collectors.toMap(SaasFeature::getId, Function.identity(), (f, s) -> s)); - } - - private Map listParentSaasFeature(Map saasFeatures) { - - if (CollectionUtils.isEmpty(saasFeatures)) { - return Collections.emptyMap(); - } - - List parentIds = saasFeatures.values().stream() - .map(SaasFeature::splitPath) - .flatMap(Collection::stream) - .distinct() - .collect(Collectors.toList()); - - if (CollectionUtils.isEmpty(parentIds)) { - return Collections.emptyMap(); - } - - return saasFeatureDao.listByIds(parentIds).stream() - .collect(Collectors.toMap(SaasFeature::getId, Function.identity())); - } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheRoleSaasFeatureResourceHandler.java b/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheRoleSaasFeatureResourceHandler.java index 1c9875ea..93be689b 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheRoleSaasFeatureResourceHandler.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheRoleSaasFeatureResourceHandler.java @@ -2,15 +2,11 @@ package cn.axzo.tyr.server.event.inner; import cn.axzo.framework.rocketmq.Event; import cn.axzo.framework.rocketmq.EventConsumer; -import cn.axzo.tyr.client.model.req.PageSaasFeatureResourceReq; -import cn.axzo.tyr.client.model.res.SaasFeatureResourceResp; -import cn.axzo.tyr.client.model.res.SaasPermissionRelationRes; import cn.axzo.tyr.client.model.res.SaasRoleRes; import cn.axzo.tyr.server.event.payload.PageElementFeatureResourceUpsertPayload; import cn.axzo.tyr.server.event.payload.RolePermissionCreatedPayload; import cn.axzo.tyr.server.service.RoleSaasFeatureResourceCacheService; import cn.axzo.tyr.server.service.RoleService; -import cn.axzo.tyr.server.service.SaasFeatureResourceService; import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -19,18 +15,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Objects; import java.util.Optional; -import java.util.function.Function; +import java.util.Set; import java.util.stream.Collectors; -import static cn.axzo.tyr.server.event.inner.CacheProductSaasFeatureResourceHandler.FEATURE_RESOURCE_TYPES; -import static cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation.NEW_FEATURE; - /** * 因为菜单树不一定有权限code * 登录时需要查询菜单树,所以把菜单树缓存起来 @@ -44,27 +32,8 @@ public class CacheRoleSaasFeatureResourceHandler implements InitializingBean { @Autowired private RoleService roleService; @Autowired - private SaasFeatureResourceService saasFeatureResourceService; - @Autowired private RoleSaasFeatureResourceCacheService roleSaasFeatureResourceCacheService; - private void storeRoleFeatureResource(List roles) { - - if (CollectionUtils.isEmpty(roles)) { - return; - } - - List rolePermissions = resolveRoleFeatureResource(roles); - - if (CollectionUtils.isEmpty(rolePermissions)) { - return; - } - - RoleSaasFeatureResourceCacheService.StoreRoleSaasFeatureResourceParam storeRoleFeatureResourceParam = RoleSaasFeatureResourceCacheService.StoreRoleSaasFeatureResourceParam.builder() - .roleSaasFeatureResources(rolePermissions) - .build(); - roleSaasFeatureResourceCacheService.store(storeRoleFeatureResourceParam); - } public void onRolePermissionUpsert(Event event, EventConsumer.Context context) { log.info("begin cached role saasFeatureResource handler rocketmq event: {}", event); RolePermissionCreatedPayload payload = event.normalizedData(RolePermissionCreatedPayload.class); @@ -79,12 +48,18 @@ public class CacheRoleSaasFeatureResourceHandler implements InitializingBean { .roleIds(Optional.ofNullable(payload.getRoleIds()) .map(Lists::newArrayList) .orElse(null)) - .needPermissionRelation(true) - .type(NEW_FEATURE) .build(); - List roles = roleService.list(listSaasRoleParam); + Set roleIds = roleService.list(listSaasRoleParam).stream() + .map(SaasRoleRes::getId) + .collect(Collectors.toSet()); + if (CollectionUtils.isEmpty(roleIds)) { + return; + } - storeRoleFeatureResource(roles); + RoleSaasFeatureResourceCacheService.RefreshRoleFeatureResourceCacheParam param = RoleSaasFeatureResourceCacheService.RefreshRoleFeatureResourceCacheParam.builder() + .roleIds(roleIds) + .build(); + roleSaasFeatureResourceCacheService.refreshCache(param); log.info("end cached role saasFeatureResource handler rocketmq event: {}", event); } @@ -97,12 +72,19 @@ public class CacheRoleSaasFeatureResourceHandler implements InitializingBean { } RoleService.ListSaasRoleParam listSaasRoleParam = RoleService.ListSaasRoleParam.builder() - .needPermissionRelation(true) - .type(NEW_FEATURE) .build(); - List roles = roleService.list(listSaasRoleParam); - storeRoleFeatureResource(roles); + Set roleIds = roleService.list(listSaasRoleParam).stream() + .map(SaasRoleRes::getId) + .collect(Collectors.toSet()); + if (CollectionUtils.isEmpty(roleIds)) { + return; + } + + RoleSaasFeatureResourceCacheService.RefreshRoleFeatureResourceCacheParam param = RoleSaasFeatureResourceCacheService.RefreshRoleFeatureResourceCacheParam.builder() + .roleIds(roleIds) + .build(); + roleSaasFeatureResourceCacheService.refreshCache(param); } @Override @@ -111,116 +93,4 @@ public class CacheRoleSaasFeatureResourceHandler implements InitializingBean { eventConsumer.registerHandler(EventTypeEnum.PAGE_ELEMENT_FEATURE_RESOURCE_UPSERT.getEventCode(), this::onPageElementFeatureResourceUpsert); } - - public List resolveRoleFeatureResource(List roles) { - - Map featureResources = listSaasFeatureResource(roles); - - Map parentFeatureResources = listParentSaasFeatureResource(featureResources); - - return roles.stream() - .map(e -> { - if (CollectionUtils.isEmpty(e.getPermissionRelations())) { - return null; - } - - List permissions = e.getPermissionRelations().stream() - .distinct() - .map(permissionRelation -> { - SaasFeatureResourceResp featureResource = featureResources.get(permissionRelation.getFeatureId()); - if (Objects.isNull(featureResource) || StringUtils.isBlank(featureResource.getUniCode())) { - return null; - } - - List featureResourceDTOS = Lists.newArrayList(RoleSaasFeatureResourceCacheService.SaasFeatureResourceDTO.builder() - .featureId(featureResource.getId()) - .featureType(featureResource.getFeatureType()) - .terminal(featureResource.getTerminal()) - .uniCode(featureResource.getUniCode()) - .build()); - List parentPermissions = featureResource.resolvePath().stream() - .map(parentFeatureResources::get) - .filter(Objects::nonNull) - .map(f -> { - - if (StringUtils.isBlank(f.getUniCode())) { - return null; - } - - return RoleSaasFeatureResourceCacheService.SaasFeatureResourceDTO.builder() - .featureId(f.getId()) - .featureType(f.getFeatureType()) - .terminal(f.getTerminal()) - .uniCode(f.getUniCode()) - .build(); - }) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - featureResourceDTOS.addAll(parentPermissions); - - return featureResourceDTOS; - }) - .filter(Objects::nonNull) - .flatMap(Collection::stream) - .distinct() - .filter(f -> FEATURE_RESOURCE_TYPES.contains(f.getFeatureType())) - .collect(Collectors.toList()); - - if (CollectionUtils.isEmpty(permissions)) { - return null; - } - - return RoleSaasFeatureResourceCacheService.RoleFeatureResource.builder() - .roleId(e.getId()) - .saasFeatureResources(permissions) - .build(); - - }) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - } - - private Map listSaasFeatureResource(List roles) { - - List featureIds = roles.stream() - .filter(e -> !CollectionUtils.isEmpty(e.getPermissionRelations())) - .map(SaasRoleRes::getPermissionRelations) - .flatMap(Collection::stream) - .map(SaasPermissionRelationRes::getFeatureId) - .distinct() - .collect(Collectors.toList()); - - if (CollectionUtils.isEmpty(featureIds)) { - return Collections.emptyMap(); - } - - // 存在pre环境更改了节点的父节点,可能导致产品没有父节点的权限,这里补齐父节点的权限 - PageSaasFeatureResourceReq pageSaasFeatureResourceReq = PageSaasFeatureResourceReq.builder() - .ids(featureIds) - .needFeatureCodes(true) - .build(); - return saasFeatureResourceService.list(pageSaasFeatureResourceReq).stream() - .collect(Collectors.toMap(SaasFeatureResourceResp::getId, Function.identity(), (f, s) -> s)); - } - - private Map listParentSaasFeatureResource(Map productPermissions) { - - List parentIds = productPermissions.values().stream() - .map(SaasFeatureResourceResp::resolvePath) - .flatMap(Collection::stream) - .distinct() - .collect(Collectors.toList()); - - if (CollectionUtils.isEmpty(parentIds)) { - return Collections.emptyMap(); - } - - // 存在pre环境更改了节点的父节点,可能导致产品没有父节点的权限,这里补齐父节点的权限 - PageSaasFeatureResourceReq pageSaasFeatureResourceReq = PageSaasFeatureResourceReq.builder() - .ids(parentIds) - .needFeatureCodes(true) - .build(); - return saasFeatureResourceService.list(pageSaasFeatureResourceReq).stream() - .collect(Collectors.toMap(SaasFeatureResourceResp::getId, Function.identity(), (f, s) -> s)); - } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheSaasFeatureHandler.java b/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheSaasFeatureHandler.java index b5651162..268cb780 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheSaasFeatureHandler.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheSaasFeatureHandler.java @@ -4,7 +4,7 @@ import cn.axzo.framework.rocketmq.Event; import cn.axzo.framework.rocketmq.EventConsumer; import cn.axzo.framework.rocketmq.EventHandler; import cn.axzo.tyr.server.event.payload.SaasFeatureUpsertPayload; -import cn.axzo.tyr.server.job.CacheSaasFeatureJob; +import cn.axzo.tyr.server.service.SaasFeatureResourceService; import com.google.common.collect.Sets; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -22,7 +22,7 @@ public class CacheSaasFeatureHandler implements EventHandler, InitializingBean { @Autowired private EventConsumer eventConsumer; @Autowired - private CacheSaasFeatureJob cacheSaasFeatureJob; + private SaasFeatureResourceService saasFeatureResourceService; @Override public void onEvent(Event event, EventConsumer.Context context) { @@ -33,7 +33,10 @@ public class CacheSaasFeatureHandler implements EventHandler, InitializingBean { return; } - cacheSaasFeatureJob.cacheSaasFeature(Sets.newHashSet(payload.getTerminal())); + SaasFeatureResourceService.RefreshFeatureResourceCacheParam param = SaasFeatureResourceService.RefreshFeatureResourceCacheParam.builder() + .terminals(Sets.newHashSet(payload.getTerminal())) + .build(); + saasFeatureResourceService.refreshCache(param); log.info("end cached saasFeature handler rocketmq event: {}", event); } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheSaasFeatureResourceHandler.java b/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheSaasFeatureResourceHandler.java index 9695a0e0..ea56c5cc 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheSaasFeatureResourceHandler.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheSaasFeatureResourceHandler.java @@ -4,7 +4,7 @@ import cn.axzo.framework.rocketmq.Event; import cn.axzo.framework.rocketmq.EventConsumer; import cn.axzo.framework.rocketmq.EventHandler; import cn.axzo.tyr.server.event.payload.SaasFeatureResourceUpsertPayload; -import cn.axzo.tyr.server.job.CacheSaasFeatureJob; +import cn.axzo.tyr.server.service.SaasFeatureResourceService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.springframework.beans.factory.InitializingBean; @@ -21,7 +21,7 @@ public class CacheSaasFeatureResourceHandler implements EventHandler, Initializi @Autowired private EventConsumer eventConsumer; @Autowired - private CacheSaasFeatureJob cacheSaasFeatureJob; + private SaasFeatureResourceService saasFeatureResourceService; @Override public void onEvent(Event event, EventConsumer.Context context) { @@ -32,7 +32,10 @@ public class CacheSaasFeatureResourceHandler implements EventHandler, Initializi return; } - cacheSaasFeatureJob.cacheSaasFeatureResource(payload.getTerminals()); + SaasFeatureResourceService.RefreshFeatureResourceCacheParam param = SaasFeatureResourceService.RefreshFeatureResourceCacheParam.builder() + .terminals(payload.getTerminals()) + .build(); + saasFeatureResourceService.refreshCache(param); log.info("end cached saasFeatureResource handler rocketmq event: {}", event); } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheProductFeatureResourceJob.java b/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheProductFeatureResourceJob.java index 2a4c602e..0bbc2b63 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheProductFeatureResourceJob.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheProductFeatureResourceJob.java @@ -1,10 +1,8 @@ package cn.axzo.tyr.server.job; -import cn.axzo.framework.rocketmq.Event; import cn.axzo.tyr.client.model.product.ProductSearchListReq; import cn.axzo.tyr.client.model.product.ProductVO; -import cn.axzo.tyr.server.event.inner.CacheProductSaasFeatureResourceHandler; -import cn.axzo.tyr.server.event.payload.ProductPermissionCreatedPayload; +import cn.axzo.tyr.server.service.ProductSaasFeatureResourceCacheService; import cn.axzo.tyr.server.service.ProductService; import com.alibaba.fastjson.JSONObject; import com.xxl.job.core.biz.model.ReturnT; @@ -13,6 +11,7 @@ import com.xxl.job.core.handler.annotation.XxlJob; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; import java.util.Optional; import java.util.Set; @@ -23,7 +22,7 @@ import java.util.stream.Collectors; public class CacheProductFeatureResourceJob extends IJobHandler { @Autowired - private CacheProductSaasFeatureResourceHandler cacheProductSaasFeatureResourceHandler; + private ProductSaasFeatureResourceCacheService productSaasFeatureResourceCacheService; @Autowired private ProductService productService; @@ -41,14 +40,14 @@ public class CacheProductFeatureResourceJob extends IJobHandler { .map(ProductVO::getId) .collect(Collectors.toSet()); - ProductPermissionCreatedPayload payload = ProductPermissionCreatedPayload.builder() - .productModuleIds(productIds) - .build(); + if (CollectionUtils.isEmpty(productIds)) { + return ReturnT.SUCCESS; + } - Event event = Event.builder() - .data(payload) + ProductSaasFeatureResourceCacheService.RefreshProductFeatureResourceCacheParam param = ProductSaasFeatureResourceCacheService.RefreshProductFeatureResourceCacheParam.builder() + .productIds(productIds) .build(); - cacheProductSaasFeatureResourceHandler.onProductPermissionUpsert(event, null); + productSaasFeatureResourceCacheService.refreshCache(param); return ReturnT.SUCCESS; } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheProductPermissionJob.java b/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheProductPermissionJob.java index b05d63a3..e7913351 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheProductPermissionJob.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheProductPermissionJob.java @@ -1,10 +1,8 @@ package cn.axzo.tyr.server.job; -import cn.axzo.framework.rocketmq.Event; import cn.axzo.tyr.client.model.product.ProductSearchListReq; import cn.axzo.tyr.client.model.product.ProductVO; -import cn.axzo.tyr.server.event.inner.CacheProductPermissionHandler; -import cn.axzo.tyr.server.event.payload.ProductPermissionCreatedPayload; +import cn.axzo.tyr.server.service.ProductPermissionCacheService; import cn.axzo.tyr.server.service.ProductService; import com.alibaba.fastjson.JSONObject; import com.xxl.job.core.biz.model.ReturnT; @@ -13,6 +11,7 @@ import com.xxl.job.core.handler.annotation.XxlJob; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; import java.util.Optional; import java.util.Set; @@ -23,7 +22,7 @@ import java.util.stream.Collectors; public class CacheProductPermissionJob extends IJobHandler { @Autowired - private CacheProductPermissionHandler cacheProductPermissionHandler; + private ProductPermissionCacheService productPermissionCacheService; @Autowired private ProductService productService; @@ -40,15 +39,14 @@ public class CacheProductPermissionJob extends IJobHandler { .stream() .map(ProductVO::getId) .collect(Collectors.toSet()); + if (CollectionUtils.isEmpty(productIds)) { + return ReturnT.SUCCESS; + } - ProductPermissionCreatedPayload payload = ProductPermissionCreatedPayload.builder() - .productModuleIds(productIds) + ProductPermissionCacheService.RefreshProductPermissionCacheParam param = ProductPermissionCacheService.RefreshProductPermissionCacheParam.builder() + .productIds(productIds) .build(); - - Event event = Event.builder() - .data(payload) - .build(); - cacheProductPermissionHandler.onProductPermissionUpsert(event, null); + productPermissionCacheService.refreshCache(param); return ReturnT.SUCCESS; } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheRoleFeatureResourceJob.java b/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheRoleFeatureResourceJob.java index d1eb092c..725bec72 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheRoleFeatureResourceJob.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheRoleFeatureResourceJob.java @@ -1,15 +1,8 @@ package cn.axzo.tyr.server.job; -import cn.axzo.foundation.page.PageResp; -import cn.axzo.tyr.client.model.res.SaasPermissionRelationRes; import cn.axzo.tyr.client.model.res.SaasRoleRes; -import cn.axzo.tyr.server.event.inner.CacheRoleSaasFeatureResourceHandler; -import cn.axzo.tyr.server.repository.dao.SaasPgroupRoleRelationDao; -import cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation; -import cn.axzo.tyr.server.repository.entity.SaasPgroupRoleRelation; import cn.axzo.tyr.server.service.RoleSaasFeatureResourceCacheService; import cn.axzo.tyr.server.service.RoleService; -import cn.axzo.tyr.server.service.SaasPgroupPermissionRelationService; import com.alibaba.fastjson.JSONObject; import com.xxl.job.core.biz.model.ReturnT; import com.xxl.job.core.handler.IJobHandler; @@ -19,9 +12,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; -import java.util.Collection; -import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -30,102 +20,32 @@ import java.util.stream.Collectors; @Component public class CacheRoleFeatureResourceJob extends IJobHandler { - @Autowired - private CacheRoleSaasFeatureResourceHandler cacheRoleSaasFeatureResourceHandler; @Autowired private RoleService roleService; @Autowired - private SaasPgroupPermissionRelationService saasPgroupPermissionRelationService; - @Autowired - private SaasPgroupRoleRelationDao saasPgroupRoleRelationDao; - @Autowired private RoleSaasFeatureResourceCacheService roleSaasFeatureResourceCacheService; - private static final Integer DEFAULT_PAGE_SIZE = 2000; - @Override @XxlJob("CacheRoleFeatureResourceJob") public ReturnT execute(String s) throws Exception { log.info("start CacheRoleFeatureResourceJob, s:{}", s); - RoleService.PageSaasRoleParam pageSaasRoleParam = Optional.ofNullable(s) - .map(e -> JSONObject.parseObject(e, RoleService.PageSaasRoleParam.class)) - .orElseGet(() -> RoleService.PageSaasRoleParam.builder().build()); + RoleService.ListSaasRoleParam listSaasRoleParam = Optional.ofNullable(s) + .map(e -> JSONObject.parseObject(e, RoleService.ListSaasRoleParam.class)) + .orElseGet(() -> RoleService.ListSaasRoleParam.builder().build()); - // 因为角色权限集是重复使用,通过角色找权限集数据量太大,直接查询所有权限集的权限,比较快 - Map> permissionRelations = listPgroupPermissionRelation(); - - Integer pageNumber = 1; - while (true) { - pageSaasRoleParam.setPage(pageNumber++); - pageSaasRoleParam.setPageSize(DEFAULT_PAGE_SIZE); - PageResp page = roleService.page(pageSaasRoleParam); - - store(page.getData(), permissionRelations); - - if (!page.hasNext()) { - break; - } + Set roleIds = roleService.list(listSaasRoleParam).stream() + .map(SaasRoleRes::getId) + .collect(Collectors.toSet()); + if (CollectionUtils.isEmpty(roleIds)) { + return ReturnT.SUCCESS; } + RoleSaasFeatureResourceCacheService.RefreshRoleFeatureResourceCacheParam param = RoleSaasFeatureResourceCacheService.RefreshRoleFeatureResourceCacheParam.builder() + .roleIds(roleIds) + .build(); + roleSaasFeatureResourceCacheService.refreshCache(param); + return ReturnT.SUCCESS; } - - private Map> listPgroupPermissionRelation() { - return saasPgroupPermissionRelationService.list().stream() - .collect(Collectors.groupingBy(SaasPgroupPermissionRelation::getGroupId, - Collectors.mapping(e -> SaasPermissionRelationRes.builder() - .featureId(e.getFeatureId()) - .featureType(e.getFeatureType()) - .type(e.getType()) - .build(), Collectors.toList()))); - - } - - private Map> listPermissionGroup(List roleIds) { - - return saasPgroupRoleRelationDao.findByRoleIds(roleIds).stream() - .collect(Collectors.groupingBy(SaasPgroupRoleRelation::getRoleId, - Collectors.mapping(SaasPgroupRoleRelation::getGroupId, Collectors.toSet()))); - } - - private void store(List roles, - Map> permissionRelations) { - - if (CollectionUtils.isEmpty(roles)) { - return; - } - - List roleIds = roles.stream() - .map(SaasRoleRes::getId) - .collect(Collectors.toList()); - Map> roleGroupMap = listPermissionGroup(roleIds); - - roles.forEach(e -> { - Set groupIds = roleGroupMap.get(e.getId()); - if (CollectionUtils.isEmpty(groupIds)) { - return; - } - - List rolePermissions = groupIds.stream() - .map(permissionRelations::get) - .filter(f -> !CollectionUtils.isEmpty(f)) - .flatMap(Collection::stream) - .distinct() - .collect(Collectors.toList()); - - e.setPermissionRelations(rolePermissions); - }); - - List roleFeatureResources = cacheRoleSaasFeatureResourceHandler.resolveRoleFeatureResource(roles); - - if (CollectionUtils.isEmpty(roleFeatureResources)) { - return; - } - - RoleSaasFeatureResourceCacheService.StoreRoleSaasFeatureResourceParam storeRolePermissionParam = RoleSaasFeatureResourceCacheService.StoreRoleSaasFeatureResourceParam.builder() - .roleSaasFeatureResources(roleFeatureResources) - .build(); - roleSaasFeatureResourceCacheService.store(storeRolePermissionParam); - } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheRolePermissionJob.java b/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheRolePermissionJob.java index 3b0d3bea..d97fa08b 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheRolePermissionJob.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheRolePermissionJob.java @@ -1,15 +1,8 @@ package cn.axzo.tyr.server.job; -import cn.axzo.foundation.page.PageResp; -import cn.axzo.tyr.client.model.res.SaasPermissionRelationRes; import cn.axzo.tyr.client.model.res.SaasRoleRes; -import cn.axzo.tyr.server.event.inner.CacheRolePermissionHandler; -import cn.axzo.tyr.server.repository.dao.SaasPgroupRoleRelationDao; -import cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation; -import cn.axzo.tyr.server.repository.entity.SaasPgroupRoleRelation; import cn.axzo.tyr.server.service.RolePermissionCacheService; import cn.axzo.tyr.server.service.RoleService; -import cn.axzo.tyr.server.service.SaasPgroupPermissionRelationService; import com.alibaba.fastjson.JSONObject; import com.xxl.job.core.biz.model.ReturnT; import com.xxl.job.core.handler.IJobHandler; @@ -19,9 +12,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; -import java.util.Collection; -import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -30,102 +20,33 @@ import java.util.stream.Collectors; @Component public class CacheRolePermissionJob extends IJobHandler { - @Autowired - private CacheRolePermissionHandler cacheRolePermissionHandler; @Autowired private RoleService roleService; @Autowired - private SaasPgroupPermissionRelationService saasPgroupPermissionRelationService; - @Autowired - private SaasPgroupRoleRelationDao saasPgroupRoleRelationDao; - @Autowired private RolePermissionCacheService rolePermissionCacheService; - private static final Integer DEFAULT_PAGE_SIZE = 2000; @Override @XxlJob("CacheRolePermissionJob") public ReturnT execute(String s) throws Exception { log.info("start CacheRolePermissionJob, s:{}", s); - RoleService.PageSaasRoleParam pageSaasRoleParam = Optional.ofNullable(s) - .map(e -> JSONObject.parseObject(e, RoleService.PageSaasRoleParam.class)) - .orElseGet(() -> RoleService.PageSaasRoleParam.builder().build()); + RoleService.ListSaasRoleParam listSaasRoleParam = Optional.ofNullable(s) + .map(e -> JSONObject.parseObject(e, RoleService.ListSaasRoleParam.class)) + .orElseGet(() -> RoleService.ListSaasRoleParam.builder().build()); - // 因为角色权限集是重复使用,通过角色找权限集数据量太大,直接查询所有权限集的权限,比较快 - Map> permissionRelations = listPgroupPermissionRelation(); - - Integer pageNumber = 1; - while (true) { - pageSaasRoleParam.setPage(pageNumber++); - pageSaasRoleParam.setPageSize(DEFAULT_PAGE_SIZE); - PageResp page = roleService.page(pageSaasRoleParam); - - store(page.getData(), permissionRelations); - - if (!page.hasNext()) { - break; - } + Set roleIds = roleService.list(listSaasRoleParam).stream() + .map(SaasRoleRes::getId) + .collect(Collectors.toSet()); + if (CollectionUtils.isEmpty(roleIds)) { + return ReturnT.SUCCESS; } + RolePermissionCacheService.RefreshRolePermissionCacheParam refreshRolePermissionCacheParam = RolePermissionCacheService.RefreshRolePermissionCacheParam.builder() + .roleIds(roleIds) + .build(); + rolePermissionCacheService.refreshCache(refreshRolePermissionCacheParam); return ReturnT.SUCCESS; } - private Map> listPgroupPermissionRelation() { - return saasPgroupPermissionRelationService.list().stream() - .collect(Collectors.groupingBy(SaasPgroupPermissionRelation::getGroupId, - Collectors.mapping(e -> SaasPermissionRelationRes.builder() - .featureId(e.getFeatureId()) - .featureType(e.getFeatureType()) - .type(e.getType()) - .build(), Collectors.toList()))); - - } - - private Map> listPermissionGroup(List roleIds) { - - return saasPgroupRoleRelationDao.findByRoleIds(roleIds).stream() - .collect(Collectors.groupingBy(SaasPgroupRoleRelation::getRoleId, - Collectors.mapping(SaasPgroupRoleRelation::getGroupId, Collectors.toSet()))); - } - - private void store(List roles, - Map> permissionRelations) { - - if (CollectionUtils.isEmpty(roles)) { - return; - } - - List roleIds = roles.stream() - .map(SaasRoleRes::getId) - .collect(Collectors.toList()); - Map> roleGroupMap = listPermissionGroup(roleIds); - - roles.forEach(e -> { - Set groupIds = roleGroupMap.get(e.getId()); - if (CollectionUtils.isEmpty(groupIds)) { - return; - } - - List rolePermissions = groupIds.stream() - .map(permissionRelations::get) - .filter(f -> !CollectionUtils.isEmpty(f)) - .flatMap(Collection::stream) - .distinct() - .collect(Collectors.toList()); - - e.setPermissionRelations(rolePermissions); - }); - - List rolePermissions = cacheRolePermissionHandler.resolveRolePermission(roles); - - if (CollectionUtils.isEmpty(rolePermissions)) { - return; - } - - RolePermissionCacheService.StoreRolePermissionParam storeRolePermissionParam = RolePermissionCacheService.StoreRolePermissionParam.builder() - .rolePermissions(rolePermissions) - .build(); - rolePermissionCacheService.store(storeRolePermissionParam); - } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheSaasFeatureJob.java b/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheSaasFeatureJob.java index b667eb0d..622a1b4c 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheSaasFeatureJob.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheSaasFeatureJob.java @@ -1,13 +1,9 @@ package cn.axzo.tyr.server.job; -import cn.axzo.tyr.client.common.enums.FeatureResourceStatus; -import cn.axzo.tyr.client.model.enums.DelegatedType; import cn.axzo.tyr.client.model.req.PageSaasFeatureResourceReq; -import cn.axzo.tyr.client.model.res.PageElementResp; import cn.axzo.tyr.client.model.res.SaasFeatureResourceResp; import cn.axzo.tyr.server.repository.dao.SaasFeatureDao; import cn.axzo.tyr.server.repository.entity.SaasFeature; -import cn.axzo.tyr.server.repository.entity.SaasFeatureResource; import cn.axzo.tyr.server.service.SaasFeatureResourceService; import com.alibaba.fastjson.JSONObject; import com.xxl.job.core.biz.model.ReturnT; @@ -22,8 +18,6 @@ import org.apache.commons.collections.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -37,11 +31,6 @@ public class CacheSaasFeatureJob extends IJobHandler { @Autowired private SaasFeatureResourceService saasFeatureResourceService; - /** - * 分组这些菜单节点没有版本号,默认为0,方便权限过滤 - */ - private static final int DEFAULT_VERSION = 0; - @Override @XxlJob("CacheSaasFeatureJob") public ReturnT execute(String s) throws Exception { @@ -50,6 +39,7 @@ public class CacheSaasFeatureJob extends IJobHandler { StoreSaasFeatureParam req = Optional.ofNullable(s) .map(e -> JSONObject.parseObject(e, StoreSaasFeatureParam.class)) .orElseGet(() -> StoreSaasFeatureParam.builder().build()); + cacheSaasFeature(req.getTerminals()); cacheSaasFeatureResource(req.getTerminals()); @@ -57,66 +47,42 @@ public class CacheSaasFeatureJob extends IJobHandler { } public void cacheSaasFeature(Set terminals) { - Map> saasFeatures = saasFeatureDao.lambdaQuery() + // 没有办法只有所有端,除非写sql去重,菜单数量不多 + Set updateTerminals = saasFeatureDao.lambdaQuery() .in(CollectionUtils.isNotEmpty(terminals), SaasFeature::getTerminal, terminals) .list() .stream() - .collect(Collectors.groupingBy(SaasFeature::getTerminal, - Collectors.mapping(e -> SaasFeatureResourceService.SaasFeatureResourceCache - .builder() - .featureId(e.getId()) - .notAuth(DelegatedType.notAuth(e.getDelegatedType())) - .parentIds(e.splitPath()) - .build(), Collectors.toList()))); + .map(SaasFeature::getTerminal) + .collect(Collectors.toSet()); - List saasFeatureResources = saasFeatures.entrySet().stream() - .map(e -> SaasFeatureResourceService.SaasFeatureResourceDTO.builder() - .terminal(e.getKey()) - .features(e.getValue()) - .build()) - .collect(Collectors.toList()); + if (CollectionUtils.isEmpty(updateTerminals)) { + return; + } - SaasFeatureResourceService.StoreSaasFeatureResourceCache storeSaasFeatureResourceCache = SaasFeatureResourceService.StoreSaasFeatureResourceCache.builder() - .saasFeatureResources(saasFeatureResources) + SaasFeatureResourceService.RefreshFeatureResourceCacheParam param = SaasFeatureResourceService.RefreshFeatureResourceCacheParam.builder() + .terminals(updateTerminals) .build(); - saasFeatureResourceService.storeCache(storeSaasFeatureResourceCache); + saasFeatureResourceService.refreshCache(param); } public void cacheSaasFeatureResource(Set terminals) { PageSaasFeatureResourceReq pageSaasFeatureResourceReq = PageSaasFeatureResourceReq.builder() - .needPageElement(true) .terminals(terminals) .build(); - Map> saasFeatureResources = saasFeatureResourceService.list(pageSaasFeatureResourceReq) + Set updateTerminals = saasFeatureResourceService.list(pageSaasFeatureResourceReq) .stream() - .collect(Collectors.groupingBy(SaasFeatureResourceResp::getTerminal, - Collectors.mapping(e -> SaasFeatureResourceService.SaasFeatureResourceCache - .builder() - .featureId(e.getId()) - .notAuth(SaasFeatureResource.AuthType.isAllRole(e.getAuthType())) - .parentIds(e.resolvePath()) - .uniCode(e.getUniCode()) - .status(e.getStatus()) - .version(Optional.ofNullable(e.getSaasPageElements()) - .map(pageElement -> pageElement.stream() - .findFirst() - .map(PageElementResp::getVersion) - .orElse(DEFAULT_VERSION)) - .orElse(DEFAULT_VERSION)) - .build(), Collectors.toList()))); + .map(SaasFeatureResourceResp::getTerminal) + .collect(Collectors.toSet()); - List featureResources = saasFeatureResources.entrySet().stream() - .map(e -> SaasFeatureResourceService.SaasFeatureResourceDTO.builder() - .terminal(e.getKey()) - .features(e.getValue()) - .build()) - .collect(Collectors.toList()); + if (CollectionUtils.isEmpty(updateTerminals)) { + return; + } - SaasFeatureResourceService.StoreSaasFeatureResourceCache storeSaasFeatureResourceCache = SaasFeatureResourceService.StoreSaasFeatureResourceCache.builder() - .saasFeatureResources(featureResources) + SaasFeatureResourceService.RefreshFeatureResourceCacheParam param = SaasFeatureResourceService.RefreshFeatureResourceCacheParam.builder() + .terminals(updateTerminals) .build(); - saasFeatureResourceService.storeCache(storeSaasFeatureResourceCache); + saasFeatureResourceService.refreshCache(param); } @Data diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/ProductPermissionCacheService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/ProductPermissionCacheService.java index d222620d..1e67c38a 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/ProductPermissionCacheService.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/ProductPermissionCacheService.java @@ -18,18 +18,15 @@ public interface ProductPermissionCacheService { */ Map> list(ListProductPermissionParam param); - /** - * 存储产品的权限信息 - * @param param - */ - void store(StoreProductPermissionParam param); + void refreshCache(RefreshProductPermissionCacheParam param); - /** - * 产品是否有缓存权限 - * @param param - * @return - */ - List hasProductIds(HasProductPermissionParam param); + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + class RefreshProductPermissionCacheParam { + private Set productIds; + } @Data @Builder diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/ProductSaasFeatureResourceCacheService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/ProductSaasFeatureResourceCacheService.java index 71ddb527..e7441513 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/ProductSaasFeatureResourceCacheService.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/ProductSaasFeatureResourceCacheService.java @@ -13,7 +13,15 @@ public interface ProductSaasFeatureResourceCacheService { Map> list(ListProductFeatureResourceParam param); - void store(StoreProductFeatureResourceParam param); + void refreshCache(RefreshProductFeatureResourceCacheParam param); + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + class RefreshProductFeatureResourceCacheParam { + private Set productIds; + } @Data @Builder diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/RolePermissionCacheService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/RolePermissionCacheService.java index ae332e55..67b62a8d 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/RolePermissionCacheService.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/RolePermissionCacheService.java @@ -14,29 +14,14 @@ public interface RolePermissionCacheService { Map> list(ListRolePermissionParam param); - /** - * redisKey:roleId - * redisValue:permission - * @param param - */ - void store(StoreRolePermissionParam param); - - List hasRoleIds(HasRolePermissionParam param); + void refreshCache(RefreshRolePermissionCacheParam param); @Data @Builder @NoArgsConstructor @AllArgsConstructor - class HasRolePermissionParam { - private List roleIds; - } - - @Data - @Builder - @NoArgsConstructor - @AllArgsConstructor - class StoreRolePermissionParam { - private List rolePermissions; + class RefreshRolePermissionCacheParam { + private Set roleIds; } @Data diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/RoleSaasFeatureResourceCacheService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/RoleSaasFeatureResourceCacheService.java index f5a95828..5d70fe28 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/RoleSaasFeatureResourceCacheService.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/RoleSaasFeatureResourceCacheService.java @@ -13,8 +13,15 @@ public interface RoleSaasFeatureResourceCacheService { Map> list(ListRoleSaasFeatureResourceParam param); - void store(StoreRoleSaasFeatureResourceParam param); + void refreshCache(RefreshRoleFeatureResourceCacheParam param); + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + class RefreshRoleFeatureResourceCacheParam { + private Set roleIds; + } @Data @Builder diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasFeatureResourceService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasFeatureResourceService.java index 10ec91e5..7aa6fa61 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasFeatureResourceService.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasFeatureResourceService.java @@ -64,10 +64,18 @@ public interface SaasFeatureResourceService extends IService> listCache(ListSaasFeatureResourceCache param); + void refreshCache(RefreshFeatureResourceCacheParam param); + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + class RefreshFeatureResourceCacheParam { + private Set terminals; + } + @Data @Builder @NoArgsConstructor diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductPermissionCacheServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductPermissionCacheServiceImpl.java index 6e1415b6..2c48a40b 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductPermissionCacheServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductPermissionCacheServiceImpl.java @@ -1,228 +1,348 @@ package cn.axzo.tyr.server.service.impl; -import cn.axzo.foundation.exception.Axssert; -import cn.axzo.pokonyan.config.redis.RedisClient; +import cn.axzo.basics.common.exception.ServiceException; import cn.axzo.tyr.client.model.req.PageProductFeatureRelationReq; -import cn.axzo.tyr.server.event.inner.CacheProductPermissionHandler; +import cn.axzo.tyr.client.model.req.PageSaasFeatureResourceReq; +import cn.axzo.tyr.client.model.res.SaasFeatureResourceResp; +import cn.axzo.tyr.server.repository.dao.SaasFeatureDao; +import cn.axzo.tyr.server.repository.entity.SaasFeature; import cn.axzo.tyr.server.repository.entity.SaasProductModuleFeatureRelation; import cn.axzo.tyr.server.service.ProductFeatureRelationService; import cn.axzo.tyr.server.service.ProductPermissionCacheService; +import cn.axzo.tyr.server.service.SaasFeatureResourceService; import cn.hutool.core.lang.Pair; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import com.google.common.collect.Sets; -import com.google.common.collect.Streams; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.BooleanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.dao.DataAccessException; -import org.springframework.data.redis.core.RedisOperations; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.SessionCallback; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; +import java.util.function.Function; import java.util.stream.Collectors; -import static cn.axzo.tyr.server.config.exception.BizResultCode.REDIS_PRODUCT_NOT_NULL; +import static cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation.NEW_FEATURE; +import static cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation.OLD_FEATURE; @Slf4j @Service @RefreshScope public class ProductPermissionCacheServiceImpl implements ProductPermissionCacheService { - private static final String PRODUCT_PERMISSION_KEY = "product:permission:%s"; - - @Autowired - private RedisTemplate redisTemplate; @Autowired private ProductFeatureRelationService productFeatureRelationService; @Autowired - private CacheProductPermissionHandler cacheProductPermissionHandler; + private SaasFeatureResourceService saasFeatureResourceService; + @Autowired + private SaasFeatureDao saasFeatureDao; /** 产品权限缓存过期时间 **/ @Value("${product.permission.expire.minutes:14}") private Long expireInMinutes; + private LoadingCache>> productPermissionCache = CacheBuilder.newBuilder() + .expireAfterWrite(14, TimeUnit.MINUTES) + .maximumSize(5000) + .build(new CacheLoader>>() { + @Override + public Optional> load(Long productId) { + return listProductPermissions(Lists.newArrayList(productId)) + .values() + .stream() + .findFirst(); + } + + @Override + public Map>> loadAll(Iterable keys) throws Exception { + List productIds = Lists.newArrayList(keys); + + Map> productPermissions = listProductPermissions(productIds); + + return Maps.toMap(productIds, productId -> Optional.ofNullable(productPermissions.get(productId))); + } + }); + @Override public Map> list(ListProductPermissionParam param) { if (CollectionUtils.isEmpty(param.getProductIds())) { return Collections.emptyMap(); } - Map> permissionCached = listProductPermissionCached(param); + Map> productPermissions; + try { + productPermissions = productPermissionCache.getAll(param.getProductIds()).entrySet() + .stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().orElseGet(Lists::newArrayList))); + } catch (ExecutionException ex) { + log.error("list product cache permission error:{} error", param.getProductIds(), ex); + // 外面有做降级 + throw new ServiceException("查询产品权限缓存异常"); + } - fillCacheProductPermissions(param, permissionCached); + if (CollectionUtils.isEmpty(param.getFeatureCodes())) { + return productPermissions; + } - return permissionCached; - } - - private Map> listProductPermissionCached(ListProductPermissionParam param) { - - List redisValues = redisTemplate.executePipelined(new SessionCallback() { - @Override - public Object execute(RedisOperations operations) throws DataAccessException { - - for (Long productId : param.getProductIds()) { - String redisKey = getKey(productId); - - if (CollectionUtils.isEmpty(param.getFeatureCodes())) { - RedisClient.HashOps.hGetAll(redisKey); - } else { - RedisClient.HashOps.hMultiGet(redisKey, Lists.newArrayList(param.getFeatureCodes())); - } - - } - return null; - } - }); - - return Streams.zip(param.getProductIds().stream(), - redisValues.stream(), - (productId, redisValue) -> { - - if (Objects.isNull(redisValue)) { - return null; - } - - if (CollectionUtils.isEmpty(param.getFeatureCodes())) { - List permissions = (List) ((Map) redisValue).values().stream() - .flatMap(e -> JSONArray.parseArray(JSONArray.toJSONString(e), PermissionDTO.class).stream()) - .collect(Collectors.toList()); - - return Pair.of(productId, permissions); - } - - List permissions = (List) ((List) redisValue).stream() - .filter(Objects::nonNull) - .flatMap(e -> JSONArray.parseArray((String) e, PermissionDTO.class).stream()) - .collect(Collectors.toList()); - - return Pair.of(productId, permissions); - - }) - .filter(Objects::nonNull) + return productPermissions.entrySet() + .stream() + .map(e -> Pair.of(e.getKey(), e.getValue().stream() + .filter(permission -> param.getFeatureCodes().contains(permission.getFeatureCode())) + .collect(Collectors.toList())) + ) + .filter(e -> !CollectionUtils.isEmpty(e.getValue())) .collect(Collectors.toMap(Pair::getKey, Pair::getValue)); } @Override - public void store(StoreProductPermissionParam param) { - - Axssert.check(param.getProductPermissions().stream().allMatch(e -> Objects.nonNull(e.getProductId())), REDIS_PRODUCT_NOT_NULL); - - redisTemplate.executePipelined(new SessionCallback() { - @Override - public Object execute(RedisOperations operations) throws DataAccessException { - - for (ProductPermission productPermission : param.getProductPermissions()) { - String redisKey = getKey(productPermission.getProductId()); - - Map redisValues = productPermission.getPermissions().stream() - .collect(Collectors.groupingBy(PermissionDTO::getFeatureCode)) - .entrySet() - .stream() - .collect(Collectors.toMap(Map.Entry::getKey, e -> JSONObject.toJSONString(e.getValue()))); - - // 存在hash中部分key移除,为了处理快,直接把redisKey删除掉,修改不频繁 - redisTemplate.delete(redisKey); - RedisClient.HashOps.hPutAll(redisKey, redisValues); - redisTemplate.expire(redisKey, expireInMinutes, TimeUnit.MINUTES); - log.info("succeed to store product permission: redisKey:{} value:{}", redisKey, redisValues); - } - return null; - } - }); - } - - @Override - public List hasProductIds(HasProductPermissionParam param) { - List redisValues = redisTemplate.executePipelined(new SessionCallback() { - @Override - public Object execute(RedisOperations operations) throws DataAccessException { - - for (Long productId : param.getProductIds()) { - String redisKey = getKey(productId); - operations.hasKey(redisKey); - } - return null; - } - }); - - return Streams.zip(param.getProductIds().stream(), - redisValues.stream(), - (productId, redisValue) -> Pair.of(productId, redisValue)) - .filter(e -> BooleanUtils.isTrue((Boolean) e.getValue())) - .map(Pair::getKey) - .collect(Collectors.toList()); - } - - /** - * 组装在缓存中没有查询到权限的产品 - * @param param - * @param permissionCached - */ - private void fillCacheProductPermissions(ListProductPermissionParam param, - Map> permissionCached) { - - Sets.SetView difference = Sets.difference(param.getProductIds(), permissionCached.keySet()); - if (difference.isEmpty()) { + public void refreshCache(RefreshProductPermissionCacheParam param) { + if (CollectionUtils.isEmpty(param.getProductIds())) { return; } + Map> productPermissions = listProductPermissions(Lists.newArrayList(param.getProductIds())); + + productPermissionCache.putAll(Maps.toMap(param.getProductIds(), productId -> Optional.ofNullable(productPermissions.get(productId)))); + } + + private Map> listProductPermissions(List productIds) { + + if (CollectionUtils.isEmpty(productIds)) { + return Collections.emptyMap(); + } + PageProductFeatureRelationReq pageProductFeatureRelationReq = PageProductFeatureRelationReq.builder() - .productModuleIds(difference) + .productModuleIds(Sets.newHashSet(productIds)) .build(); List productPermissions = productFeatureRelationService.list(pageProductFeatureRelationReq); - List productPermissionsCache = cacheProductPermissionHandler.resolveProductPermissions(productPermissions); - if (CollectionUtils.isEmpty(productPermissionsCache)) return; - - StoreProductPermissionParam storeWorkspaceProductParam = StoreProductPermissionParam.builder() - .productPermissions(productPermissionsCache) - .build(); - store(storeWorkspaceProductParam); - - Map> productPermissionMap = productPermissionsCache.stream() + return resolveProductPermissions(productPermissions).stream() .collect(Collectors.toMap(ProductPermission::getProductId, ProductPermission::getPermissions)); - permissionCached.putAll(productPermissionMap); } - private String getKey(Object... params) { - return String.format(PRODUCT_PERMISSION_KEY, params); + private List resolveProductPermissions(List productPermissions) { + if (CollectionUtils.isEmpty(productPermissions)) { + return Collections.emptyList(); + } + + // 新的菜单树是是把有权限点的父节点也存进去了,所以直接解析 + Map featureResources = listSaasFeatureResource(productPermissions); + + Map parentFeatureResources = listParentSaasFeatureResource(featureResources); + + // 旧的菜单树只存储了权限点信息,没有把父节点存进去,需要解析父节点进行存储 + Map saasFeatures = listSaasFeature(productPermissions); + + Map parentSaasFeatures = listParentSaasFeature(saasFeatures); + + return productPermissions.stream() + .collect(Collectors.groupingBy(SaasProductModuleFeatureRelation::getProductModuleId)) + .entrySet() + .stream() + .map(e -> { + List productFeatureRelations = e.getValue(); + + if (CollectionUtils.isEmpty(productFeatureRelations)) { + return null; + } + + List permissions = productFeatureRelations.stream() + .map(relation -> { + if (Objects.equals(relation.getType(), NEW_FEATURE)) { + return resolveFeatureResourcePermission(relation, featureResources, parentFeatureResources); + } + + return resolveFeaturePermission(relation, saasFeatures, parentSaasFeatures); + }) + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .distinct() + .collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(permissions)) { + return null; + } + + return ProductPermissionCacheService.ProductPermission.builder() + .productId(e.getKey()) + .permissions(permissions) + .build(); + + }) + .filter(Objects::nonNull) + .collect(Collectors.toList()); } - @Data - @Builder - @NoArgsConstructor - @AllArgsConstructor - static class PermissionWrapper { + private List resolveFeaturePermission(SaasProductModuleFeatureRelation relation, Map saasFeatures, Map parentSaasFeatures) { + SaasFeature saasFeature = saasFeatures.get(relation.getFeatureId()); + if (Objects.isNull(saasFeature)) { + return null; + } - /** - * 协同关系类型 - * 原saas_product_module_feature_relation.dictCode - */ - private String cooperateType; + List permissionDTOS = Lists.newArrayList(ProductPermissionCacheService.PermissionDTO.builder() + .featureId(saasFeature.getId()) + .featureCode(saasFeature.getFeatureCode()) + .featureType(saasFeature.getFeatureType()) + .terminal(saasFeature.getTerminal()) + .cooperateType(relation.getDictCode()) + .build()); - private Long featureId; + List parentPermissions = saasFeature.splitPath().stream() + .map(parentSaasFeatures::get) + .filter(Objects::nonNull) + .map(f -> ProductPermissionCacheService.PermissionDTO.builder() + .featureId(f.getId()) + .featureCode(f.getFeatureCode()) + .featureType(f.getFeatureType()) + .terminal(f.getTerminal()) + .cooperateType(relation.getDictCode()) + .build()) + .collect(Collectors.toList()); - private String featureCode; + permissionDTOS.addAll(parentPermissions); + return permissionDTOS; + } - private String terminal; + private List resolveFeatureResourcePermission(SaasProductModuleFeatureRelation relation, Map featureResources, Map parentFeatureResources) { + SaasFeatureResourceResp featureResource = featureResources.get(relation.getFeatureId()); + // 菜单节点是不会关联元素code,所以缓存的featureCode使用菜单编码 + if (Objects.isNull(featureResource)) { + return null; + } - private Integer featureType; + if (CollectionUtils.isEmpty(featureResource.getSaasPageElements())) { + return null; + } - private Long productId; + List permissionDTOS = featureResource.getSaasPageElements().stream() + .map(pageElement -> ProductPermissionCacheService.PermissionDTO.builder() + .featureId(featureResource.getId()) + .featureCode(pageElement.getCode()) + .featureType(featureResource.getFeatureType()) + .terminal(featureResource.getTerminal()) + .cooperateType(relation.getDictCode()) + .itemCode(pageElement.getItemCode()) + .version(pageElement.getVersion()) + .appType(pageElement.getAppType()) + .build()) + .collect(Collectors.toList()); + + List parentPermissions = featureResource.resolvePath().stream() + .map(parentFeatureResources::get) + .filter(Objects::nonNull) + .map(f -> { + if (CollectionUtils.isEmpty(f.getSaasPageElements())) { + return null; + } + + return f.getSaasPageElements().stream() + .map(pageElement -> ProductPermissionCacheService.PermissionDTO.builder() + .featureId(f.getId()) + .featureCode(pageElement.getCode()) + .featureType(f.getFeatureType()) + .terminal(f.getTerminal()) + .cooperateType(relation.getDictCode()) + .itemCode(pageElement.getItemCode()) + .version(pageElement.getVersion()) + .appType(pageElement.getAppType()) + .build()) + .collect(Collectors.toList()); + }) + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .collect(Collectors.toList()); + + permissionDTOS.addAll(parentPermissions); + return permissionDTOS; + } + + + private Map listSaasFeatureResource(List productPermissions) { + + List featureIds = productPermissions.stream() + .filter(e -> Objects.equals(e.getType(), NEW_FEATURE)) + .map(SaasProductModuleFeatureRelation::getFeatureId) + .distinct() + .collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(featureIds)) { + return Collections.emptyMap(); + } + + PageSaasFeatureResourceReq pageSaasFeatureResourceReq = PageSaasFeatureResourceReq.builder() + .ids(featureIds) + .needPageElement(true) + .build(); + return saasFeatureResourceService.list(pageSaasFeatureResourceReq).stream() + .collect(Collectors.toMap(SaasFeatureResourceResp::getId, Function.identity(), (f, s) -> s)); + } + + private Map listParentSaasFeatureResource(Map productPermissions) { + + List parentIds = productPermissions.values().stream() + .map(SaasFeatureResourceResp::resolvePath) + .flatMap(Collection::stream) + .distinct() + .collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(parentIds)) { + return Collections.emptyMap(); + } + + PageSaasFeatureResourceReq pageSaasFeatureResourceReq = PageSaasFeatureResourceReq.builder() + .ids(parentIds) + .needPageElement(true) + .build(); + return saasFeatureResourceService.list(pageSaasFeatureResourceReq).stream() + .collect(Collectors.toMap(SaasFeatureResourceResp::getId, Function.identity(), (f, s) -> s)); + } + + private Map listSaasFeature(List productPermissions) { + + Set featureIds = productPermissions.stream() + .filter(e -> Objects.equals(e.getType(), OLD_FEATURE)) + .map(SaasProductModuleFeatureRelation::getFeatureId) + .collect(Collectors.toSet()); + + if (CollectionUtils.isEmpty(featureIds)) { + return Collections.emptyMap(); + } + + return saasFeatureDao.listByIds(featureIds).stream() + .collect(Collectors.toMap(SaasFeature::getId, Function.identity())); + } + + private Map listParentSaasFeature(Map saasFeatures) { + + if (CollectionUtils.isEmpty(saasFeatures)) { + return Collections.emptyMap(); + } + + List parentIds = saasFeatures.values().stream() + .map(SaasFeature::splitPath) + .flatMap(Collection::stream) + .distinct() + .collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(parentIds)) { + return Collections.emptyMap(); + } + + return saasFeatureDao.listByIds(parentIds).stream() + .collect(Collectors.toMap(SaasFeature::getId, Function.identity())); } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductSaasFeatureResourceCacheServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductSaasFeatureResourceCacheServiceImpl.java index 97d7c6cc..09eeb53f 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductSaasFeatureResourceCacheServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductSaasFeatureResourceCacheServiceImpl.java @@ -1,38 +1,41 @@ package cn.axzo.tyr.server.service.impl; -import cn.axzo.foundation.exception.Axssert; -import cn.axzo.pokonyan.config.redis.RedisClient; +import cn.axzo.basics.common.exception.ServiceException; import cn.axzo.tyr.client.common.enums.FeatureResourceType; import cn.axzo.tyr.client.model.req.PageProductFeatureRelationReq; -import cn.axzo.tyr.server.event.inner.CacheProductSaasFeatureResourceHandler; +import cn.axzo.tyr.client.model.req.PageSaasFeatureResourceReq; +import cn.axzo.tyr.client.model.res.SaasFeatureResourceResp; import cn.axzo.tyr.server.repository.entity.SaasProductModuleFeatureRelation; import cn.axzo.tyr.server.service.ProductFeatureRelationService; import cn.axzo.tyr.server.service.ProductSaasFeatureResourceCacheService; +import cn.axzo.tyr.server.service.SaasFeatureResourceService; import cn.hutool.core.lang.Pair; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import com.google.common.collect.Sets; -import com.google.common.collect.Streams; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.dao.DataAccessException; -import org.springframework.data.redis.core.RedisOperations; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.SessionCallback; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; +import java.util.function.Function; import java.util.stream.Collectors; -import static cn.axzo.tyr.server.config.exception.BizResultCode.REDIS_PRODUCT_NOT_NULL; import static cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation.NEW_FEATURE; @Slf4j @@ -40,139 +43,213 @@ import static cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation. @RefreshScope public class ProductSaasFeatureResourceCacheServiceImpl implements ProductSaasFeatureResourceCacheService { - private static final String PRODUCT_SAAS_FEATURE_RESOURCE_KEY = "product:feature:resource:%s"; - - @Autowired - private RedisTemplate redisTemplate; @Autowired private ProductFeatureRelationService productFeatureRelationService; @Autowired - private CacheProductSaasFeatureResourceHandler cacheProductSaasFeatureResourceHandler; + private SaasFeatureResourceService saasFeatureResourceService; @Value("${product.feature.resouce.expire.minutes:14}") private Long expireInMinutes; + public static final Set FEATURE_RESOURCE_TYPES = Sets.newHashSet(FeatureResourceType.MENU.getCode(), + FeatureResourceType.PAGE.getCode(), + FeatureResourceType.MENU_PARTITION_GROUP.getCode(), + FeatureResourceType.GROUP.getCode(), + FeatureResourceType.APP_ENTRY.getCode()); + + private LoadingCache>> productFeatureResourceCache = CacheBuilder.newBuilder() + .expireAfterWrite(14, TimeUnit.MINUTES) + .maximumSize(5000) + .build(new CacheLoader>>() { + @Override + public Optional> load(Long productId) { + return listProductFeatureResource(Lists.newArrayList(productId)) + .values() + .stream() + .findFirst(); + } + + @Override + public Map>> loadAll(Iterable keys) throws Exception { + List productIds = Lists.newArrayList(keys); + + Map> productPermissions = listProductFeatureResource(productIds); + + return Maps.toMap(productIds, productId -> Optional.ofNullable(productPermissions.get(productId))); + } + }); + @Override public Map> list(ListProductFeatureResourceParam param) { if (CollectionUtils.isEmpty(param.getProductIds())) { return Collections.emptyMap(); } - Map> featureResourceCached = listProductFeatureResourceCached(param); + Map> productFeatureResources; + try { + productFeatureResources = productFeatureResourceCache.getAll(param.getProductIds()).entrySet() + .stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().orElseGet(Lists::newArrayList))); + } catch (ExecutionException ex) { + log.error("list product cache featureResource error:{} error", param.getProductIds(), ex); + // 外面有做降级 + throw new ServiceException("查询产品菜单缓存异常"); + } - fillCacheProductFeatureResource(param, featureResourceCached); + if (CollectionUtils.isEmpty(param.getUniCodes())) { + return productFeatureResources; + } - return featureResourceCached; - } - - @Override - public void store(StoreProductFeatureResourceParam param) { - Axssert.check(param.getProductFeatureResources().stream().allMatch(e -> Objects.nonNull(e.getProductId())), REDIS_PRODUCT_NOT_NULL); - - redisTemplate.executePipelined(new SessionCallback() { - @Override - public Object execute(RedisOperations operations) throws DataAccessException { - - for (ProductFeatureResource productFeatureResource : param.getProductFeatureResources()) { - String redisKey = getKey(productFeatureResource.getProductId()); - - Map redisValues = productFeatureResource.getFeatureResources().stream() - .collect(Collectors.groupingBy(FeatureResourceDTO::getUniCode)) - .entrySet() - .stream() - .collect(Collectors.toMap(Map.Entry::getKey, e -> JSONObject.toJSONString(e.getValue()))); - - // 存在hash中部分key移除,为了处理快,直接把redisKey删除掉,修改不频繁 - redisTemplate.delete(redisKey); - RedisClient.HashOps.hPutAll(redisKey, redisValues); - redisTemplate.expire(redisKey, expireInMinutes, TimeUnit.MINUTES); - log.info("succeed to store product featureResource: redisKey:{} value:{}", redisKey, redisValues); - } - return null; - } - }); - } - - private Map> listProductFeatureResourceCached(ListProductFeatureResourceParam param) { - - List redisValues = redisTemplate.executePipelined(new SessionCallback() { - @Override - public Object execute(RedisOperations operations) throws DataAccessException { - - for (Long productId : param.getProductIds()) { - String redisKey = getKey(productId); - - if (CollectionUtils.isEmpty(param.getUniCodes())) { - RedisClient.HashOps.hGetAll(redisKey); - } else { - RedisClient.HashOps.hMultiGet(redisKey, Lists.newArrayList(param.getUniCodes())); - } - - } - return null; - } - }); - - return Streams.zip(param.getProductIds().stream(), - redisValues.stream(), - (productId, redisValue) -> { - - if (Objects.isNull(redisValue)) { - return null; - } - - if (CollectionUtils.isEmpty(param.getUniCodes())) { - List featureResources = (List) ((Map) redisValue).values().stream() - .flatMap(e -> JSONArray.parseArray(JSONArray.toJSONString(e), FeatureResourceDTO.class).stream()) - .collect(Collectors.toList()); - - return Pair.of(productId, featureResources); - } - - List featureResources = (List) ((List) redisValue).stream() - .filter(Objects::nonNull) - .flatMap(e -> JSONArray.parseArray((String) e, FeatureResourceDTO.class).stream()) - .collect(Collectors.toList()); - - return Pair.of(productId, featureResources); - - }) - .filter(Objects::nonNull) + return productFeatureResources.entrySet() + .stream() + .map(e -> Pair.of(e.getKey(), e.getValue().stream() + .filter(permission -> param.getUniCodes().contains(permission.getUniCode())) + .collect(Collectors.toList())) + ) + .filter(e -> !CollectionUtils.isEmpty(e.getValue())) .collect(Collectors.toMap(Pair::getKey, Pair::getValue)); } - private void fillCacheProductFeatureResource(ListProductFeatureResourceParam param, - Map> featureResourceCached) { - - Sets.SetView difference = Sets.difference(param.getProductIds(), featureResourceCached.keySet()); - if (difference.isEmpty()) { + @Override + public void refreshCache(RefreshProductFeatureResourceCacheParam param) { + if (CollectionUtils.isEmpty(param.getProductIds())) { return; } + Map> productPermissions = listProductFeatureResource(Lists.newArrayList(param.getProductIds())); + + productFeatureResourceCache.putAll(Maps.toMap(param.getProductIds(), productId -> Optional.ofNullable(productPermissions.get(productId)))); + } + + private Map> listProductFeatureResource(List productIds) { + + if (CollectionUtils.isEmpty(productIds)) { + return Collections.emptyMap(); + } + PageProductFeatureRelationReq pageProductFeatureRelationReq = PageProductFeatureRelationReq.builder() - .productModuleIds(difference) + .productModuleIds(Sets.newHashSet(productIds)) .type(NEW_FEATURE) - .featureResourceTypes(Lists.newArrayList(FeatureResourceType.MENU.getCode(), - FeatureResourceType.PAGE.getCode(), - FeatureResourceType.MENU_PARTITION_GROUP.getCode(), - FeatureResourceType.GROUP.getCode(), - FeatureResourceType.APP_ENTRY.getCode())) .build(); List productPermissions = productFeatureRelationService.list(pageProductFeatureRelationReq); - List productFeatureResources = cacheProductSaasFeatureResourceHandler.resolveProductFeatureResources(productPermissions); - if (CollectionUtils.isEmpty(productFeatureResources)) return; - - StoreProductFeatureResourceParam storeProductFeatureResourceParam = StoreProductFeatureResourceParam.builder() - .productFeatureResources(productFeatureResources) - .build(); - store(storeProductFeatureResourceParam); - - Map> productFeatureResourceMap = productFeatureResources.stream() + return resolveProductFeatureResources(productPermissions).stream() .collect(Collectors.toMap(ProductFeatureResource::getProductId, ProductFeatureResource::getFeatureResources)); - featureResourceCached.putAll(productFeatureResourceMap); } - private String getKey(Object... params) { - return String.format(PRODUCT_SAAS_FEATURE_RESOURCE_KEY, params); + private List resolveProductFeatureResources(List productPermissions) { + if (CollectionUtils.isEmpty(productPermissions)) { + return Collections.emptyList(); + } + + Map featureResources = listSaasFeatureResource(productPermissions); + + Map parentFeatureResources = listParentSaasFeatureResource(featureResources); + + return productPermissions.stream() + .collect(Collectors.groupingBy(SaasProductModuleFeatureRelation::getProductModuleId)) + .entrySet() + .stream() + .map(e -> { + List productFeatureRelations = e.getValue(); + + if (CollectionUtils.isEmpty(productFeatureRelations)) { + return null; + } + + List productFeatureResources = productFeatureRelations.stream() + .map(relation -> { + SaasFeatureResourceResp featureResource = featureResources.get(relation.getFeatureId()); + if (Objects.isNull(featureResource) || StringUtils.isBlank(featureResource.getUniCode())) { + return null; + } + + ProductSaasFeatureResourceCacheService.FeatureResourceDTO featureResourceDTO = from(featureResource, relation); + List featureResourceDTOS = Lists.newArrayList(featureResourceDTO); + + List parentPermissions = featureResource.resolvePath().stream() + .map(parentFeatureResources::get) + .filter(Objects::nonNull) + .map(f -> { + + if (StringUtils.isBlank(f.getUniCode())) { + return null; + } + + return from(featureResource, relation); + }) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + featureResourceDTOS.addAll(parentPermissions); + + return featureResourceDTOS; + }) + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .distinct() + .filter(f -> FEATURE_RESOURCE_TYPES.contains(f.getFeatureType())) + .collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(productFeatureResources)) { + return null; + } + + return ProductSaasFeatureResourceCacheService.ProductFeatureResource.builder() + .productId(e.getKey()) + .featureResources(productFeatureResources) + .build(); + + }) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } + + private ProductSaasFeatureResourceCacheService.FeatureResourceDTO from(SaasFeatureResourceResp featureResource, + SaasProductModuleFeatureRelation relation) { + return ProductSaasFeatureResourceCacheService.FeatureResourceDTO.builder() + .featureId(featureResource.getId()) + .featureType(featureResource.getFeatureType()) + .terminal(featureResource.getTerminal()) + .uniCode(featureResource.getUniCode()) + .cooperateType(relation.getDictCode()) + .build(); + } + + private Map listSaasFeatureResource(List productPermissions) { + + List featureIds = productPermissions.stream() + .map(SaasProductModuleFeatureRelation::getFeatureId) + .distinct() + .collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(featureIds)) { + return Collections.emptyMap(); + } + + // 存在pre环境更改了节点的父节点,可能导致产品没有父节点的权限,这里补齐父节点的权限 + PageSaasFeatureResourceReq pageSaasFeatureResourceReq = PageSaasFeatureResourceReq.builder() + .ids(featureIds) + .build(); + return saasFeatureResourceService.list(pageSaasFeatureResourceReq).stream() + .collect(Collectors.toMap(SaasFeatureResourceResp::getId, Function.identity(), (f, s) -> s)); + } + + private Map listParentSaasFeatureResource(Map productPermissions) { + + List parentIds = productPermissions.values().stream() + .map(SaasFeatureResourceResp::resolvePath) + .flatMap(Collection::stream) + .distinct() + .collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(parentIds)) { + return Collections.emptyMap(); + } + + // 存在pre环境更改了节点的父节点,可能导致产品没有父节点的权限,这里补齐父节点的权限 + PageSaasFeatureResourceReq pageSaasFeatureResourceReq = PageSaasFeatureResourceReq.builder() + .ids(parentIds) + .build(); + return saasFeatureResourceService.list(pageSaasFeatureResourceReq).stream() + .collect(Collectors.toMap(SaasFeatureResourceResp::getId, Function.identity(), (f, s) -> s)); } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RolePermissionCacheServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RolePermissionCacheServiceImpl.java index 43ac0dbb..14eb0b7a 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RolePermissionCacheServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RolePermissionCacheServiceImpl.java @@ -1,207 +1,338 @@ package cn.axzo.tyr.server.service.impl; -import cn.axzo.foundation.exception.Axssert; -import cn.axzo.pokonyan.config.redis.RedisClient; +import cn.axzo.basics.common.exception.ServiceException; +import cn.axzo.tyr.client.model.req.PageSaasFeatureResourceReq; +import cn.axzo.tyr.client.model.res.SaasFeatureResourceResp; +import cn.axzo.tyr.client.model.res.SaasPermissionRelationRes; import cn.axzo.tyr.client.model.res.SaasRoleRes; -import cn.axzo.tyr.server.event.inner.CacheRolePermissionHandler; +import cn.axzo.tyr.server.repository.dao.SaasFeatureDao; +import cn.axzo.tyr.server.repository.entity.SaasFeature; import cn.axzo.tyr.server.service.RolePermissionCacheService; import cn.axzo.tyr.server.service.RoleService; +import cn.axzo.tyr.server.service.SaasFeatureResourceService; import cn.hutool.core.lang.Pair; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import com.google.common.collect.Streams; +import com.google.common.collect.Maps; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.BooleanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.dao.DataAccessException; -import org.springframework.data.redis.core.RedisCallback; -import org.springframework.data.redis.core.RedisOperations; -import org.springframework.data.redis.core.SessionCallback; -import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; +import java.util.function.Function; import java.util.stream.Collectors; -import static cn.axzo.tyr.server.config.exception.BizResultCode.REDIS_ROLE_NOT_NULL; +import static cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation.NEW_FEATURE; +import static cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation.OLD_FEATURE; @Slf4j @Service @RefreshScope public class RolePermissionCacheServiceImpl implements RolePermissionCacheService { - private static final String ROLE_PERMISSION_KEY = "role:permission:%s"; - - @Autowired - protected StringRedisTemplate redisTemplate; @Autowired private RoleService roleService; @Autowired - private CacheRolePermissionHandler cacheRolePermissionHandler; - + private SaasFeatureResourceService saasFeatureResourceService; + @Autowired + private SaasFeatureDao saasFeatureDao; /** 角色权限缓存过期时间 **/ @Value("${role.permission.expire.minutes:14}") - private Long expireInMinutes; + private static Long expireInMinutes; + + private LoadingCache>> rolePermissionCache = CacheBuilder.newBuilder() + .expireAfterWrite(14, TimeUnit.MINUTES) + .maximumSize(5000) + .build(new CacheLoader>>() { + @Override + public Optional> load(Long roleId) { + return listRolePermission(Lists.newArrayList(roleId)) + .values() + .stream() + .findFirst(); + } + + @Override + public Map>> loadAll(Iterable keys) throws Exception { + List roleIds = Lists.newArrayList(keys); + + Map> rolePermissions = listRolePermission(roleIds); + + return Maps.toMap(roleIds, roleId -> Optional.ofNullable(rolePermissions.get(roleId))); + } + }); @Override public Map> list(ListRolePermissionParam param) { if (CollectionUtils.isEmpty(param.getRoleIds())) { return Collections.emptyMap(); } + Map> rolePermissions; + try { + rolePermissions = rolePermissionCache.getAll(param.getRoleIds()).entrySet() + .stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().orElseGet(Lists::newArrayList))); + } catch (ExecutionException ex) { + log.error("list role cache permission error:{} error", param.getRoleIds(), ex); + // 外面有做降级 + throw new ServiceException("查询角色权限缓存异常"); + } - Map> permissions = listRolePermissionCached(param); + if (CollectionUtils.isEmpty(param.getFeatureCodes())) { + return rolePermissions; + } - fillCacheRolePermissions(param, permissions); - return permissions; - } - - - private Map> listRolePermissionCached(ListRolePermissionParam param) { - - List redisValues = redisTemplate.executePipelined(new SessionCallback() { - @Override - public Object execute(RedisOperations operations) throws DataAccessException { - - for (Long roleId : param.getRoleIds()) { - String redisKey = getKey(roleId); - if (CollectionUtils.isEmpty(param.getFeatureCodes())) { - RedisClient.HashOps.hGetAll(redisKey); - } else { - RedisClient.HashOps.hMultiGet(redisKey, Lists.newArrayList(param.getFeatureCodes())); - } - - } - return null; - } - }); - - return Streams.zip(param.getRoleIds().stream(), - redisValues.stream(), - (roleId, redisValue) -> { - - if (Objects.isNull(redisValue)) { - return null; - } - - if (CollectionUtils.isEmpty(param.getFeatureCodes())) { - - List permissions = (List) ((Map) redisValue).values().stream() - .flatMap(e -> JSONArray.parseArray(JSONArray.toJSONString(e), PermissionDTO.class).stream()) - .collect(Collectors.toList()); - return Pair.of(roleId, permissions); - } - - List permissions = (List) ((List) redisValue).stream() - .filter(Objects::nonNull) - .flatMap(e -> JSONArray.parseArray((String) e, PermissionDTO.class).stream()) - .collect(Collectors.toList()); - return Pair.of(roleId, permissions); - - }) - .filter(Objects::nonNull) + return rolePermissions.entrySet() + .stream() + .map(e -> Pair.of(e.getKey(), e.getValue().stream() + .filter(permission -> param.getFeatureCodes().contains(permission.getFeatureCode())) + .collect(Collectors.toList())) + ) + .filter(e -> !CollectionUtils.isEmpty(e.getValue())) .collect(Collectors.toMap(Pair::getKey, Pair::getValue)); } @Override - public void store(StoreRolePermissionParam param) { - - Axssert.check(param.getRolePermissions().stream().allMatch(e -> Objects.nonNull(e.getRoleId())), REDIS_ROLE_NOT_NULL); - - redisTemplate.executePipelined((RedisCallback) connection -> { - - connection.openPipeline(); - - for (RolePermission rolePermission : param.getRolePermissions()) { - String redisKey = getKey(rolePermission.getRoleId()); - - Map redisValues = rolePermission.getPermissions().stream() - .collect(Collectors.groupingBy(PermissionDTO::getFeatureCode)) - .entrySet() - .stream() - .collect(Collectors.toMap(Map.Entry::getKey, e -> JSONObject.toJSONString(e.getValue()))); - - // 存在hash中部分key移除,为了处理快,直接把redisKey删除掉,修改不频繁 - redisTemplate.delete(redisKey); - RedisClient.HashOps.hPutAll(redisKey, redisValues); - redisTemplate.expire(redisKey, expireInMinutes, TimeUnit.MINUTES); - log.info("succeed to store role permission: redisKey:{} value:{}", redisKey, redisValues); - } - return null; - }); - } - - @Override - public List hasRoleIds(HasRolePermissionParam param) { - List redisValues = redisTemplate.executePipelined(new SessionCallback() { - @Override - public Object execute(RedisOperations operations) throws DataAccessException { - - for (Long roleId : param.getRoleIds()) { - String redisKey = getKey(roleId); - operations.hasKey(redisKey); - } - return null; - } - }); - - return Streams.zip(param.getRoleIds().stream(), - redisValues.stream(), - (roleId, redisValue) -> Pair.of(roleId, redisValue)) - .filter(e -> BooleanUtils.isTrue((Boolean) e.getValue())) - .map(Pair::getKey) - .collect(Collectors.toList()); - } - - /** - * 组装在缓存中没有查询到权限的角色权限 - * @param param - * @param permissionCached - */ - private void fillCacheRolePermissions(ListRolePermissionParam param, - Map> permissionCached) { - - Sets.SetView difference = Sets.difference(param.getRoleIds(), permissionCached.keySet()); - if (difference.isEmpty()) { + public void refreshCache(RefreshRolePermissionCacheParam param) { + if (CollectionUtils.isEmpty(param.getRoleIds())) { return; } + Map> rolePermissions = listRolePermission(Lists.newArrayList(param.getRoleIds())); + rolePermissionCache.putAll(Maps.toMap(param.getRoleIds(), roleId -> Optional.ofNullable(rolePermissions.get(roleId)))); + } + private Map> listRolePermission(List roleIds) { RoleService.ListSaasRoleParam listSaasRoleParam = RoleService.ListSaasRoleParam.builder() - .roleIds(Lists.newArrayList(difference)) + .roleIds(roleIds) .needPermissionRelation(true) .build(); List roles = roleService.list(listSaasRoleParam); if (CollectionUtils.isEmpty(roles)) { - return; + return Collections.emptyMap(); } - List rolePermissions = cacheRolePermissionHandler.resolveRolePermission(roles); - - if (CollectionUtils.isEmpty(rolePermissions)) { - return; - } - - StoreRolePermissionParam storeRolePermissionParam = StoreRolePermissionParam.builder() - .rolePermissions(rolePermissions) - .build(); - store(storeRolePermissionParam); - - Map> rolePermissionMap = rolePermissions.stream() - .collect(Collectors.toMap(RolePermission::getRoleId, RolePermission::getPermissions)); - permissionCached.putAll(rolePermissionMap); + return resolveRolePermission(roles).stream() + .collect(Collectors.toMap(RolePermissionCacheService.RolePermission::getRoleId, + RolePermissionCacheService.RolePermission::getPermissions)); } - private String getKey(Object... params) { - return String.format(ROLE_PERMISSION_KEY, params); + private List resolveRolePermission(List roles) { + + + Map featureResources = listSaasFeatureResource(roles); + + Map parentFeatureResources = listParentSaasFeatureResource(featureResources); + + Map saasFeatures = listSaasFeature(roles); + + Map parentSaasFeatures = listParentSaasFeature(saasFeatures); + + + return roles.stream() + .map(e -> { + if (CollectionUtils.isEmpty(e.getPermissionRelations())) { + return null; + } + + List permissions = e.getPermissionRelations().stream() + .distinct() + .map(permissionRelation -> { + if (Objects.equals(permissionRelation.getType(), NEW_FEATURE)) { + return resolveFeatureResourcePermission(permissionRelation, featureResources, parentFeatureResources); + } + return resolveFeaturePermission(permissionRelation, saasFeatures, parentSaasFeatures); + }) + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .distinct() + .collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(permissions)) { + return null; + } + + return RolePermissionCacheService.RolePermission.builder() + .roleId(e.getId()) + .permissions(permissions) + .build(); + + }) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } + + private static List resolveFeaturePermission(SaasPermissionRelationRes permissionRelation, Map saasFeatures, Map parentSaasFeatures) { + SaasFeature saasFeature = saasFeatures.get(permissionRelation.getFeatureId()); + if (Objects.isNull(saasFeature)) { + return null; + } + + List permissionDTOS = Lists.newArrayList(RolePermissionCacheService.PermissionDTO.builder() + .featureId(saasFeature.getId()) + .featureCode(saasFeature.getFeatureCode()) + .featureType(saasFeature.getFeatureType()) + .terminal(saasFeature.getTerminal()) + .build()); + + List parentPermissions = saasFeature.splitPath().stream() + .map(parentSaasFeatures::get) + .filter(Objects::nonNull) + .map(f -> RolePermissionCacheService.PermissionDTO.builder() + .featureId(f.getId()) + .featureCode(f.getFeatureCode()) + .featureType(f.getFeatureType()) + .terminal(f.getTerminal()) + .build()) + .collect(Collectors.toList()); + + permissionDTOS.addAll(parentPermissions); + return permissionDTOS; + } + + private static List resolveFeatureResourcePermission(SaasPermissionRelationRes permissionRelation, Map featureResources, Map parentFeatureResources) { + SaasFeatureResourceResp featureResource = featureResources.get(permissionRelation.getFeatureId()); + // 菜单节点是不会关联元素code,所以缓存的featureCode使用菜单编码 + if (Objects.isNull(featureResource)) { + return null; + } + + if (CollectionUtils.isEmpty(featureResource.getSaasPageElements())) { + return null; + } + + List permissionDTOS = featureResource.getSaasPageElements().stream() + .map(pageElement -> RolePermissionCacheService.PermissionDTO.builder() + .featureId(featureResource.getId()) + .featureCode(pageElement.getCode()) + .featureType(featureResource.getFeatureType()) + .terminal(featureResource.getTerminal()) + .build()) + .collect(Collectors.toList()); + + List parentPermissions = featureResource.resolvePath().stream() + .map(parentFeatureResources::get) + .filter(Objects::nonNull) + .map(f -> { + + if (CollectionUtils.isEmpty(featureResource.getSaasPageElements())) { + return null; + } + + return featureResource.getSaasPageElements().stream() + .map(pageElement -> RolePermissionCacheService.PermissionDTO.builder() + .featureId(f.getId()) + .featureCode(pageElement.getCode()) + .featureType(f.getFeatureType()) + .terminal(f.getTerminal()) + .build()) + .collect(Collectors.toList()); + }) + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .collect(Collectors.toList()); + + permissionDTOS.addAll(parentPermissions); + + return permissionDTOS; + } + + + private Map listSaasFeatureResource(List roles) { + + List featureIds = roles.stream() + .filter(e -> !CollectionUtils.isEmpty(e.getPermissionRelations())) + .map(SaasRoleRes::getPermissionRelations) + .flatMap(Collection::stream) + .filter(e -> Objects.equals(e.getType(), NEW_FEATURE)) + .map(SaasPermissionRelationRes::getFeatureId) + .distinct() + .collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(featureIds)) { + return Collections.emptyMap(); + } + + + PageSaasFeatureResourceReq pageSaasFeatureResourceReq = PageSaasFeatureResourceReq.builder() + .ids(featureIds) + .needPageElement(true) + .build(); + return saasFeatureResourceService.list(pageSaasFeatureResourceReq).stream() + .collect(Collectors.toMap(SaasFeatureResourceResp::getId, Function.identity(), (f, s) -> s)); + } + + private Map listParentSaasFeatureResource(Map productPermissions) { + + List parentIds = productPermissions.values().stream() + .map(SaasFeatureResourceResp::resolvePath) + .flatMap(Collection::stream) + .distinct() + .collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(parentIds)) { + return Collections.emptyMap(); + } + + // 存在pre环境更改了节点的父节点,可能导致产品没有父节点的权限,这里补齐父节点的权限 + PageSaasFeatureResourceReq pageSaasFeatureResourceReq = PageSaasFeatureResourceReq.builder() + .ids(parentIds) + .needPageElement(true) + .build(); + return saasFeatureResourceService.list(pageSaasFeatureResourceReq).stream() + .collect(Collectors.toMap(SaasFeatureResourceResp::getId, Function.identity(), (f, s) -> s)); + } + + private Map listSaasFeature(List roles) { + + Set featureIds = roles.stream() + .filter(e -> !CollectionUtils.isEmpty(e.getPermissionRelations())) + .map(SaasRoleRes::getPermissionRelations) + .flatMap(Collection::stream) + .filter(e -> Objects.equals(e.getType(), OLD_FEATURE)) + .map(SaasPermissionRelationRes::getFeatureId) + .collect(Collectors.toSet()); + + if (CollectionUtils.isEmpty(featureIds)) { + return Collections.emptyMap(); + } + + return saasFeatureDao.listByIds(featureIds) + .stream() + .collect(Collectors.toMap(SaasFeature::getId, Function.identity(), (f, s) -> s)); + } + + private Map listParentSaasFeature(Map saasFeatures) { + + if (CollectionUtils.isEmpty(saasFeatures)) { + return Collections.emptyMap(); + } + + List parentIds = saasFeatures.values().stream() + .map(SaasFeature::splitPath) + .flatMap(Collection::stream) + .distinct() + .collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(parentIds)) { + return Collections.emptyMap(); + } + + return saasFeatureDao.listByIds(parentIds).stream() + .collect(Collectors.toMap(SaasFeature::getId, Function.identity())); } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RoleSaasFeatureResourceCacheServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RoleSaasFeatureResourceCacheServiceImpl.java index f63f3e02..5a3e4a7c 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RoleSaasFeatureResourceCacheServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RoleSaasFeatureResourceCacheServiceImpl.java @@ -1,153 +1,127 @@ package cn.axzo.tyr.server.service.impl; -import cn.axzo.foundation.exception.Axssert; -import cn.axzo.pokonyan.config.redis.RedisClient; +import cn.axzo.basics.common.exception.ServiceException; import cn.axzo.tyr.client.common.enums.FeatureResourceType; +import cn.axzo.tyr.client.model.req.PageSaasFeatureResourceReq; +import cn.axzo.tyr.client.model.res.SaasFeatureResourceResp; +import cn.axzo.tyr.client.model.res.SaasPermissionRelationRes; import cn.axzo.tyr.client.model.res.SaasRoleRes; -import cn.axzo.tyr.server.event.inner.CacheRoleSaasFeatureResourceHandler; import cn.axzo.tyr.server.service.RoleSaasFeatureResourceCacheService; import cn.axzo.tyr.server.service.RoleService; +import cn.axzo.tyr.server.service.SaasFeatureResourceService; import cn.hutool.core.lang.Pair; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import com.google.common.collect.Streams; +import com.google.common.collect.Maps; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.dao.DataAccessException; -import org.springframework.data.redis.core.RedisCallback; -import org.springframework.data.redis.core.RedisOperations; -import org.springframework.data.redis.core.SessionCallback; -import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; +import java.util.function.Function; import java.util.stream.Collectors; -import static cn.axzo.tyr.server.config.exception.BizResultCode.REDIS_ROLE_NOT_NULL; import static cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation.NEW_FEATURE; +import static cn.axzo.tyr.server.service.impl.ProductSaasFeatureResourceCacheServiceImpl.FEATURE_RESOURCE_TYPES; @Slf4j @Service @RefreshScope public class RoleSaasFeatureResourceCacheServiceImpl implements RoleSaasFeatureResourceCacheService { - private static final String ROLE_SAAS_FEATURE_RESOURCE_KEY = "role:feature:resource:%s"; - - @Autowired - protected StringRedisTemplate redisTemplate; @Autowired private RoleService roleService; @Autowired - private CacheRoleSaasFeatureResourceHandler cacheRoleSaasFeatureResourceHandler; - + private SaasFeatureResourceService saasFeatureResourceService; /** 角色菜单缓存过期时间 **/ @Value("${role.feature.resource.expire.minutes:14}") private Long expireInMinutes; + private LoadingCache>> roleFeatureResourceCache = CacheBuilder.newBuilder() + .expireAfterWrite(14, TimeUnit.MINUTES) + .maximumSize(5000) + .build(new CacheLoader>>() { + @Override + public Optional> load(Long roleId) { + return listRoleFeatureResource(Lists.newArrayList(roleId)) + .values() + .stream() + .findFirst(); + } + + @Override + public Map>> loadAll(Iterable keys) throws Exception { + List roleIds = Lists.newArrayList(keys); + + Map> roleFeatureResources = listRoleFeatureResource(roleIds); + + return Maps.toMap(roleIds, roleId -> Optional.ofNullable(roleFeatureResources.get(roleId))); + } + }); + @Override public Map> list(ListRoleSaasFeatureResourceParam param) { if (CollectionUtils.isEmpty(param.getRoleIds())) { return Collections.emptyMap(); } - Map> featureResources = listRoleSaasFeatureResourceCached(param); + Map> roleFeatureResources; + try { + roleFeatureResources = roleFeatureResourceCache.getAll(param.getRoleIds()).entrySet() + .stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().orElseGet(Lists::newArrayList))); + } catch (ExecutionException ex) { + log.error("list role cache featureResource error:{} error", param.getRoleIds(), ex); + // 外面有做降级 + throw new ServiceException("查询角色菜单缓存异常"); + } - fillCacheRoleFeatureResources(param, featureResources); - return featureResources; - } + if (CollectionUtils.isEmpty(param.getUniCodes())) { + return roleFeatureResources; + } - @Override - public void store(StoreRoleSaasFeatureResourceParam param) { - Axssert.check(param.getRoleSaasFeatureResources().stream().allMatch(e -> Objects.nonNull(e.getRoleId())), REDIS_ROLE_NOT_NULL); - - redisTemplate.executePipelined((RedisCallback) connection -> { - - connection.openPipeline(); - - for (RoleFeatureResource roleFeatureResource : param.getRoleSaasFeatureResources()) { - String redisKey = getKey(roleFeatureResource.getRoleId()); - - Map redisValues = roleFeatureResource.getSaasFeatureResources().stream() - .collect(Collectors.groupingBy(SaasFeatureResourceDTO::getUniCode)) - .entrySet() - .stream() - .collect(Collectors.toMap(Map.Entry::getKey, e -> JSONObject.toJSONString(e.getValue()))); - - // 存在hash中部分key移除,为了处理快,直接把redisKey删除掉,修改不频繁 - redisTemplate.delete(redisKey); - RedisClient.HashOps.hPutAll(redisKey, redisValues); - redisTemplate.expire(redisKey, expireInMinutes, TimeUnit.MINUTES); - log.info("succeed to store role featureResource: redisKey:{} value:{}", redisKey, redisValues); - } - return null; - }); - } - - private Map> listRoleSaasFeatureResourceCached(ListRoleSaasFeatureResourceParam param) { - - List redisValues = redisTemplate.executePipelined(new SessionCallback() { - @Override - public Object execute(RedisOperations operations) throws DataAccessException { - - for (Long roleId : param.getRoleIds()) { - String redisKey = getKey(roleId); - if (CollectionUtils.isEmpty(param.getUniCodes())) { - RedisClient.HashOps.hGetAll(redisKey); - } else { - RedisClient.HashOps.hMultiGet(redisKey, Lists.newArrayList(param.getUniCodes())); - } - } - return null; - } - }); - - return Streams.zip(param.getRoleIds().stream(), - redisValues.stream(), - (roleId, redisValue) -> { - - if (Objects.isNull(redisValue)) { - return null; - } - - if (CollectionUtils.isEmpty(param.getUniCodes())) { - - List featureResources = (List) ((Map) redisValue).values().stream() - .flatMap(e -> JSONArray.parseArray(JSONArray.toJSONString(e), SaasFeatureResourceDTO.class).stream()) - .collect(Collectors.toList()); - return Pair.of(roleId, featureResources); - } - - List featureResources = (List) ((List) redisValue).stream() - .filter(Objects::nonNull) - .flatMap(e -> JSONArray.parseArray((String) e, SaasFeatureResourceDTO.class).stream()) - .collect(Collectors.toList()); - return Pair.of(roleId, featureResources); - - }) - .filter(Objects::nonNull) + return roleFeatureResources.entrySet() + .stream() + .map(e -> Pair.of(e.getKey(), e.getValue().stream() + .filter(permission -> param.getUniCodes().contains(permission.getUniCode())) + .collect(Collectors.toList())) + ) + .filter(e -> !CollectionUtils.isEmpty(e.getValue())) .collect(Collectors.toMap(Pair::getKey, Pair::getValue)); } - private void fillCacheRoleFeatureResources(ListRoleSaasFeatureResourceParam param, - Map> featureResources) { - - Sets.SetView difference = Sets.difference(param.getRoleIds(), featureResources.keySet()); - if (difference.isEmpty()) { + @Override + public void refreshCache(RefreshRoleFeatureResourceCacheParam param) { + if (CollectionUtils.isEmpty(param.getRoleIds())) { return; } + Map> roleFeatureResources = listRoleFeatureResource(Lists.newArrayList(param.getRoleIds())); + + roleFeatureResourceCache.putAll(Maps.toMap(param.getRoleIds(), roleId -> Optional.ofNullable(roleFeatureResources.get(roleId)))); + } + + private Map> listRoleFeatureResource(List roleIds) { + + if (CollectionUtils.isEmpty(roleIds)) { + return Collections.emptyMap(); + } RoleService.ListSaasRoleParam listSaasRoleParam = RoleService.ListSaasRoleParam.builder() - .roleIds(Lists.newArrayList(difference)) + .roleIds(roleIds) .needPermissionRelation(true) .type(NEW_FEATURE) .featureResourceTypes(Lists.newArrayList(FeatureResourceType.MENU, @@ -159,26 +133,122 @@ public class RoleSaasFeatureResourceCacheServiceImpl implements RoleSaasFeatureR List roles = roleService.list(listSaasRoleParam); if (CollectionUtils.isEmpty(roles)) { - return; + return Collections.emptyMap(); } - List roleFeatureResources = cacheRoleSaasFeatureResourceHandler.resolveRoleFeatureResource(roles); - - if (CollectionUtils.isEmpty(roleFeatureResources)) { - return; - } - - StoreRoleSaasFeatureResourceParam storeRolePermissionParam = StoreRoleSaasFeatureResourceParam.builder() - .roleSaasFeatureResources(roleFeatureResources) - .build(); - store(storeRolePermissionParam); - - Map> rolePermissionMap = roleFeatureResources.stream() + return resolveRoleFeatureResource(roles).stream() .collect(Collectors.toMap(RoleSaasFeatureResourceCacheService.RoleFeatureResource::getRoleId, RoleSaasFeatureResourceCacheService.RoleFeatureResource::getSaasFeatureResources)); - featureResources.putAll(rolePermissionMap); } - private String getKey(Object... params) { - return String.format(ROLE_SAAS_FEATURE_RESOURCE_KEY, params); + private List resolveRoleFeatureResource(List roles) { + + Map featureResources = listSaasFeatureResource(roles); + + Map parentFeatureResources = listParentSaasFeatureResource(featureResources); + + return roles.stream() + .map(e -> { + if (CollectionUtils.isEmpty(e.getPermissionRelations())) { + return null; + } + + List permissions = e.getPermissionRelations().stream() + .distinct() + .map(permissionRelation -> { + SaasFeatureResourceResp featureResource = featureResources.get(permissionRelation.getFeatureId()); + if (Objects.isNull(featureResource) || StringUtils.isBlank(featureResource.getUniCode())) { + return null; + } + + List featureResourceDTOS = Lists.newArrayList(RoleSaasFeatureResourceCacheService.SaasFeatureResourceDTO.builder() + .featureId(featureResource.getId()) + .featureType(featureResource.getFeatureType()) + .terminal(featureResource.getTerminal()) + .uniCode(featureResource.getUniCode()) + .build()); + List parentPermissions = featureResource.resolvePath().stream() + .map(parentFeatureResources::get) + .filter(Objects::nonNull) + .map(f -> { + + if (StringUtils.isBlank(f.getUniCode())) { + return null; + } + + return RoleSaasFeatureResourceCacheService.SaasFeatureResourceDTO.builder() + .featureId(f.getId()) + .featureType(f.getFeatureType()) + .terminal(f.getTerminal()) + .uniCode(f.getUniCode()) + .build(); + }) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + featureResourceDTOS.addAll(parentPermissions); + + return featureResourceDTOS; + }) + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .distinct() + .filter(f -> FEATURE_RESOURCE_TYPES.contains(f.getFeatureType())) + .collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(permissions)) { + return null; + } + + return RoleSaasFeatureResourceCacheService.RoleFeatureResource.builder() + .roleId(e.getId()) + .saasFeatureResources(permissions) + .build(); + + }) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } + + private Map listSaasFeatureResource(List roles) { + + List featureIds = roles.stream() + .filter(e -> !CollectionUtils.isEmpty(e.getPermissionRelations())) + .map(SaasRoleRes::getPermissionRelations) + .flatMap(Collection::stream) + .map(SaasPermissionRelationRes::getFeatureId) + .distinct() + .collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(featureIds)) { + return Collections.emptyMap(); + } + + // 存在pre环境更改了节点的父节点,可能导致产品没有父节点的权限,这里补齐父节点的权限 + PageSaasFeatureResourceReq pageSaasFeatureResourceReq = PageSaasFeatureResourceReq.builder() + .ids(featureIds) + .needFeatureCodes(true) + .build(); + return saasFeatureResourceService.list(pageSaasFeatureResourceReq).stream() + .collect(Collectors.toMap(SaasFeatureResourceResp::getId, Function.identity(), (f, s) -> s)); + } + + private Map listParentSaasFeatureResource(Map productPermissions) { + + List parentIds = productPermissions.values().stream() + .map(SaasFeatureResourceResp::resolvePath) + .flatMap(Collection::stream) + .distinct() + .collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(parentIds)) { + return Collections.emptyMap(); + } + + // 存在pre环境更改了节点的父节点,可能导致产品没有父节点的权限,这里补齐父节点的权限 + PageSaasFeatureResourceReq pageSaasFeatureResourceReq = PageSaasFeatureResourceReq.builder() + .ids(parentIds) + .needFeatureCodes(true) + .build(); + return saasFeatureResourceService.list(pageSaasFeatureResourceReq).stream() + .collect(Collectors.toMap(SaasFeatureResourceResp::getId, Function.identity(), (f, s) -> s)); } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceServiceImpl.java index 5f426559..5592923d 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceServiceImpl.java @@ -1,6 +1,7 @@ package cn.axzo.tyr.server.service.impl; import cn.axzo.basics.common.BeanMapper; +import cn.axzo.basics.common.exception.ServiceException; import cn.axzo.basics.common.util.StopWatchUtil; import cn.axzo.basics.common.util.TreeUtil; import cn.axzo.foundation.dao.support.converter.PageConverter; @@ -10,7 +11,6 @@ import cn.axzo.foundation.page.PageResp; import cn.axzo.framework.domain.web.code.BaseCode; import cn.axzo.framework.rocketmq.Event; import cn.axzo.pokonyan.config.mybatisplus.BaseEntity; -import cn.axzo.pokonyan.config.redis.RedisClient; import cn.axzo.tyr.client.common.enums.FeatureResourceAuthType; import cn.axzo.tyr.client.common.enums.FeatureResourceStatus; import cn.axzo.tyr.client.common.enums.FeatureResourceType; @@ -50,29 +50,24 @@ import cn.axzo.tyr.server.service.SaasPgroupPermissionRelationService; import cn.azxo.framework.common.utils.StringUtils; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.lang.Assert; -import cn.hutool.core.lang.Pair; import cn.hutool.core.util.ObjectUtil; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import com.google.common.collect.Sets; -import com.google.common.collect.Streams; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.BooleanUtils; import org.springframework.beans.BeanUtils; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.dao.DataAccessException; -import org.springframework.data.redis.core.RedisOperations; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.SessionCallback; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -82,7 +77,9 @@ import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Set; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.stream.Collectors; @@ -117,16 +114,35 @@ public class SaasFeatureResourceServiceImpl extends ServiceImpl redisTemplate; /** 菜单树过期时间 **/ @Value("${saas.feature.resource.expire.minutes:14}") private Long expireInMinutes; - private static final String SAAS_FEATURE_RESOURCE_KEY = "saas:feature:resource:%s"; - private static final String TARGET_TYPE = "saasFeatureResourceId"; + + private LoadingCache>> featureResourceCache = CacheBuilder.newBuilder() + .expireAfterWrite(14, TimeUnit.MINUTES) + .maximumSize(5000) + .build(new CacheLoader>>() { + @Override + public Optional> load(String terminal) { + return listFeatureSources(Lists.newArrayList(terminal)) + .values() + .stream() + .findFirst(); + } + + @Override + public Map>> loadAll(Iterable keys) throws Exception { + List terminals = Lists.newArrayList(keys); + + Map> featureResources = listFeatureSources(terminals); + + return Maps.toMap(terminals, terminal -> Optional.ofNullable(featureResources.get(terminal))); + } + }); + @Override public List listNavByIds(List featureIds, List featureTypes) { //按需扩展要查询的字段 @@ -791,85 +807,44 @@ public class SaasFeatureResourceServiceImpl extends ServiceImpl() { - @Override - public Object execute(RedisOperations operations) throws DataAccessException { - - for (SaasFeatureResourceDTO saasFeatureResource : param.getSaasFeatureResources()) { - String redisKey = getKey(saasFeatureResource.getTerminal()); - String redisValue = JSONObject.toJSONString(saasFeatureResource.getFeatures()); - RedisClient.StringOps.setEx(redisKey, redisValue, - expireInMinutes, TimeUnit.MINUTES); - log.info("succeed to store featureResource: redisKey:{} value:{}", redisKey, redisValue); - } - return null; - } - }); - } - @Override public Map> listCache(ListSaasFeatureResourceCache param) { if (org.springframework.util.CollectionUtils.isEmpty(param.getTerminals())) { return Collections.emptyMap(); } - Map> featureSourceCached = listFeatureSourceCached(param); - - fillCacheFeatureSources(param, featureSourceCached); - - return featureSourceCached; + Map> terminalFeatureResources; + try { + terminalFeatureResources = featureResourceCache.getAll(param.getTerminals()).entrySet() + .stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().orElseGet(Lists::newArrayList))); + } catch (ExecutionException ex) { + log.error("list terminal cache featureResource error:{} error", param.getTerminals(), ex); + // 外面有做降级 + throw new ServiceException("查询端的菜单缓存异常"); + } + return terminalFeatureResources; } - private Map> listFeatureSourceCached(ListSaasFeatureResourceCache param) { - - List redisValues = redisTemplate.executePipelined(new SessionCallback() { - @Override - public Object execute(RedisOperations operations) throws DataAccessException { - - for (String terminal : param.getTerminals()) { - String redisKey = getKey(terminal); - - RedisClient.StringOps.get(redisKey); - } - return null; - } - }); - - return Streams.zip(param.getTerminals().stream(), - redisValues.stream(), - (terminal, redisValue) -> { - - if (Objects.isNull(redisValue)) { - return null; - } - return Pair.of(terminal, JSONArray.parseArray((String) redisValue, - SaasFeatureResourceCache.class)); - }) - .filter(Objects::nonNull) - .collect(Collectors.toMap(Pair::getKey, Pair::getValue)); - } - - private void fillCacheFeatureSources(ListSaasFeatureResourceCache param, - Map> featureSourceCached) { - - Sets.SetView difference = Sets.difference(param.getTerminals(), featureSourceCached.keySet()); - if (difference.isEmpty()) { + @Override + public void refreshCache(RefreshFeatureResourceCacheParam param) { + if (org.springframework.util.CollectionUtils.isEmpty(param.getTerminals())) { return; } - List saasFeatureResources = resolveSaasFeature(difference); + Map> featureResources = listFeatureSources(Lists.newArrayList(param.getTerminals())); - SaasFeatureResourceService.StoreSaasFeatureResourceCache storeSaasFeatureResourceCache = SaasFeatureResourceService.StoreSaasFeatureResourceCache.builder() - .saasFeatureResources(saasFeatureResources) - .build(); - storeCache(storeSaasFeatureResourceCache); + featureResourceCache.putAll(Maps.toMap(param.getTerminals(), terminal -> Optional.ofNullable(featureResources.get(terminal)))); + } - Map> featureSourceMap = saasFeatureResources.stream() + private Map> listFeatureSources(List terminals) { + + if (CollectionUtils.isEmpty(terminals)) { + return Collections.emptyMap(); + } + + return resolveSaasFeature(Sets.newHashSet(terminals)).stream() .collect(Collectors.toMap(SaasFeatureResourceDTO::getTerminal, SaasFeatureResourceDTO::getFeatures)); - featureSourceCached.putAll(featureSourceMap); } private List resolveSaasFeature(Set terminals) { @@ -915,8 +890,4 @@ public class SaasFeatureResourceServiceImpl extends ServiceImpl Date: Wed, 11 Sep 2024 15:26:05 +0800 Subject: [PATCH 21/27] =?UTF-8?q?feat:(hotfix/20240906)=20=E5=8F=AA?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E6=99=AE=E9=80=9A=E8=A7=92=E8=89=B2=E4=BB=A5?= =?UTF-8?q?=E5=8F=8A=E7=BC=93=E5=AD=98=E6=9C=89=E6=95=88=E6=9C=9F=E6=94=B9?= =?UTF-8?q?=E6=88=901=E5=A4=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/axzo/tyr/client/common/enums/RoleTypeEnum.java | 7 +++++++ .../server/event/inner/CacheRolePermissionHandler.java | 6 +++++- .../event/inner/CacheRoleSaasFeatureResourceHandler.java | 3 +++ .../axzo/tyr/server/job/CacheRoleFeatureResourceJob.java | 2 ++ .../cn/axzo/tyr/server/job/CacheRolePermissionJob.java | 3 +++ .../main/java/cn/axzo/tyr/server/service/RoleService.java | 3 +++ .../service/impl/ProductPermissionCacheServiceImpl.java | 7 +------ .../impl/ProductSaasFeatureResourceCacheServiceImpl.java | 6 +----- .../service/impl/RolePermissionCacheServiceImpl.java | 7 +------ .../impl/RoleSaasFeatureResourceCacheServiceImpl.java | 6 +----- .../service/impl/SaasFeatureResourceServiceImpl.java | 8 +------- 11 files changed, 28 insertions(+), 30 deletions(-) diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/RoleTypeEnum.java b/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/RoleTypeEnum.java index c94a57f7..6b765e76 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/RoleTypeEnum.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/RoleTypeEnum.java @@ -5,6 +5,7 @@ import lombok.AllArgsConstructor; import lombok.Getter; import java.util.Arrays; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -56,4 +57,10 @@ public enum RoleTypeEnum { return Objects.equals(this.value, value); } + public static List listAdmin() { + return Arrays.stream(values()) + .filter(RoleTypeEnum::isAdminRole) + .map(RoleTypeEnum::getValue) + .collect(Collectors.toList()); + } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheRolePermissionHandler.java b/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheRolePermissionHandler.java index b0a66cc4..b048fdc7 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheRolePermissionHandler.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheRolePermissionHandler.java @@ -2,6 +2,7 @@ package cn.axzo.tyr.server.event.inner; import cn.axzo.framework.rocketmq.Event; import cn.axzo.framework.rocketmq.EventConsumer; +import cn.axzo.tyr.client.common.enums.RoleTypeEnum; import cn.axzo.tyr.client.model.res.SaasRoleRes; import cn.axzo.tyr.server.event.payload.PageElementFeatureResourceUpsertPayload; import cn.axzo.tyr.server.event.payload.RolePermissionCreatedPayload; @@ -47,6 +48,7 @@ public class CacheRolePermissionHandler implements InitializingBean { .roleIds(Optional.ofNullable(payload.getRoleIds()) .map(Lists::newArrayList) .orElse(null)) + .roleTypesNotIn(RoleTypeEnum.listAdmin()) .build(); Set roleIds = roleService.list(listSaasRoleParam).stream() .map(SaasRoleRes::getId) @@ -70,7 +72,9 @@ public class CacheRolePermissionHandler implements InitializingBean { return; } - RoleService.ListSaasRoleParam listSaasRoleParam = RoleService.ListSaasRoleParam.builder().build(); + RoleService.ListSaasRoleParam listSaasRoleParam = RoleService.ListSaasRoleParam.builder() + .roleTypesNotIn(RoleTypeEnum.listAdmin()) + .build(); Set roleIds = roleService.list(listSaasRoleParam).stream() .map(SaasRoleRes::getId) .collect(Collectors.toSet()); diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheRoleSaasFeatureResourceHandler.java b/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheRoleSaasFeatureResourceHandler.java index 93be689b..aec6cc72 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheRoleSaasFeatureResourceHandler.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheRoleSaasFeatureResourceHandler.java @@ -2,6 +2,7 @@ package cn.axzo.tyr.server.event.inner; import cn.axzo.framework.rocketmq.Event; import cn.axzo.framework.rocketmq.EventConsumer; +import cn.axzo.tyr.client.common.enums.RoleTypeEnum; import cn.axzo.tyr.client.model.res.SaasRoleRes; import cn.axzo.tyr.server.event.payload.PageElementFeatureResourceUpsertPayload; import cn.axzo.tyr.server.event.payload.RolePermissionCreatedPayload; @@ -48,6 +49,7 @@ public class CacheRoleSaasFeatureResourceHandler implements InitializingBean { .roleIds(Optional.ofNullable(payload.getRoleIds()) .map(Lists::newArrayList) .orElse(null)) + .roleTypesNotIn(RoleTypeEnum.listAdmin()) .build(); Set roleIds = roleService.list(listSaasRoleParam).stream() .map(SaasRoleRes::getId) @@ -72,6 +74,7 @@ public class CacheRoleSaasFeatureResourceHandler implements InitializingBean { } RoleService.ListSaasRoleParam listSaasRoleParam = RoleService.ListSaasRoleParam.builder() + .roleTypesNotIn(RoleTypeEnum.listAdmin()) .build(); Set roleIds = roleService.list(listSaasRoleParam).stream() diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheRoleFeatureResourceJob.java b/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheRoleFeatureResourceJob.java index 725bec72..698c947e 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheRoleFeatureResourceJob.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheRoleFeatureResourceJob.java @@ -1,5 +1,6 @@ package cn.axzo.tyr.server.job; +import cn.axzo.tyr.client.common.enums.RoleTypeEnum; import cn.axzo.tyr.client.model.res.SaasRoleRes; import cn.axzo.tyr.server.service.RoleSaasFeatureResourceCacheService; import cn.axzo.tyr.server.service.RoleService; @@ -33,6 +34,7 @@ public class CacheRoleFeatureResourceJob extends IJobHandler { RoleService.ListSaasRoleParam listSaasRoleParam = Optional.ofNullable(s) .map(e -> JSONObject.parseObject(e, RoleService.ListSaasRoleParam.class)) .orElseGet(() -> RoleService.ListSaasRoleParam.builder().build()); + listSaasRoleParam.setRoleTypesNotIn(RoleTypeEnum.listAdmin()); Set roleIds = roleService.list(listSaasRoleParam).stream() .map(SaasRoleRes::getId) diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheRolePermissionJob.java b/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheRolePermissionJob.java index d97fa08b..72b4faef 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheRolePermissionJob.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheRolePermissionJob.java @@ -1,5 +1,6 @@ package cn.axzo.tyr.server.job; +import cn.axzo.tyr.client.common.enums.RoleTypeEnum; import cn.axzo.tyr.client.model.res.SaasRoleRes; import cn.axzo.tyr.server.service.RolePermissionCacheService; import cn.axzo.tyr.server.service.RoleService; @@ -35,6 +36,8 @@ public class CacheRolePermissionJob extends IJobHandler { .map(e -> JSONObject.parseObject(e, RoleService.ListSaasRoleParam.class)) .orElseGet(() -> RoleService.ListSaasRoleParam.builder().build()); + listSaasRoleParam.setRoleTypesNotIn(RoleTypeEnum.listAdmin()); + Set roleIds = roleService.list(listSaasRoleParam).stream() .map(SaasRoleRes::getId) .collect(Collectors.toSet()); diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/RoleService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/RoleService.java index f8ca3353..2274e702 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/RoleService.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/RoleService.java @@ -136,6 +136,9 @@ public interface RoleService extends IService { @CriteriaField(field = "roleType", operator = Operator.IN) private List roleTypes; + @CriteriaField(field = "roleType", operator = Operator.NOT_IN) + private List roleTypesNotIn; + @CriteriaField(field = "id", operator = Operator.NE) private Long idNE; diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductPermissionCacheServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductPermissionCacheServiceImpl.java index 2c48a40b..710e7ee5 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductPermissionCacheServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductPermissionCacheServiceImpl.java @@ -19,7 +19,6 @@ import com.google.common.collect.Maps; import com.google.common.collect.Sets; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; @@ -51,12 +50,8 @@ public class ProductPermissionCacheServiceImpl implements ProductPermissionCache @Autowired private SaasFeatureDao saasFeatureDao; - /** 产品权限缓存过期时间 **/ - @Value("${product.permission.expire.minutes:14}") - private Long expireInMinutes; - private LoadingCache>> productPermissionCache = CacheBuilder.newBuilder() - .expireAfterWrite(14, TimeUnit.MINUTES) + .expireAfterWrite(1, TimeUnit.DAYS) .maximumSize(5000) .build(new CacheLoader>>() { @Override diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductSaasFeatureResourceCacheServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductSaasFeatureResourceCacheServiceImpl.java index 09eeb53f..79a8fa4d 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductSaasFeatureResourceCacheServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductSaasFeatureResourceCacheServiceImpl.java @@ -19,7 +19,6 @@ import com.google.common.collect.Sets; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; @@ -48,9 +47,6 @@ public class ProductSaasFeatureResourceCacheServiceImpl implements ProductSaasFe @Autowired private SaasFeatureResourceService saasFeatureResourceService; - @Value("${product.feature.resouce.expire.minutes:14}") - private Long expireInMinutes; - public static final Set FEATURE_RESOURCE_TYPES = Sets.newHashSet(FeatureResourceType.MENU.getCode(), FeatureResourceType.PAGE.getCode(), FeatureResourceType.MENU_PARTITION_GROUP.getCode(), @@ -58,7 +54,7 @@ public class ProductSaasFeatureResourceCacheServiceImpl implements ProductSaasFe FeatureResourceType.APP_ENTRY.getCode()); private LoadingCache>> productFeatureResourceCache = CacheBuilder.newBuilder() - .expireAfterWrite(14, TimeUnit.MINUTES) + .expireAfterWrite(1, TimeUnit.DAYS) .maximumSize(5000) .build(new CacheLoader>>() { @Override diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RolePermissionCacheServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RolePermissionCacheServiceImpl.java index 14eb0b7a..d819fdb7 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RolePermissionCacheServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RolePermissionCacheServiceImpl.java @@ -18,7 +18,6 @@ import com.google.common.collect.Lists; import com.google.common.collect.Maps; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; @@ -50,12 +49,8 @@ public class RolePermissionCacheServiceImpl implements RolePermissionCacheServic @Autowired private SaasFeatureDao saasFeatureDao; - /** 角色权限缓存过期时间 **/ - @Value("${role.permission.expire.minutes:14}") - private static Long expireInMinutes; - private LoadingCache>> rolePermissionCache = CacheBuilder.newBuilder() - .expireAfterWrite(14, TimeUnit.MINUTES) + .expireAfterWrite(1, TimeUnit.DAYS) .maximumSize(5000) .build(new CacheLoader>>() { @Override diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RoleSaasFeatureResourceCacheServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RoleSaasFeatureResourceCacheServiceImpl.java index 5a3e4a7c..f28d2523 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RoleSaasFeatureResourceCacheServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RoleSaasFeatureResourceCacheServiceImpl.java @@ -18,7 +18,6 @@ import com.google.common.collect.Maps; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; @@ -47,12 +46,9 @@ public class RoleSaasFeatureResourceCacheServiceImpl implements RoleSaasFeatureR @Autowired private SaasFeatureResourceService saasFeatureResourceService; - /** 角色菜单缓存过期时间 **/ - @Value("${role.feature.resource.expire.minutes:14}") - private Long expireInMinutes; private LoadingCache>> roleFeatureResourceCache = CacheBuilder.newBuilder() - .expireAfterWrite(14, TimeUnit.MINUTES) + .expireAfterWrite(1, TimeUnit.DAYS) .maximumSize(5000) .build(new CacheLoader>>() { @Override diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceServiceImpl.java index 5592923d..20cdf985 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceServiceImpl.java @@ -65,7 +65,6 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.BooleanUtils; import org.springframework.beans.BeanUtils; -import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.stereotype.Service; @@ -114,15 +113,10 @@ public class SaasFeatureResourceServiceImpl extends ServiceImpl>> featureResourceCache = CacheBuilder.newBuilder() - .expireAfterWrite(14, TimeUnit.MINUTES) + .expireAfterWrite(1, TimeUnit.DAYS) .maximumSize(5000) .build(new CacheLoader>>() { @Override From 602ac6561887edc9e7aa4097d46ed66cd9d79f8d Mon Sep 17 00:00:00 2001 From: lilong Date: Wed, 11 Sep 2024 18:24:36 +0800 Subject: [PATCH 22/27] =?UTF-8?q?feat:(hotfix/20240906)=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E8=8F=9C=E5=8D=95=E7=BC=93=E5=AD=98=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/PermissionQueryServiceImpl.java | 24 ++++++++++++------- .../impl/SaasFeatureResourceServiceImpl.java | 14 +++++++++++ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/PermissionQueryServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/PermissionQueryServiceImpl.java index 637e1011..39dc6c8e 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/PermissionQueryServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/PermissionQueryServiceImpl.java @@ -1002,13 +1002,16 @@ public class PermissionQueryServiceImpl implements PermissionQueryService { Set adminFeatureIds = resolveAdminRole(productFeatureSources, saasRole); Set notAuthFeatureIds = resolveNotAuthFeatureIds(productFeatureSources, authFreeFeatureIds); - List roleFeatureResources = roleFeatureResourceMap.get(saasRole.getId()).stream() - .filter(e -> StringUtils.isBlank(treePermissionReq.getTerminal()) - || Objects.equals(e.getTerminal(), treePermissionReq.getTerminal())) - .filter(e -> CollectionUtils.isEmpty(featureTypes) || featureTypes.contains(e.getFeatureType())) - .collect(Collectors.toList()); - Set normalFeatureIds = resolveNormalRole(productFeatureSources, saasRole, roleFeatureResources); + List roleFeatureResources = Optional.ofNullable(roleFeatureResourceMap.get(saasRole.getId())) + .map(role -> role.stream() + .filter(e -> StringUtils.isBlank(treePermissionReq.getTerminal()) + || Objects.equals(e.getTerminal(), treePermissionReq.getTerminal())) + .filter(e -> CollectionUtils.isEmpty(featureTypes) || featureTypes.contains(e.getFeatureType())) + .collect(Collectors.toList())) + .orElseGet(Lists::newArrayList); + + Set normalFeatureIds = resolveNormalRole(productFeatureSources, saasRole, roleFeatureResources, roleFeatureResourceMap); Set result = Sets.newHashSet(); result.addAll(adminFeatureIds); @@ -1038,8 +1041,13 @@ public class PermissionQueryServiceImpl implements PermissionQueryService { } private Set resolveNormalRole(List workspaceProduct, - SaasRoleUserV2DTO.SaasRole saasRole, - List roleFeatureResources) { + SaasRoleUserV2DTO.SaasRole saasRole, + List roleFeatureResources, + Map> roleFeatureResourceMap) { + + if (RoleTypeEnum.isAdmin(saasRole.getRoleType())) { + return Collections.emptySet(); + } if (CollectionUtils.isEmpty(roleFeatureResources)) { return Collections.emptySet(); diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceServiceImpl.java index 20cdf985..427ab713 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceServiceImpl.java @@ -114,6 +114,10 @@ public class SaasFeatureResourceServiceImpl extends ServiceImpl>> featureResourceCache = CacheBuilder.newBuilder() .expireAfterWrite(1, TimeUnit.DAYS) @@ -851,6 +855,7 @@ public class SaasFeatureResourceServiceImpl extends ServiceImpl allFeatureResources = Lists.newArrayList(); @@ -872,6 +877,15 @@ public class SaasFeatureResourceServiceImpl extends ServiceImpl pageElement.stream() + .findFirst() + .map(PageElementResp::getVersion) + .orElse(DEFAULT_VERSION)) + .orElse(DEFAULT_VERSION)) .build(), Collectors.toList()))) .entrySet().stream() .map(e -> SaasFeatureResourceDTO.builder() From b16da5cd22aef4e5e1a5a9ac0c14ac75e8124343 Mon Sep 17 00:00:00 2001 From: lilong Date: Wed, 11 Sep 2024 18:31:07 +0800 Subject: [PATCH 23/27] =?UTF-8?q?feat:(hotfix/20240906)=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E8=8F=9C=E5=8D=95=E7=BC=93=E5=AD=98=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/service/impl/PermissionQueryServiceImpl.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/PermissionQueryServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/PermissionQueryServiceImpl.java index 39dc6c8e..e8c34ff8 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/PermissionQueryServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/PermissionQueryServiceImpl.java @@ -1011,7 +1011,7 @@ public class PermissionQueryServiceImpl implements PermissionQueryService { .collect(Collectors.toList())) .orElseGet(Lists::newArrayList); - Set normalFeatureIds = resolveNormalRole(productFeatureSources, saasRole, roleFeatureResources, roleFeatureResourceMap); + Set normalFeatureIds = resolveNormalRole(productFeatureSources, saasRole, roleFeatureResources); Set result = Sets.newHashSet(); result.addAll(adminFeatureIds); @@ -1042,12 +1042,7 @@ public class PermissionQueryServiceImpl implements PermissionQueryService { private Set resolveNormalRole(List workspaceProduct, SaasRoleUserV2DTO.SaasRole saasRole, - List roleFeatureResources, - Map> roleFeatureResourceMap) { - - if (RoleTypeEnum.isAdmin(saasRole.getRoleType())) { - return Collections.emptySet(); - } + List roleFeatureResources) { if (CollectionUtils.isEmpty(roleFeatureResources)) { return Collections.emptySet(); From f4b99c62092a8009fb7dfb33066f44844ba95d1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Sat, 14 Sep 2024 13:12:12 +0800 Subject: [PATCH 24/27] =?UTF-8?q?feat(REQ-2899):pageV2=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tyr/server/service/impl/SaasPageElementServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java index 9a1f533c..b878eb24 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java @@ -511,7 +511,7 @@ public class SaasPageElementServiceImpl extends ServiceImpl w.like(SaasPageElement::getCode, request.getPageElementCodeOrName()) .or().like(SaasPageElement::getName, request.getPageElementCodeOrName())) - .eq(StringUtils.isNotBlank(request.getPageElementGroupCodeOrName()), SaasPageElement::getType, PageElementTypeEnum.PAGE.getCode()) +// .eq(StringUtils.isNotBlank(request.getPageElementGroupCodeOrName()), SaasPageElement::getType, PageElementTypeEnum.PAGE.getCode()) .and(StringUtils.isNotBlank(request.getPageElementGroupCodeOrName()), w -> w.like(SaasPageElement::getGroupCode, request.getPageElementGroupCodeOrName()) .or().like(SaasPageElement::getName, request.getPageElementGroupCodeOrName())) From a2069f8377706063c1315538f62ea42402aeb822 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=86=E9=B9=8F?= Date: Sat, 14 Sep 2024 13:36:56 +0800 Subject: [PATCH 25/27] =?UTF-8?q?feat(REQ-2899):pageV2=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tyr/server/service/impl/SaasPageElementServiceImpl.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java index b878eb24..3f6eaa60 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java @@ -80,9 +80,9 @@ public class SaasPageElementServiceImpl extends ServiceImpl w.like(SaasPageElement::getCode, request.getPageElementCodeOrName()) .or().like(SaasPageElement::getName, request.getPageElementCodeOrName())) -// .eq(StringUtils.isNotBlank(request.getPageElementGroupCodeOrName()), SaasPageElement::getType, PageElementTypeEnum.PAGE.getCode()) + .eq(StringUtils.isNotBlank(request.getPageElementGroupCodeOrName()), SaasPageElement::getType, PageElementTypeEnum.PAGE.getCode()) .and(StringUtils.isNotBlank(request.getPageElementGroupCodeOrName()), w -> w.like(SaasPageElement::getGroupCode, request.getPageElementGroupCodeOrName()) .or().like(SaasPageElement::getName, request.getPageElementGroupCodeOrName())) @@ -870,4 +870,5 @@ public class SaasPageElementServiceImpl extends ServiceImpl Date: Sat, 14 Sep 2024 14:01:52 +0800 Subject: [PATCH 26/27] =?UTF-8?q?feat(REQ-2899):=E5=85=B3=E7=B3=BB?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E8=B0=83=E6=95=B4=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/SaasPageElementServiceImpl.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java index 3f6eaa60..57d510e5 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java @@ -671,8 +671,18 @@ public class SaasPageElementServiceImpl extends ServiceImpl uniCodeRelationMap = relations.stream() - .collect(Collectors.toMap(SaasPageElementFeatureResourceRelation::getFeatureResourceUniCode, Function.identity(), (v1, v2) -> v1)); + Map uniCodeRelationMap = Maps.newHashMap(); + List pageRouteUniCodes = Lists.newArrayList(); + for(SaasPageElementFeatureResourceRelation relation : relations) { + if (pageRouteUniCodes.contains(relation.getFeatureResourceUniCode())) { + continue; + } + uniCodeRelationMap.put(relation.getFeatureResourceUniCode(), relation); + if (PageElementFeatureResourceRelationTypeEnum.PAGE_ROUTE.getValue().equals(relation.getType())) { + pageRouteUniCodes.add(relation.getFeatureResourceUniCode()); + } + } + List reps = allFeatureResources.stream().map(e -> PageElementRelationFeatureResourceResp.builder() .id(e.getId()) .parentId(e.getParentId()) From 92d0a627d25f47afd418d1e557fe1c4f68e4c474 Mon Sep 17 00:00:00 2001 From: lilong Date: Sat, 14 Sep 2024 14:32:53 +0800 Subject: [PATCH 27/27] =?UTF-8?q?feat:(feature/REQ-2899)=20=E8=A7=A3?= =?UTF-8?q?=E5=86=B3=E9=80=9A=E8=BF=87=E9=A1=B5=E9=9D=A2code=E6=88=96?= =?UTF-8?q?=E8=80=85name=E6=A8=A1=E7=B3=8A=E6=9F=A5=E8=AF=A2bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/req/PageQueryElementV2Req.java | 12 ++- .../impl/SaasPageElementServiceImpl.java | 73 ++++++++++++++++--- 2 files changed, 72 insertions(+), 13 deletions(-) diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PageQueryElementV2Req.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PageQueryElementV2Req.java index 47b9abab..2ae8ad4d 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PageQueryElementV2Req.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PageQueryElementV2Req.java @@ -1,11 +1,12 @@ package cn.axzo.tyr.client.model.req; +import cn.axzo.framework.domain.page.PageResp; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotBlank; +import java.util.Collections; import java.util.List; /** @@ -57,4 +58,13 @@ public class PageQueryElementV2Req { */ @Builder.Default private Long pageSize = 20L; + + public PageResp toEmpty() { + return PageResp.builder() + .page(this.getPage()) + .pageSize(this.getPageSize()) + .list(Collections.emptyList()) + .totalCount(0L) + .build(); + } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java index 57d510e5..b18a6b40 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasPageElementServiceImpl.java @@ -13,9 +13,32 @@ import cn.axzo.foundation.exception.BusinessException; import cn.axzo.framework.domain.page.PageResp; import cn.axzo.framework.rocketmq.Event; import cn.axzo.pokonyan.config.mybatisplus.BaseEntity; -import cn.axzo.tyr.client.common.enums.*; -import cn.axzo.tyr.client.model.req.*; -import cn.axzo.tyr.client.model.res.*; +import cn.axzo.tyr.client.common.enums.FeatureResourceType; +import cn.axzo.tyr.client.common.enums.PageElementAppTypeEnum; +import cn.axzo.tyr.client.common.enums.PageElementFeatureResourceRelationTypeEnum; +import cn.axzo.tyr.client.common.enums.PageElementTypeEnum; +import cn.axzo.tyr.client.common.enums.PermissionRelationOperateLogSceneEnum; +import cn.axzo.tyr.client.model.req.DeletePageElementReq; +import cn.axzo.tyr.client.model.req.GetPageElementReq; +import cn.axzo.tyr.client.model.req.GetUserHasPermissionPageElementReq; +import cn.axzo.tyr.client.model.req.IdentityAuthReq; +import cn.axzo.tyr.client.model.req.ModifyPageElementRelationDTO; +import cn.axzo.tyr.client.model.req.PageElementFeatureResourceRelationReq; +import cn.axzo.tyr.client.model.req.PageElementImportDataReq; +import cn.axzo.tyr.client.model.req.PageElementReportReq; +import cn.axzo.tyr.client.model.req.PageElementReq; +import cn.axzo.tyr.client.model.req.PageQueryElementReq; +import cn.axzo.tyr.client.model.req.PageQueryElementV2Req; +import cn.axzo.tyr.client.model.req.PageSaasFeatureResourceReq; +import cn.axzo.tyr.client.model.req.PermissionOperateLogReq; +import cn.axzo.tyr.client.model.req.SaveOrUpdatePageElementReq; +import cn.axzo.tyr.client.model.res.GetUserHasPermissionPageElementResp; +import cn.axzo.tyr.client.model.res.IdentityAuthRes; +import cn.axzo.tyr.client.model.res.PageElementBasicDTO; +import cn.axzo.tyr.client.model.res.PageElementCategoryAndElementResp; +import cn.axzo.tyr.client.model.res.PageElementRelationFeatureResourceResp; +import cn.axzo.tyr.client.model.res.PageElementResp; +import cn.axzo.tyr.client.model.res.SaasFeatureResourceResp; import cn.axzo.tyr.server.config.MqProducer; import cn.axzo.tyr.server.event.payload.PageElementFeatureResourceUpsertPayload; import cn.axzo.tyr.server.model.RelationOperateLogResourceBindElementDO; @@ -23,7 +46,11 @@ import cn.axzo.tyr.server.repository.dao.SaasFeatureResourceDao; import cn.axzo.tyr.server.repository.dao.SaasPageElementCategoryDao; import cn.axzo.tyr.server.repository.dao.SaasPageElementDao; import cn.axzo.tyr.server.repository.dao.SaasPageElementFeatureResourceRelationDao; -import cn.axzo.tyr.server.repository.entity.*; +import cn.axzo.tyr.server.repository.entity.SaasFeatureResource; +import cn.axzo.tyr.server.repository.entity.SaasPageElement; +import cn.axzo.tyr.server.repository.entity.SaasPageElementCategory; +import cn.axzo.tyr.server.repository.entity.SaasPageElementFeatureResourceRelation; +import cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelationOperateLog; import cn.axzo.tyr.server.repository.mapper.SaasPageElementMapper; import cn.axzo.tyr.server.service.SaasFeatureResourceService; import cn.axzo.tyr.server.service.SaasPageElementFeatureResourceRelationService; @@ -36,6 +63,7 @@ import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.google.common.base.Strings; @@ -56,7 +84,13 @@ import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.*; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.function.Function; @@ -504,19 +538,34 @@ public class SaasPageElementServiceImpl extends ServiceImpl pageV2(PageQueryElementV2Req request) { - IPage page = saasPageElementDao.lambdaQuery() + LambdaQueryChainWrapper wrapper = saasPageElementDao.lambdaQuery() .eq(Objects.nonNull(request.getId()), SaasPageElement::getId, request.getId()) .eq(StringUtils.isNotBlank(request.getTerminal()), SaasPageElement::getTerminal, request.getTerminal()) .eq(StringUtils.isNotBlank(request.getItemCode()), SaasPageElement::getItemCode, request.getItemCode()) .in(CollectionUtils.isNotEmpty(request.getElementTypes()), SaasPageElement::getType, request.getElementTypes()) .and(StringUtils.isNotBlank(request.getPageElementCodeOrName()), w -> w.like(SaasPageElement::getCode, request.getPageElementCodeOrName()) - .or().like(SaasPageElement::getName, request.getPageElementCodeOrName())) - .eq(StringUtils.isNotBlank(request.getPageElementGroupCodeOrName()), SaasPageElement::getType, PageElementTypeEnum.PAGE.getCode()) - .and(StringUtils.isNotBlank(request.getPageElementGroupCodeOrName()), - w -> w.like(SaasPageElement::getGroupCode, request.getPageElementGroupCodeOrName()) - .or().like(SaasPageElement::getName, request.getPageElementGroupCodeOrName())) - .orderByDesc(BaseEntity::getId) + .or().like(SaasPageElement::getName, request.getPageElementCodeOrName())); + + + // 待切换写法,收口page,pageV2查询 + // 因为页面名字没有每条记录冗余,查询条件可能是页面名字或者code,所以需要根据入参找到对应的页面code,然后作为页面code查询 + if (StringUtils.isNotBlank(request.getPageElementGroupCodeOrName())) { + List groupPageElements = saasPageElementDao.lambdaQuery() + .eq(SaasPageElement::getType, PageElementTypeEnum.PAGE.getCode()) + .and(w -> w.like(SaasPageElement::getGroupCode, request.getPageElementGroupCodeOrName()) + .or() + .like(SaasPageElement::getName, request.getPageElementGroupCodeOrName())) + .list(); + if (CollectionUtils.isEmpty(groupPageElements)) { + return request.toEmpty(); + } + + wrapper.in(SaasPageElement::getGroupCode, groupPageElements.stream().map(SaasPageElement::getGroupCode).collect(Collectors.toSet())); + } + + IPage page = wrapper.orderByDesc(BaseEntity::getId) .page(new Page<>(request.getPage(), request.getPageSize())); + List list = BeanMapper.copyList(page.getRecords(), PageElementResp.class); // 补充元素组名 fillGroupName(list);