feat: (feature/REQ-3167) 实现前端资源同步,新增资源管理批量upsert接口,重构原upsert接口

This commit is contained in:
李龙 2024-11-25 21:00:57 +08:00
parent 944c0d099b
commit 164ea1361a
25 changed files with 1210 additions and 285 deletions

View File

@ -2,8 +2,26 @@ 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.*;
import cn.axzo.tyr.client.model.req.DeletePageElementCategoryReq;
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.IdReq;
import cn.axzo.tyr.client.model.req.ModifyPageElementRelationDTO;
import cn.axzo.tyr.client.model.req.PageElementCategoryReq;
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.SaveOrUpdatePageElementCategoryReq;
import cn.axzo.tyr.client.model.req.SaveOrUpdatePageElementReq;
import cn.axzo.tyr.client.model.req.SyncPageElementReq;
import cn.axzo.tyr.client.model.res.GetUserHasPermissionPageElementResp;
import cn.axzo.tyr.client.model.res.ListPageElementCategoryResp;
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 org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@ -75,4 +93,12 @@ public interface PageElementApi {
/** 查询页面元素关联关系 **/
@PostMapping("/api/pageElement/importData")
ApiResult<Void> importData(@RequestBody @Valid List<PageElementImportDataReq> req);
/**
* 从基准环境把前端资源元素同步到当前环境
* @param req
* @return
*/
@PostMapping("/api/pageElement/sync")
ApiResult<Void> syncPageElement(@RequestBody @Valid SyncPageElementReq req);
}

View File

@ -0,0 +1,22 @@
package cn.axzo.tyr.client.feign;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.tyr.client.model.req.PageElementCategoryReq;
import cn.axzo.tyr.client.model.res.ListPageElementCategoryResp;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
@FeignClient(name = "tyr", url = "${axzo.service.tyr:http://tyr:8080}")
public interface PageElementCategoryApi {
/**
* 从基准环境查询分类信息
* @param req
* @return
*/
@PostMapping("/api/pageElementCategory/base/list")
ApiResult<List<ListPageElementCategoryResp>> listFromBase(@RequestBody PageElementCategoryReq req);
}

View File

@ -0,0 +1,44 @@
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 javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BatchUpsertPageElementCategoryReq {
@NotEmpty(message = "upsertPageElementCategories不能为空")
private List<UpsertPageElementCategory> upsertPageElementCategories;
@NotNull(message = "操作人不能为空")
private Long operatorId;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class UpsertPageElementCategory {
private Long id;
/** 项目编码 **/
private String itemCode;
/** 项目名称 **/
@NotBlank(message = "项目名称不能为空")
private String itemName;
/** 登录端 **/
@NotBlank(message = "所属端不能为空")
private String terminal;
}
}

View File

@ -0,0 +1,105 @@
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 javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BatchUpsertPageElementReq {
@NotEmpty(message = "upsertPageElementReqs不能为空")
private List<UpsertPageElementReq> upsertPageElementReqs;
@NotNull(message = "操作人不能为空")
private Long operatorId;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class UpsertPageElementReq {
private Long id;
/** 项目编码 **/
private String itemCode;
/** 分组ID **/
private String groupCode;
/** 页面元素类型PAGE/COMPONENT **/
@NotBlank(message = "页面元素类型不能为空")
private String type;
/** 项目编码 **/
@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;
/**
* 已经作废不能再使用现在分iosandroid的版本号
*/
@Deprecated
private Integer version;
/** 操作人personId **/
private Long operatorId;
/**
* ios 最低版本要求
*/
private Integer iosMinVersion;
/**
* ios 最高版本要求
*/
private Integer iosMaxVersion;
/**
* ios 是否开启最高版本要求:true-开启false-关闭
*/
private Boolean iosMaxVersionEnabled;
/**
* android 最低版本要求
*/
private Integer androidMinVersion;
/**
* android 最高版本要求
*/
private Integer androidMaxVersion;
/**
* android 是否开启最高版本要求:true-开启false-关闭
*/
private Boolean androidMaxVersionEnabled;
}
}

View File

@ -41,4 +41,13 @@ public class PageElementReq implements IPageReq {
@CriteriaField(field = "type", operator = Operator.IN)
private Set<PageElementTypeEnum> types;
@CriteriaField(field = "id", operator = Operator.IN)
private Set<Long> ids;
@CriteriaField(ignore = true)
private Boolean needChildren;
@CriteriaField(ignore = true)
private Boolean needPageElementCategory;
}

View File

@ -0,0 +1,26 @@
package cn.axzo.tyr.client.model.req;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Set;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SyncPageElementReq {
/**
* 分组下类型是PAGE的pageElement记录id同步时会把PAGE下的COMPONENT信息也一起同步
*/
@NotEmpty(message = "资源页面元素id不能为空")
private Set<Long> pageElementIds;
@NotNull(message = "操作人不能为空")
private Long operatorId;
}

View File

@ -0,0 +1,48 @@
package cn.axzo.tyr.client.model.res;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PageElementCategoryResp {
private Long id;
private Date createAt;
private Date updateAt;
private Long isDelete;
/**
* 创建人
*/
private Long createBy;
/**
* 更新人
*/
private Long updateBy;
/**
* 项目codeH5会拉取项目下所有的元素
*/
private String itemCode;
/**
* 项目名称
*/
private String itemName;
/**
* 所属端
*/
private String terminal;
}

View File

@ -127,6 +127,11 @@ public class PageElementResp {
*/
private Boolean androidMaxVersionEnabled;
/**
* 所属的itemCode的分类
*/
private PageElementCategoryResp pageElementCategory;
@Data
@Builder
@NoArgsConstructor

View File

@ -17,10 +17,17 @@ public enum BizResultCode implements IResultCode {
REMOVE_USER_ROLE_ERROR("100007", "删除用户角色数据异常"),
DATA_ERROR("100008", "数据异常"),
FEATURE_CODE_EXIST("100009", "featureCode已经存在"),
PAGE_ELEMENT_ITEM_CODE_NOT_FOUND("100010", "页面元素不存在"),
PAGE_ELEMENT_ITEM_CODE_NOT_NULL("100011", "项目编码不能为空"),
PAGE_ELEMENT_ITEM_CODE_NOT_FOUND("100010", "资源分组不存在:{}"),
PAGE_ELEMENT_ITEM_CODE_NOT_NULL("100011", "资源分组数据不存在"),
PAGE_ELEMENT_GROUP_CODE_NOT_NULL("100012", "分组编码不能为空"),
PAGE_ELEMENT_GROUP_CODE_NOT_FOUND("100013", "页面元素不存在");
PAGE_ELEMENT_GROUP_CODE_NOT_FOUND("100013", "页面元素不存在:{}"),
ITEM_NAME_DUPLICATE("100014", "资源分组名字重复,重复的名字:{}"),
ITEM_CODE_DUPLICATE("100015", "资源分组code重复,重复的code:{}"),
PAGE_ELEMENT_CATEGORY_NOT_FOUND("100016", "资源分组数据不存在"),
PAGE_ELEMENT_ERROR("100017", "资源分组错误:{}"),
PAGE_CODE_DUPLICATE("100018", "资源元素code重复,重复的code:{}"),
PARAM_ERROR("100019", "参数错误");
private String errorCode;
private String errorMessage;

View File

@ -0,0 +1,28 @@
package cn.axzo.tyr.server.controller.permission;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.tyr.client.feign.PageElementCategoryApi;
import cn.axzo.tyr.client.model.req.PageElementCategoryReq;
import cn.axzo.tyr.client.model.res.ListPageElementCategoryResp;
import cn.axzo.tyr.server.inner.feign.BasePageElementCategoryApi;
import cn.axzo.tyr.server.util.RpcInternalUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Slf4j
@RestController
public class PageElementCategoryController implements PageElementCategoryApi {
@Autowired
private BasePageElementCategoryApi basePageElementCategoryApi;
@Override
public ApiResult<List<ListPageElementCategoryResp>> listFromBase(PageElementCategoryReq req) {
return RpcInternalUtil.rpcProcessor(() -> basePageElementCategoryApi.listPageElementCategory(req),
"list pageElementCategory from base env", req);
}
}

View File

@ -17,6 +17,7 @@ import cn.axzo.tyr.client.model.req.PageQueryElementReq;
import cn.axzo.tyr.client.model.req.PageQueryElementV2Req;
import cn.axzo.tyr.client.model.req.SaveOrUpdatePageElementCategoryReq;
import cn.axzo.tyr.client.model.req.SaveOrUpdatePageElementReq;
import cn.axzo.tyr.client.model.req.SyncPageElementReq;
import cn.axzo.tyr.client.model.res.GetUserHasPermissionPageElementResp;
import cn.axzo.tyr.client.model.res.ListPageElementCategoryResp;
import cn.axzo.tyr.client.model.res.PageElementCategoryAndElementResp;
@ -118,4 +119,10 @@ public class PageElementController implements PageElementApi {
saasPageElementService.importData(req);
return ApiResult.ok();
}
@Override
public ApiResult<Void> syncPageElement(SyncPageElementReq req) {
saasPageElementService.syncPageElement(req);
return ApiResult.ok();
}
}

View File

@ -0,0 +1,16 @@
package cn.axzo.tyr.server.inner.feign;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.tyr.client.model.req.PageElementReq;
import cn.axzo.tyr.client.model.res.PageElementResp;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import java.util.List;
@FeignClient(name = "tyr", url = "${axzo.service.base.tyr:https://pre-api.axzo.cn/tyr}")
public interface BasePageElementApi {
@PostMapping("/api/pageElement/list")
ApiResult<List<PageElementResp>> list(PageElementReq param);
}

View File

@ -0,0 +1,18 @@
package cn.axzo.tyr.server.inner.feign;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.tyr.client.model.req.PageElementCategoryReq;
import cn.axzo.tyr.client.model.res.ListPageElementCategoryResp;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
@FeignClient(name = "tyr", url = "${axzo.service.base.tyr:https://pre-api.axzo.cn/tyr}")
public interface BasePageElementCategoryApi {
/** 查询页面元素类型(按端分组) **/
@PostMapping("/api/pageElementCategory/list")
ApiResult<List<ListPageElementCategoryResp>> listPageElementCategory(@RequestBody PageElementCategoryReq req);
}

View File

@ -71,14 +71,4 @@ public class SaasPageElementDao extends ServiceImpl<SaasPageElementMapper, SaasP
.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();
}
}

View File

@ -40,6 +40,8 @@ public class SaasPageElement extends BaseEntity<SaasPageElement> {
/**
* 元素的组编码
* type = PAGE时code跟groupCode一样
* type = COMPONENT时groupCode是对应 type = PAGE的code
*/
@TableField("group_code")
private String groupCode;
@ -100,6 +102,7 @@ public class SaasPageElement extends BaseEntity<SaasPageElement> {
/**
* 项目名称
*/
@Deprecated
@TableField("item_name")
private String itemName;

View File

@ -1,9 +1,14 @@
package cn.axzo.tyr.server.service;
import cn.axzo.foundation.page.PageResp;
import cn.axzo.tyr.client.model.req.BatchUpsertPageElementCategoryReq;
import cn.axzo.tyr.client.model.req.DeletePageElementCategoryReq;
import cn.axzo.tyr.client.model.req.PageElementCategoryReq;
import cn.axzo.tyr.client.model.req.PageElementReq;
import cn.axzo.tyr.client.model.req.SaveOrUpdatePageElementCategoryReq;
import cn.axzo.tyr.client.model.res.ListPageElementCategoryResp;
import cn.axzo.tyr.server.repository.entity.SaasPageElementCategory;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
@ -12,11 +17,13 @@ import java.util.List;
* @version 1.0
* @date 2024/8/20
*/
public interface SaasPageElementCategoryService {
public interface SaasPageElementCategoryService extends IService<SaasPageElementCategory> {
List<ListPageElementCategoryResp> listGroupByTerminal(PageElementCategoryReq req);
Long saveOrUpdate(SaveOrUpdatePageElementCategoryReq req);
void delete(DeletePageElementCategoryReq req);
void batchUpsert(BatchUpsertPageElementCategoryReq req);
}

View File

@ -92,4 +92,8 @@ public interface SaasPageElementService extends IService<SaasPageElement> {
List<PageElementRelationFeatureResourceResp> getFeatureResourceRelations(Long pageElementId);
void importData(List<PageElementImportDataReq> req);
void syncPageElement(SyncPageElementReq req);
List<Long> batchUpsert(BatchUpsertPageElementReq req);
}

View File

@ -2,10 +2,12 @@ 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.foundation.exception.Axssert;
import cn.axzo.framework.rocketmq.Event;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import cn.axzo.tyr.client.common.enums.PageElementTypeEnum;
import cn.axzo.tyr.client.common.enums.PermissionRelationOperateLogSceneEnum;
import cn.axzo.tyr.client.model.req.BatchUpsertPageElementCategoryReq;
import cn.axzo.tyr.client.model.req.DeletePageElementCategoryReq;
import cn.axzo.tyr.client.model.req.PageElementCategoryReq;
import cn.axzo.tyr.client.model.req.PageElementReq;
@ -20,9 +22,12 @@ 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.repository.mapper.SaasPageElementCategoryMapper;
import cn.axzo.tyr.server.service.SaasPageElementCategoryService;
import cn.axzo.tyr.server.service.SaasPageElementService;
import cn.axzo.tyr.server.service.SaasPgroupPermissionRelationOperateLogService;
import com.alibaba.nacos.common.utils.UuidUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Sets;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -36,8 +41,12 @@ 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.config.exception.BizResultCode.ITEM_CODE_DUPLICATE;
import static cn.axzo.tyr.server.config.exception.BizResultCode.ITEM_NAME_DUPLICATE;
import static cn.axzo.tyr.server.config.exception.BizResultCode.PAGE_ELEMENT_CATEGORY_NOT_FOUND;
import static cn.axzo.tyr.server.event.inner.EventTypeEnum.PAGE_ELEMENT_FEATURE_RESOURCE_UPSERT;
/**
@ -48,7 +57,8 @@ import static cn.axzo.tyr.server.event.inner.EventTypeEnum.PAGE_ELEMENT_FEATURE_
@Slf4j
@Service
@AllArgsConstructor
public class SaasPageElementCategoryServiceImpl implements SaasPageElementCategoryService {
public class SaasPageElementCategoryServiceImpl extends ServiceImpl<SaasPageElementCategoryMapper, SaasPageElementCategory>
implements SaasPageElementCategoryService {
public static final String PAGE_ELEMENT_CATEGORY_TABLE_NAME = "saas_page_element_category";
private static final String TARGET_TYPE = "pageElementFeatureResourceId";
@ -156,6 +166,147 @@ public class SaasPageElementCategoryServiceImpl implements SaasPageElementCatego
return baseCategory.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void batchUpsert(BatchUpsertPageElementCategoryReq req) {
check(req);
List<SaasPageElementCategory> saasPageElementCategories = req.getUpsertPageElementCategories().stream()
.map(e -> {
SaasPageElementCategory saasPageElementCategory = SaasPageElementCategory.builder()
.itemCode(e.getItemCode())
.itemName(e.getItemName())
.terminal(e.getTerminal())
.createBy(Objects.nonNull(e.getId()) ? null : req.getOperatorId())
.updateBy(req.getOperatorId())
.build();
saasPageElementCategory.setId(e.getId());
return saasPageElementCategory;
})
.collect(Collectors.toList());
saasPageElementCategoryDao.updateBatchById(saasPageElementCategories);
try {
saveOrUpdateOperateLog(req, saasPageElementCategories);
} catch (Exception e) {
log.warn("save operate log error", e);
}
}
private void checkItemName(BatchUpsertPageElementCategoryReq req) {
// check入参中重复的名字
Set<String> duplicateItemNames = req.getUpsertPageElementCategories().stream()
.collect(Collectors.groupingBy(BatchUpsertPageElementCategoryReq.UpsertPageElementCategory::getItemName))
.entrySet()
.stream()
.filter(e -> e.getValue().size() > 1)
.map(Map.Entry::getKey)
.collect(Collectors.toSet());
Axssert.check(CollectionUtils.isEmpty(duplicateItemNames), ITEM_NAME_DUPLICATE,
ITEM_NAME_DUPLICATE.getErrorMessage(), duplicateItemNames);
// check新增或者更新的itemName是否已经存在
List<String> itemNames = req.getUpsertPageElementCategories().stream()
.map(BatchUpsertPageElementCategoryReq.UpsertPageElementCategory::getItemName)
.collect(Collectors.toList());
List<SaasPageElementCategory> saasPageElementCategories = this.lambdaQuery()
.in(SaasPageElementCategory::getItemName, itemNames)
.eq(SaasPageElementCategory::getIsDelete, DeleteEnum.NORMAL.value)
.list();
if (CollectionUtils.isEmpty(saasPageElementCategories)) {
return;
}
Map<String, SaasPageElementCategory> itemNameMap = saasPageElementCategories.stream()
.collect(Collectors.toMap(SaasPageElementCategory::getItemName, Function.identity()));
List<String> dbDuplicateItemNames = req.getUpsertPageElementCategories().stream()
.filter(e -> {
SaasPageElementCategory oldSaasPageElementCategory = itemNameMap.get(e.getItemName());
if (Objects.isNull(oldSaasPageElementCategory)) {
return false;
}
// 新增里重复的itemName
if (Objects.isNull(e.getId())) {
return true;
}
// 更新里重复的itemName
return !Objects.equals(e.getId(), oldSaasPageElementCategory.getId());
})
.map(BatchUpsertPageElementCategoryReq.UpsertPageElementCategory::getItemName)
.collect(Collectors.toList());
Axssert.check(CollectionUtils.isEmpty(dbDuplicateItemNames), ITEM_NAME_DUPLICATE,
ITEM_NAME_DUPLICATE.getErrorMessage(), dbDuplicateItemNames);
}
private void checkItemCode(BatchUpsertPageElementCategoryReq req) {
// check入参中重复的ItemCode
Set<String> duplicateItemCodes = req.getUpsertPageElementCategories().stream()
.collect(Collectors.groupingBy(BatchUpsertPageElementCategoryReq.UpsertPageElementCategory::getItemCode))
.entrySet()
.stream()
.filter(e -> e.getValue().size() > 1)
.map(Map.Entry::getKey)
.collect(Collectors.toSet());
Axssert.check(CollectionUtils.isEmpty(duplicateItemCodes), ITEM_CODE_DUPLICATE,
ITEM_CODE_DUPLICATE.getErrorMessage(), duplicateItemCodes);
// check新增或者更新的itemCode是否已经存在
List<String> itemCodes = req.getUpsertPageElementCategories().stream()
.map(BatchUpsertPageElementCategoryReq.UpsertPageElementCategory::getItemCode)
.collect(Collectors.toList());
List<SaasPageElementCategory> saasPageElementCategories = this.lambdaQuery()
.in(SaasPageElementCategory::getItemCode, itemCodes)
.eq(SaasPageElementCategory::getIsDelete, DeleteEnum.NORMAL.value)
.list();
if (CollectionUtils.isEmpty(saasPageElementCategories)) {
return;
}
Map<String, SaasPageElementCategory> itemCodeMap = saasPageElementCategories.stream()
.collect(Collectors.toMap(SaasPageElementCategory::getItemCode, Function.identity()));
List<String> dbDuplicateItemCodes = req.getUpsertPageElementCategories().stream()
.filter(e -> {
SaasPageElementCategory oldSaasPageElementCategory = itemCodeMap.get(e.getItemName());
if (Objects.isNull(oldSaasPageElementCategory)) {
return false;
}
// 新增里重复的itemName
if (Objects.isNull(e.getId())) {
return true;
}
// 更新里重复的itemName
return !Objects.equals(e.getId(), oldSaasPageElementCategory.getId());
})
.map(BatchUpsertPageElementCategoryReq.UpsertPageElementCategory::getItemCode)
.collect(Collectors.toList());
Axssert.check(CollectionUtils.isEmpty(dbDuplicateItemCodes), ITEM_CODE_DUPLICATE,
ITEM_CODE_DUPLICATE.getErrorMessage(), dbDuplicateItemCodes);
}
private void check(BatchUpsertPageElementCategoryReq req) {
checkItemName(req);
checkItemCode(req);
List<Long> ids = req.getUpsertPageElementCategories().stream()
.map(BatchUpsertPageElementCategoryReq.UpsertPageElementCategory::getId)
.filter(Objects::nonNull)
.collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(ids)) {
List<SaasPageElementCategory> saasPageElementCategories = saasPageElementCategoryDao.listByIds(ids);
Axssert.check(ids.size() == saasPageElementCategories.size(), PAGE_ELEMENT_CATEGORY_NOT_FOUND);
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void delete(DeletePageElementCategoryReq req) {
@ -223,6 +374,20 @@ public class SaasPageElementCategoryServiceImpl implements SaasPageElementCatego
.build());
}
private void saveOrUpdateOperateLog(BatchUpsertPageElementCategoryReq req,
List<SaasPageElementCategory> saasPageElementCategories) {
saasPgroupPermissionRelationOperateLogService.save(PermissionOperateLogReq.builder()
.tableName(PAGE_ELEMENT_CATEGORY_TABLE_NAME)
.operatorId(req.getOperatorId())
.scene(PermissionRelationOperateLogSceneEnum.OMS_UPSERT_PAGE_ELEMENT_CATEGORY.getValue())
// 批量更新记录id会超长后续提供统一的更基础的日志记录表先暂时用
.sceneId(UuidUtils.generateUuid())
.requestData(req)
.operateData(saasPageElementCategories)
.build());
}
private void saveDeleteOperateLog(DeletePageElementCategoryReq req, SaasPageElementCategory baseCategory) {
saasPgroupPermissionRelationOperateLogService.save(PermissionOperateLogReq.builder()
.tableName(PAGE_ELEMENT_CATEGORY_TABLE_NAME)

View File

@ -19,6 +19,8 @@ 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.BatchUpsertPageElementCategoryReq;
import cn.axzo.tyr.client.model.req.BatchUpsertPageElementReq;
import cn.axzo.tyr.client.model.req.DeletePageElementReq;
import cn.axzo.tyr.client.model.req.GetPageElementReq;
import cn.axzo.tyr.client.model.req.GetUserHasPermissionPageElementReq;
@ -33,15 +35,18 @@ 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.req.SyncPageElementReq;
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.PageElementCategoryResp;
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.inner.feign.BasePageElementApi;
import cn.axzo.tyr.server.model.RelationOperateLogResourceBindElementDO;
import cn.axzo.tyr.server.repository.dao.SaasFeatureResourceDao;
import cn.axzo.tyr.server.repository.dao.SaasPageElementCategoryDao;
@ -54,6 +59,7 @@ import cn.axzo.tyr.server.repository.entity.SaasPageElementFeatureResourceRelati
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.SaasPageElementCategoryService;
import cn.axzo.tyr.server.service.SaasPageElementFeatureResourceRelationService;
import cn.axzo.tyr.server.service.SaasPageElementService;
import cn.axzo.tyr.server.service.SaasPgroupPermissionRelationOperateLogService;
@ -62,6 +68,7 @@ import cn.axzo.tyr.server.util.RpcInternalUtil;
import cn.azxo.framework.common.constatns.Constants;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.common.utils.UuidUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
@ -82,10 +89,12 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.util.Pair;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@ -97,10 +106,13 @@ import java.util.concurrent.ExecutorService;
import java.util.function.Function;
import java.util.stream.Collectors;
import static cn.axzo.tyr.server.config.exception.BizResultCode.PAGE_CODE_DUPLICATE;
import static cn.axzo.tyr.server.config.exception.BizResultCode.PAGE_ELEMENT_ERROR;
import static cn.axzo.tyr.server.config.exception.BizResultCode.PAGE_ELEMENT_GROUP_CODE_NOT_FOUND;
import static cn.axzo.tyr.server.config.exception.BizResultCode.PAGE_ELEMENT_GROUP_CODE_NOT_NULL;
import static cn.axzo.tyr.server.config.exception.BizResultCode.PAGE_ELEMENT_ITEM_CODE_NOT_FOUND;
import static cn.axzo.tyr.server.config.exception.BizResultCode.PAGE_ELEMENT_ITEM_CODE_NOT_NULL;
import static cn.axzo.tyr.server.config.exception.BizResultCode.PARAM_ERROR;
import static cn.axzo.tyr.server.event.inner.EventTypeEnum.PAGE_ELEMENT_FEATURE_RESOURCE_UPSERT;
/**
@ -125,6 +137,8 @@ public class SaasPageElementServiceImpl extends ServiceImpl<SaasPageElementMappe
private final SaasFeatureResourceService saasFeatureResourceService;
private final SaasPageElementFeatureResourceRelationService saasPageElementFeatureResourceRelationService;
private final SaasPageElementCategoryDao saasPageElementCategoryDao;
private final BasePageElementApi basePageElementApi;
private final SaasPageElementCategoryService saasPageElementCategoryService;
@Qualifier("asyncExecutor")
@Autowired
@ -544,7 +558,11 @@ public class SaasPageElementServiceImpl extends ServiceImpl<SaasPageElementMappe
Map<String, List<SaasFeatureResourceResp>> featureResources = listFeatureResource(page.getRecords(), param);
return PageConverter.toResp(page, e -> from(e, featureResources));
Map<String, List<PageElementResp>> childrenPageElements = listChildrenPageElement(page.getRecords(), param);
Map<String, PageElementCategoryResp> pageElementCategories = listPageElementCategory(page.getRecords(), param);
return PageConverter.toResp(page, e -> from(e, featureResources, childrenPageElements, pageElementCategories));
}
@Override
@ -618,6 +636,37 @@ public class SaasPageElementServiceImpl extends ServiceImpl<SaasPageElementMappe
return result;
}
private SaasPageElement.Ext resolveExt(BatchUpsertPageElementReq.UpsertPageElementReq req) {
List<SaasPageElement.Application> applications = Lists.newArrayList();
if (Objects.nonNull(req.getIosMinVersion())
|| Objects.nonNull(req.getIosMaxVersion())
|| Objects.nonNull(req.getIosMaxVersionEnabled())) {
SaasPageElement.Application application = SaasPageElement.Application.builder()
.type(SaasPageElement.ApplicationTypeEnum.IOS)
.minVersion(req.getIosMinVersion())
.maxVersion(req.getIosMaxVersion())
.maxVersionEnabled(req.getIosMaxVersionEnabled())
.build();
applications.add(application);
}
if (Objects.nonNull(req.getAndroidMaxVersion())
|| Objects.nonNull(req.getAndroidMinVersion())
|| Objects.nonNull(req.getAndroidMaxVersionEnabled())) {
SaasPageElement.Application application = SaasPageElement.Application.builder()
.type(SaasPageElement.ApplicationTypeEnum.ANDROID)
.minVersion(req.getAndroidMinVersion())
.maxVersion(req.getAndroidMaxVersion())
.maxVersionEnabled(req.getAndroidMaxVersionEnabled())
.build();
applications.add(application);
}
return SaasPageElement.Ext.builder()
.applications(applications)
.build();
}
private SaasPageElement.Ext resolveExt(SaveOrUpdatePageElementReq req) {
List<SaasPageElement.Application> applications = Lists.newArrayList();
if (Objects.nonNull(req.getIosMinVersion())
@ -652,84 +701,17 @@ public class SaasPageElementServiceImpl extends ServiceImpl<SaasPageElementMappe
@Override
@Transactional(rollbackFor = Exception.class)
public Long saveOrUpdate(SaveOrUpdatePageElementReq req) {
SaasPageElement basePageElement = SaasPageElement.builder()
.version(req.getVersion())
.groupCode(req.getCode())
.code(req.getCode())
.name(req.getName())
.type(req.getType())
.linkUrl(req.getLinkUrl())
.linkExt(getLinkExtStr(req.getIosRouterUrl(), req.getAndroidRouterUrl()))
.appType(req.getAppType())
.appId(req.getAppId())
.itemCode(req.getItemCode())
BatchUpsertPageElementReq.UpsertPageElementReq upsertPageElementReq = BatchUpsertPageElementReq.UpsertPageElementReq.builder().build();
BeanUtils.copyProperties(req, upsertPageElementReq);
BatchUpsertPageElementReq batchUpsertPageElementReq = BatchUpsertPageElementReq.builder()
.operatorId(req.getOperatorId())
.upsertPageElementReqs(Lists.newArrayList(upsertPageElementReq))
.build();
SaasPageElement.Ext ext = resolveExt(req);
List<Long> ids = batchUpsert(batchUpsertPageElementReq);
if (Objects.nonNull(req.getId())) {
SaasPageElement dbPageElement = saasPageElementDao.getById(req.getId());
AssertUtil.notNull(dbPageElement, "页面元素资源不存在");
basePageElement.setId(dbPageElement.getId());
basePageElement.setExt(dbPageElement.buildMergedExt(ext));
basePageElement.setUpdateBy(req.getOperatorId());
if (!dbPageElement.getCode().equals(basePageElement.getCode())) {
// 校验code唯一
validCode(basePageElement.getCode());
if (PageElementTypeEnum.PAGE.getCode().equals(req.getType())) {
// 更新子元素的group_code
saasPageElementDao.updateComponentsGroupCode(dbPageElement.getCode(), basePageElement.getCode(), dbPageElement.getTerminal());
}
// 更新关联关系的page_element_code
saasPageElementFeatureResourceRelationDao.updateGroupCode(dbPageElement.getCode(), basePageElement.getCode(), dbPageElement.getTerminal());
}
// page的groupCode是自己的code但是component的groupCode是父级页面的code
// 原来component在更新时会把自己的groupCode更新成自己的code
if (PageElementTypeEnum.COMPONENT.getCode().equals(req.getType())) {
basePageElement.setGroupCode(req.getGroupCode());
}
saasPageElementDao.updateById(basePageElement);
} else {
if (PageElementTypeEnum.PAGE.getCode().equals(req.getType())) {
AssertUtil.isTrue(StringUtils.isNotBlank(req.getItemCode()), "页面元素不存在");
List<SaasPageElementCategory> 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(StringUtils.isNotBlank(req.getGroupCode()), "页面元素不存在");
List<SaasPageElement> pageElements = saasPageElementDao.lambdaQuery()
.eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.getValue())
.eq(SaasPageElement::getCode, req.getGroupCode()).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());
basePageElement.setCreateBy(req.getOperatorId());
basePageElement.setUpdateBy(req.getOperatorId());
basePageElement.setExt(basePageElement.buildMergedExt(ext));
saasPageElementDao.save(basePageElement);
}
// 记录操作日志
try {
saveOrUpdateOperateLog(req, basePageElement);
} catch (Exception e) {
log.warn("save operate log error", e);
}
return basePageElement.getId();
return ids.stream().findFirst().get();
}
@Override
@ -869,11 +851,17 @@ public class SaasPageElementServiceImpl extends ServiceImpl<SaasPageElementMappe
}
private PageElementResp from(SaasPageElement saasPageElement,
Map<String, List<SaasFeatureResourceResp>> featureResources) {
Map<String, List<SaasFeatureResourceResp>> featureResources,
Map<String, List<PageElementResp>> childrenPageElements,
Map<String, PageElementCategoryResp> pageElementCategories) {
PageElementResp pageElementResp = PageElementResp.builder().build();
BeanUtils.copyProperties(saasPageElement, pageElementResp);
pageElementResp.setFeatureResources(featureResources.get(saasPageElement.getCode()));
pageElementResp.setChildren(childrenPageElements.get(saasPageElement.getCode()));
pageElementResp.setPageElementCategory(pageElementCategories.get(saasPageElement.getItemCode()));
return pageElementResp;
}
@ -957,6 +945,18 @@ public class SaasPageElementServiceImpl extends ServiceImpl<SaasPageElementMappe
}
}
private void saveOrUpdateOperateLog(BatchUpsertPageElementReq req, List<SaasPageElement> basePageElement) {
saasPgroupPermissionRelationOperateLogService.save(PermissionOperateLogReq.builder()
.tableName(PAGE_ELEMENT_TABLE_NAME)
.operatorId(req.getOperatorId())
.scene(PermissionRelationOperateLogSceneEnum.OMS_UPSERT_PAGE_ELEMENT.getValue())
// 批量更新记录id会超长后续提供统一的更基础的日志记录表先暂时用
.sceneId(UuidUtils.generateUuid())
.requestData(req)
.operateData(basePageElement)
.build());
}
private void saveOrUpdateOperateLog(SaveOrUpdatePageElementReq req, SaasPageElement basePageElement) {
saasPgroupPermissionRelationOperateLogService.save(PermissionOperateLogReq.builder()
.tableName(PAGE_ELEMENT_TABLE_NAME)
@ -1016,4 +1016,444 @@ public class SaasPageElementServiceImpl extends ServiceImpl<SaasPageElementMappe
.list();
}
private Map<String, List<PageElementResp>> listChildrenPageElement(List<SaasPageElement> pageElements,
PageElementReq param) {
if (CollectionUtils.isEmpty(pageElements) || BooleanUtils.isNotTrue(param.getNeedChildren())) {
return Collections.emptyMap();
}
Set<String> codes = pageElements.stream()
.map(SaasPageElement::getCode)
.collect(Collectors.toSet());
// 因为现在的数据结构type为PAGE的和type为COMPONENT的groupCode一样所以要排除type=PAGE的记录
return this.lambdaQuery()
.in(SaasPageElement::getGroupCode, codes)
.ne(SaasPageElement::getType, PageElementTypeEnum.PAGE)
.list()
.stream()
.map(e -> {
PageElementResp pageElementResp = PageElementResp.builder().build();
BeanUtils.copyProperties(e, pageElementResp);
return pageElementResp;
})
.collect(Collectors.groupingBy(PageElementResp::getGroupCode));
}
private Map<String, PageElementCategoryResp> listPageElementCategory(List<SaasPageElement> pageElements,
PageElementReq param) {
if (CollectionUtils.isEmpty(pageElements) || BooleanUtils.isNotTrue(param.getNeedPageElementCategory())) {
return Collections.emptyMap();
}
Set<String> itemCodes = pageElements.stream()
.map(SaasPageElement::getItemCode)
.collect(Collectors.toSet());
return saasPageElementCategoryDao.lambdaQuery()
.in(SaasPageElementCategory::getItemCode, itemCodes)
.eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.value)
.list()
.stream()
.map(e -> {
PageElementCategoryResp pageElementCategoryResp = PageElementCategoryResp.builder().build();
BeanUtils.copyProperties(e, pageElementCategoryResp);
return pageElementCategoryResp;
})
.collect(Collectors.toMap(PageElementCategoryResp::getItemCode, Function.identity()));
}
/**
* 资源对应的category如果不存在则需要补上对应的category
* @param req
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void syncPageElement(SyncPageElementReq req) {
PageElementReq pageElementReq = PageElementReq.builder()
.ids(req.getPageElementIds())
.needPageElementCategory(true)
.needChildren(true)
.build();
List<PageElementResp> prePageElements = RpcInternalUtil.rpcProcessor(() -> basePageElementApi.list(pageElementReq),
"list pageElement from base env", pageElementReq).getData();
if (CollectionUtils.isEmpty(prePageElements)) {
return;
}
Map<String, PageElementResp> localDBPageElements = listLocalDBPageElement(prePageElements);
// upsert pageElementCategory
upsertPageElementCategory(prePageElements, localDBPageElements, req);
BatchUpsertPageElementReq batchUpsertPageElementReq = BatchUpsertPageElementReq.builder()
.upsertPageElementReqs(prePageElements.stream()
.map(e -> {
BatchUpsertPageElementReq.UpsertPageElementReq upsertPageElementReq = BatchUpsertPageElementReq.UpsertPageElementReq.builder().build();
BeanUtils.copyProperties(e, upsertPageElementReq);
return upsertPageElementReq;
})
.collect(Collectors.toList()))
.operatorId(req.getOperatorId())
.build();
batchUpsert(batchUpsertPageElementReq);
}
private void upsertPageElementCategory(List<PageElementResp> prePageElements,
Map<String, PageElementResp> localDBPageElements,
SyncPageElementReq req) {
List<PageElementCategoryResp> prePageElementCategories = prePageElements.stream()
.map(PageElementResp::getPageElementCategory)
.filter(Objects::nonNull)
.collect(Collectors.toList());
if (CollectionUtils.isEmpty(prePageElementCategories)) {
log.info("no pageElementCategory need sync");
return;
}
Map<String, PageElementCategoryResp> localDBPageElementCategories = localDBPageElements.values().stream()
.map(PageElementResp::getPageElementCategory)
.filter(Objects::nonNull)
.collect(Collectors.toMap(PageElementCategoryResp::getItemCode, Function.identity()));
List<BatchUpsertPageElementCategoryReq.UpsertPageElementCategory> upsert = prePageElementCategories.stream()
.map(e -> {
PageElementCategoryResp localDBPageElementCategory = localDBPageElementCategories.get(e.getItemCode());
return BatchUpsertPageElementCategoryReq.UpsertPageElementCategory.builder()
.id(Objects.nonNull(localDBPageElementCategory) ? localDBPageElementCategory.getId() : null)
.terminal(e.getTerminal())
.itemCode(e.getItemCode())
.itemName(e.getItemName())
.build();
})
.collect(Collectors.toList());
BatchUpsertPageElementCategoryReq batchUpsertPageElementCategoryReq = BatchUpsertPageElementCategoryReq.builder()
.operatorId(req.getOperatorId())
.upsertPageElementCategories(upsert)
.build();
saasPageElementCategoryService.batchUpsert(batchUpsertPageElementCategoryReq);
}
private Map<String, PageElementResp> listLocalDBPageElement(List<PageElementResp> pageElements) {
Set<String> codes = pageElements.stream()
.map(PageElementResp::getCode)
.collect(Collectors.toSet());
Set<String> childrenCodes = pageElements.stream()
.map(PageElementResp::getChildren)
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.map(PageElementResp::getCode)
.collect(Collectors.toSet());
codes.addAll(childrenCodes);
return this.list(PageElementReq.builder()
.codes(codes)
.needPageElementCategory(true)
.build())
.stream()
.collect(Collectors.toMap(PageElementResp::getCode, Function.identity()));
}
@Override
@Transactional(rollbackFor = Exception.class)
public List<Long> batchUpsert(BatchUpsertPageElementReq req) {
Axssert.checkNotEmpty(req.getUpsertPageElementReqs(), PARAM_ERROR);
Map<String, SaasPageElementCategory> cagetories = checkItemCode(req);
Map<String, SaasPageElement> parentPageElements = checkGroupCode(req);
checkCode(req);
Map<Long, SaasPageElement> oldSaasPageElements = checkId(req);
// first:oldCode second:newCode
Map<String, BatchUpsertPageElementReq.UpsertPageElementReq> updatedCodePageElements = req.getUpsertPageElementReqs().stream()
.map(e -> {
if (Objects.isNull(e.getId())) {
return null;
}
SaasPageElement oldPageElement = oldSaasPageElements.get(e.getId());
if (Objects.equals(oldPageElement.getCode(), e.getCode())) {
return null;
}
return Pair.of(oldPageElement.getCode(), e);
})
.filter(Objects::nonNull)
.collect(Collectors.toMap(Pair::getFirst, Pair::getSecond));
// 原来设计问题点
// 1组件的groupCode是父级页面的code页面的groupCode是页面的code
// 2组件的itemCode使用父级页面的itemCode并且冗余了itemName
// 3新增页面需要根据itemCode找到category设置terminalitemCodeitemName
// 4新增组件需要根据页面的信息设置terminalitemCodeitemNameappTypeappId等
List<SaasPageElement> upsert = req.getUpsertPageElementReqs().stream()
.map(e -> {
SaasPageElement saasPageElement = SaasPageElement.builder()
.version(e.getVersion())
.groupCode(e.getCode())
.code(e.getCode())
.name(e.getName())
.type(e.getType())
.linkUrl(e.getLinkUrl())
.linkExt(getLinkExtStr(e.getIosRouterUrl(), e.getAndroidRouterUrl()))
.appType(e.getAppType())
.appId(e.getAppId())
.itemCode(e.getItemCode())
.createBy(Objects.nonNull(e.getId()) ? null : req.getOperatorId())
.updateBy(req.getOperatorId())
.build();
if (Objects.equals(PageElementTypeEnum.PAGE.getCode(), e.getType()) && Objects.nonNull(e.getItemCode())) {
SaasPageElementCategory category = cagetories.get(e.getItemCode());
Axssert.notNull(category, PAGE_ELEMENT_ITEM_CODE_NOT_FOUND);
saasPageElement.setTerminal(category.getTerminal());
saasPageElement.setItemCode(category.getItemCode());
saasPageElement.setItemName(category.getItemName());
} else if (Objects.equals(PageElementTypeEnum.COMPONENT.getCode(), e.getType()) && Objects.nonNull(e.getGroupCode())) {
SaasPageElement parentPageElement = parentPageElements.get(e.getGroupCode());
Axssert.notNull(parentPageElement, PAGE_ELEMENT_GROUP_CODE_NOT_FOUND);
saasPageElement.setVersion(parentPageElement.getVersion());
saasPageElement.setGroupCode(parentPageElement.getCode());
saasPageElement.setTerminal(parentPageElement.getTerminal());
saasPageElement.setAppType(parentPageElement.getAppType());
saasPageElement.setAppId(parentPageElement.getAppId());
saasPageElement.setItemCode(parentPageElement.getItemCode());
saasPageElement.setItemName(parentPageElement.getItemName());
}
SaasPageElement.Ext ext = resolveExt(e);
if (Objects.nonNull(e.getId())) {
SaasPageElement dbPageElement = oldSaasPageElements.get(e.getId());
Axssert.notNull(dbPageElement, PAGE_ELEMENT_ERROR);
saasPageElement.setExt(dbPageElement.buildMergedExt(ext));
} else {
saasPageElement.setExt(saasPageElement.buildMergedExt(ext));
}
return saasPageElement;
})
.collect(Collectors.toList());
this.updateBatchById(upsert);
// 1更新页面的code时需要把对应组件的groupCode都更新需要把菜单资源关联表的pageCode进行更新
// 2更新组件的code时需要把菜单资源关联表的pageCode进行更新
if (!updatedCodePageElements.isEmpty()) {
// TODO 待统一的更新接口收口后切换
updateComponentGroupCode(updatedCodePageElements);
// 更新关联关系的page_element_code
updatePageElementFeatureResource(updatedCodePageElements);
}
// 记录操作日志
try {
saveOrUpdateOperateLog(req, upsert);
} catch (Exception e) {
log.warn("save operate log error", e);
}
return upsert.stream()
.map(BaseEntity::getId)
.collect(Collectors.toList());
}
private void updateComponentGroupCode(Map<String, BatchUpsertPageElementReq.UpsertPageElementReq> updatedCodePageElementMap) {
if (Objects.isNull(updatedCodePageElementMap) || updatedCodePageElementMap.isEmpty()) {
return;
}
List<BatchUpsertPageElementReq.UpsertPageElementReq> updatedCodePageElements = updatedCodePageElementMap.values().stream()
.filter(e -> Objects.equals(PageElementTypeEnum.PAGE.getCode(), e.getType()))
.collect(Collectors.toList());
if (CollectionUtils.isEmpty(updatedCodePageElements)) {
return;
}
List<SaasPageElement> components = this.lambdaQuery()
.in(SaasPageElement::getGroupCode, updatedCodePageElementMap.keySet())
.eq(SaasPageElement::getIsDelete, DeleteEnum.NORMAL.getValue())
.eq(SaasPageElement::getType, PageElementTypeEnum.COMPONENT.getCode())
.list();
if (CollectionUtils.isEmpty(components)) {
return;
}
this.updateBatchById(components.stream()
.map(e -> {
SaasPageElement saasPageElement = SaasPageElement.builder()
.groupCode(updatedCodePageElementMap.get(e.getGroupCode()).getGroupCode())
.build();
saasPageElement.setId(e.getId());
return saasPageElement;
})
.collect(Collectors.toList()));
}
private void updatePageElementFeatureResource(Map<String, BatchUpsertPageElementReq.UpsertPageElementReq> updatedCodePageElements) {
if (Objects.isNull(updatedCodePageElements) || updatedCodePageElements.isEmpty()) {
return;
}
List<SaasPageElementFeatureResourceRelation> pageElementFeatureResourceRelations = saasPageElementFeatureResourceRelationDao.lambdaQuery()
.in(SaasPageElementFeatureResourceRelation::getPageElementCode, updatedCodePageElements.keySet())
.eq(SaasPageElementFeatureResourceRelation::getIsDelete, DeleteEnum.NORMAL.getValue())
.list();
if (CollectionUtils.isEmpty(pageElementFeatureResourceRelations)) {
return;
}
List<SaasPageElementFeatureResourceRelation> updates = pageElementFeatureResourceRelations.stream()
.map(e -> {
SaasPageElementFeatureResourceRelation result = SaasPageElementFeatureResourceRelation.builder()
.pageElementCode(updatedCodePageElements.get(e.getPageElementCode()).getCode())
.build();
result.setId(e.getId());
return result;
})
.collect(Collectors.toList());
saasPageElementFeatureResourceRelationDao.updateBatchById(updates);
}
private Map<Long, SaasPageElement> checkId(BatchUpsertPageElementReq req) {
Set<Long> ids = req.getUpsertPageElementReqs().stream()
.map(BatchUpsertPageElementReq.UpsertPageElementReq::getId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
if (CollectionUtils.isEmpty(ids)) {
return Collections.emptyMap();
}
List<SaasPageElement> pageElements = saasPageElementDao.listByIds(ids);
if (!Objects.equals(ids.size(), pageElements.size())) {
ids.removeAll(pageElements.stream().map(SaasPageElement::getId).collect(Collectors.toSet()));
throw PAGE_ELEMENT_ERROR.toException(PAGE_ELEMENT_ERROR.getErrorMessage(), ids);
}
return pageElements.stream()
.collect(Collectors.toMap(SaasPageElement::getId, Function.identity()));
}
private Map<String, SaasPageElement> checkGroupCode(BatchUpsertPageElementReq req) {
// 组件一定要传groupCode
List<BatchUpsertPageElementReq.UpsertPageElementReq> componentElements = req.getUpsertPageElementReqs().stream()
.filter(e -> Objects.equals(PageElementTypeEnum.COMPONENT.getCode(), e.getType()))
.collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(componentElements)) {
List<BatchUpsertPageElementReq.UpsertPageElementReq> blankGroupCodes = componentElements.stream()
.filter(e -> StringUtils.isBlank(e.getGroupCode()))
.collect(Collectors.toList());
Axssert.check(CollectionUtils.isEmpty(blankGroupCodes), PAGE_ELEMENT_GROUP_CODE_NOT_NULL);
}
// 后续如果有其他类型也需要传groupCode这里就不按照组件来过滤
Set<String> groupCodes = req.getUpsertPageElementReqs().stream()
.map(BatchUpsertPageElementReq.UpsertPageElementReq::getGroupCode)
.filter(StringUtils::isNotBlank)
.collect(Collectors.toSet());
if (CollectionUtils.isEmpty(groupCodes)) {
return Collections.emptyMap();
}
List<SaasPageElement> pageElements = saasPageElementDao.lambdaQuery()
.eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.getValue())
.eq(SaasPageElement::getCode, groupCodes)
.list();
if (!Objects.equals(groupCodes.size(), pageElements.size())) {
groupCodes.removeAll(pageElements.stream().map(SaasPageElement::getCode).collect(Collectors.toSet()));
throw PAGE_ELEMENT_GROUP_CODE_NOT_FOUND.toException(PAGE_ELEMENT_GROUP_CODE_NOT_FOUND.getErrorMessage(), groupCodes);
}
return pageElements.stream()
.collect(Collectors.toMap(SaasPageElement::getCode, Function.identity()));
}
private Map<String, SaasPageElementCategory> checkItemCode(BatchUpsertPageElementReq req) {
// 页面一定要选分组
List<BatchUpsertPageElementReq.UpsertPageElementReq> pageElements = req.getUpsertPageElementReqs().stream()
.filter(e -> Objects.equals(PageElementTypeEnum.PAGE.getCode(), e.getType()))
.collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(pageElements)) {
List<BatchUpsertPageElementReq.UpsertPageElementReq> blankItemCodes = pageElements.stream()
.filter(e -> StringUtils.isBlank(e.getItemCode()))
.collect(Collectors.toList());
Axssert.check(CollectionUtils.isEmpty(blankItemCodes), PAGE_ELEMENT_ITEM_CODE_NOT_NULL);
}
Set<String> itemCodes = req.getUpsertPageElementReqs().stream()
.map(BatchUpsertPageElementReq.UpsertPageElementReq::getItemCode)
.filter(StringUtils::isNotBlank)
.collect(Collectors.toSet());
if (CollectionUtils.isEmpty(itemCodes)) {
return Collections.emptyMap();
}
List<SaasPageElementCategory> categories = saasPageElementCategoryDao.lambdaQuery()
.eq(BaseEntity::getIsDelete, DeleteEnum.NORMAL.getValue())
.in(SaasPageElementCategory::getItemCode, itemCodes)
.list();
if (!Objects.equals(itemCodes.size(), categories.size())) {
itemCodes.removeAll(categories.stream().map(SaasPageElementCategory::getItemCode).collect(Collectors.toSet()));
throw PAGE_ELEMENT_ITEM_CODE_NOT_FOUND.toException(PAGE_ELEMENT_ITEM_CODE_NOT_FOUND.getErrorMessage(), itemCodes);
}
return categories.stream()
.collect(Collectors.toMap(SaasPageElementCategory::getItemCode, Function.identity()));
}
private void checkCode(BatchUpsertPageElementReq req) {
// check新增或者更新的itemCode是否已经存在
List<String> codes = req.getUpsertPageElementReqs().stream()
.map(BatchUpsertPageElementReq.UpsertPageElementReq::getCode)
.collect(Collectors.toList());
List<SaasPageElement> saasPageElements = this.lambdaQuery()
.in(SaasPageElement::getCode, codes)
.eq(SaasPageElement::getIsDelete, DeleteEnum.NORMAL.value)
.list();
if (CollectionUtils.isEmpty(saasPageElements)) {
return;
}
Map<String, SaasPageElement> codeMap = saasPageElements.stream()
.collect(Collectors.toMap(SaasPageElement::getCode, Function.identity()));
List<String> dbDuplicateCodes = req.getUpsertPageElementReqs().stream()
.filter(e -> {
SaasPageElement oldSaasPageElement = codeMap.get(e.getCode());
if (Objects.isNull(oldSaasPageElement)) {
return false;
}
// 新增里重复的code
if (Objects.isNull(e.getId())) {
return true;
}
// 更新里重复的code
return !Objects.equals(e.getId(), oldSaasPageElement.getId());
})
.map(BatchUpsertPageElementReq.UpsertPageElementReq::getCode)
.collect(Collectors.toList());
Axssert.check(CollectionUtils.isEmpty(dbDuplicateCodes), PAGE_CODE_DUPLICATE,
PAGE_CODE_DUPLICATE.getErrorMessage(), dbDuplicateCodes);
}
}

View File

@ -1,127 +0,0 @@
package cn.axzo.tyr.server.service.impl;
import cn.axzo.thrones.client.saas.ServicePkgClient;
import cn.axzo.thrones.client.saas.entity.serivicepgkproduct.ServicePkgProduct;
import cn.axzo.thrones.client.saas.entity.servicepkg.ServicePkgDetailRes;
import cn.axzo.tyr.base.BaseTest;
import cn.axzo.tyr.base.MysqlDataLoader;
import cn.axzo.tyr.client.model.req.IdentityAuthReq;
import cn.axzo.tyr.client.model.req.PermissionCheckReq;
import cn.axzo.tyr.client.model.res.IdentityAuthRes;
import cn.axzo.tyr.server.repository.dao.ProductModuleDao;
import cn.axzo.tyr.server.repository.dao.SaasFeatureDao;
import cn.axzo.tyr.server.repository.entity.ProductModule;
import cn.axzo.tyr.server.service.PermissionQueryService;
import cn.axzo.tyr.server.service.TyrSaasAuthService;
import cn.azxo.framework.common.model.CommonResponse;
import cn.hutool.core.collection.CollectionUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@Slf4j
class PermissionQueryServiceImplTest extends BaseTest {
@Autowired
private PermissionQueryService permissionQueryService;
@Autowired
private MysqlDataLoader mysqlDataLoader;
@Autowired
private TyrSaasAuthService tyrSaasAuthService;
@Autowired
private SaasFeatureDao saasFeatureDao;
@Autowired
private ServicePkgClient servicePkgClient;
@Autowired
private ProductModuleDao productModuleDao;
@BeforeEach
@Override
public void setup() {
super.setup();
mysqlDataLoader.loadFromClassName(getClass().getSimpleName());
MockitoAnnotations.initMocks(this);
}
@Test
void hasPermissionNew() {
ServicePkgDetailRes servicePkgDetailRes = new ServicePkgDetailRes();
ServicePkgProduct servicePkgProduct = new ServicePkgProduct();
servicePkgProduct.setProductId(1L);
ServicePkgProduct servicePkgProduct2 = new ServicePkgProduct();
servicePkgProduct2.setProductId(6L);
servicePkgDetailRes.setProducts(Lists.newArrayList(
servicePkgProduct,
servicePkgProduct2
));
Mockito.when(servicePkgClient.getServicePkgDetailBySpaceId(Mockito.any()))
.thenReturn(CommonResponse.success(Lists.newArrayList(servicePkgDetailRes)));
// 普通角色和产品有旧权限码权限begin
PermissionCheckReq permissionCheckReq = PermissionCheckReq.builder()
.personId(80792L)
.featureCodes(Lists.newArrayList("cms:ent_contact", "cms:ent_contact_new"))
.ouId(5154L)
.workspaceId(205L)
.build();
List<ProductModule> list = productModuleDao.list();
log.info("size:{}", list.size());
System.out.println("size+" + list.size());
new Thread(() -> {
synchronized (this) {
List<ProductModule> productModules = productModuleDao.list();
log.info("inner size:{}", productModules.size());
System.out.println("inner size+" + list.size());
}
}).start();
boolean result = authPermission(permissionCheckReq);
boolean resultOld = authPermissionOld(permissionCheckReq);
Assertions.assertTrue(result);
Assertions.assertTrue(resultOld);
// 普通角色和产品有旧权限码权限end
// 管理员角色和产品有旧权限码权限begin
permissionCheckReq = PermissionCheckReq.builder()
.personId(80792L)
.featureCodes(Lists.newArrayList("cms:ent_contact", "cms:ent_contact_new"))
.ouId(5154L)
.workspaceId(290L)
.build();
result = authPermission(permissionCheckReq);
resultOld = authPermissionOld(permissionCheckReq);
Assertions.assertTrue(result);
Assertions.assertTrue(resultOld);
// 管理员角色和产品有旧权限码权限end
}
private boolean authPermission(PermissionCheckReq permissionCheckReq) {
return tyrSaasAuthService.authPermission(permissionCheckReq) || tyrSaasAuthService.authNewPermission(permissionCheckReq);
}
private boolean authPermissionOld(PermissionCheckReq req) {
IdentityAuthReq authReq = IdentityAuthReq.builder()
.personId(req.getPersonId())
.workspaceOusPairs(Collections.singletonList(IdentityAuthReq.WorkspaceOuPair.builder()
.workspaceId(req.getWorkspaceId())
.ouId(req.getOuId()).build()))
.featureCode(new HashSet<>(req.getFeatureCodes()))
.terminal(StringUtils.isBlank(req.getTerminal()) ? null : Collections.singletonList(req.getTerminal()))
.build();
IdentityAuthRes.WorkspacePermission permissions = tyrSaasAuthService.findIdentityAuthMix(authReq).getPermissions().get(0);
return CollectionUtil.isNotEmpty(permissions.getPermissionPoint());
}
}

View File

@ -0,0 +1,53 @@
package cn.axzo.tyr.server.service.impl;
import cn.axzo.foundation.exception.BusinessException;
import cn.axzo.tyr.base.BaseTest;
import cn.axzo.tyr.client.model.req.BatchUpsertPageElementCategoryReq;
import cn.axzo.tyr.client.model.req.SaveOrUpdatePageElementCategoryReq;
import cn.axzo.tyr.server.service.SaasPageElementCategoryService;
import cn.axzo.tyr.server.service.SaasRoleUserRelationService;
import com.google.common.collect.Sets;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
import static cn.axzo.tyr.server.config.exception.BizResultCode.ITEM_NAME_DUPLICATE;
import static cn.axzo.tyr.server.config.exception.BizResultCode.REMOVE_USER_ROLE_ERROR;
import static org.junit.jupiter.api.Assertions.*;
class SaasPageElementCategoryServiceImplTest extends BaseTest {
@Autowired
private SaasPageElementCategoryService saasPageElementCategoryService;
@BeforeEach
@Override
public void setup() {
super.setup();
}
@Test
void batchUpsert() {
BusinessException businessException = assertThrows(BusinessException.class, ()->{
List<BatchUpsertPageElementCategoryReq.UpsertPageElementCategory> req = Lists.newArrayList(
BatchUpsertPageElementCategoryReq.UpsertPageElementCategory.builder().itemName("A1").build(),
BatchUpsertPageElementCategoryReq.UpsertPageElementCategory.builder().itemName("A1").build(),
BatchUpsertPageElementCategoryReq.UpsertPageElementCategory.builder().itemName("B1").build(),
BatchUpsertPageElementCategoryReq.UpsertPageElementCategory.builder().itemName("B1").build(),
BatchUpsertPageElementCategoryReq.UpsertPageElementCategory.builder().itemName("C1").build()
);
BatchUpsertPageElementCategoryReq batchUpsertPageElementCategoryReq = BatchUpsertPageElementCategoryReq.builder()
.upsertPageElementCategories(req)
.operatorId(11L)
.build();
saasPageElementCategoryService.batchUpsert(batchUpsertPageElementCategoryReq);
});
assertEquals(businessException.getErrorCode(), ITEM_NAME_DUPLICATE.getErrorCode());
assertEquals(businessException.getErrorMsg(), "资源分组名字重复,重复的名字:[A1, B1]");
}
}

View File

@ -0,0 +1,54 @@
package cn.axzo.tyr.server.service.impl;
import cn.axzo.apollo.workspace.api.workspace.WorkspaceApi;
import cn.axzo.foundation.exception.BusinessException;
import cn.axzo.tyr.base.BaseTest;
import cn.axzo.tyr.base.MysqlDataLoader;
import cn.axzo.tyr.client.model.req.BatchUpsertPageElementCategoryReq;
import cn.axzo.tyr.client.model.req.SaveOrUpdatePageElementReq;
import cn.axzo.tyr.server.service.SaasPageElementService;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
import static cn.axzo.tyr.server.config.exception.BizResultCode.ITEM_NAME_DUPLICATE;
import static cn.axzo.tyr.server.config.exception.BizResultCode.PAGE_ELEMENT_ERROR;
import static org.junit.jupiter.api.Assertions.*;
class SaasPageElementServiceImplTest extends BaseTest {
@Autowired
private MysqlDataLoader mysqlDataLoader;
@Autowired
private SaasPageElementService saasPageElementService;
@BeforeEach
@Override
public void setup() {
super.setup();
mysqlDataLoader.loadFromClassName(getClass().getSimpleName());
MockitoAnnotations.initMocks(this);
}
@Test
void saveOrUpdate() {
// 更新时id是错的
BusinessException businessException = assertThrows(BusinessException.class, ()->{
SaveOrUpdatePageElementReq saveOrUpdatePageElementReq = SaveOrUpdatePageElementReq.builder()
.id(1L)
.build();
saasPageElementService.saveOrUpdate(saveOrUpdatePageElementReq);
});
assertEquals(businessException.getErrorCode(), PAGE_ELEMENT_ERROR.getErrorCode());
assertEquals(businessException.getErrorMsg(), "资源分组错误:[1]");
}
@Test
void batchUpsert() {
}
}

View File

@ -1,62 +0,0 @@
package cn.axzo.tyr.server.service.impl;
import cn.axzo.tyr.base.BaseTest;
import cn.axzo.tyr.base.MysqlDataLoader;
import cn.axzo.tyr.client.model.req.PermissionCheckReq;
import cn.axzo.tyr.server.repository.dao.SaasFeatureDao;
import cn.axzo.tyr.server.repository.dao.SaasRoleDao;
import cn.axzo.tyr.server.repository.entity.SaasFeature;
import cn.axzo.tyr.server.service.TyrSaasAuthService;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import static org.junit.jupiter.api.Assertions.*;
class TyrSaasAuthServiceImplTest extends BaseTest {
@Autowired
private MysqlDataLoader mysqlDataLoader;
@Autowired
private TyrSaasAuthService tyrSaasAuthService;
@Autowired
private SaasFeatureDao saasFeatureDao;
@BeforeEach
@Override
public void setup() {
super.setup();
mysqlDataLoader.loadFromClassName(getClass().getSimpleName());
}
@Test
void authPermission() {
saasFeatureDao.save(SaasFeature.builder()
.featureCode("CMS_001")
.terminal("CMS")
.build());
PermissionCheckReq permissionCheckReq = PermissionCheckReq.builder()
.ouId(5708L)
.workspaceId(300L)
.personId(42642L)
.featureCodes(Lists.newArrayList("dfff"))
.build();
boolean result = tyrSaasAuthService.authPermission(permissionCheckReq);
Assertions.assertFalse(result);
result = tyrSaasAuthService.authPermission(PermissionCheckReq.builder()
.ouId(5708L)
.workspaceId(300L)
.personId(42642L)
.featureCodes(Lists.newArrayList("CMS_001"))
.terminal("sdf")
.build());
Assertions.assertFalse(result);
}
}

View File

@ -0,0 +1,7 @@
#-->DEFAULT
INSERT INTO saas_page_element (id, group_code, code, name, type, link_url, terminal, create_at, update_at, is_delete, create_name, app_type, version, item_code, link_ext, app_id, item_name, ext, create_by, update_by) VALUES (364184, 'h5:cmp_invite_team_page', 'h5:cmp_invite_team_page', '项目通讯录-邀请班组', 'PAGE', '__UNI__33771704#/inviteTeam', 'NT_CMP_APP_GENERAL', '2024-09-02 11:19:33', '2024-11-22 15:55:22', 0, '', 'H5', 0, 'h5:member_33771704', '', '__UNI__33771704', '通讯录H5', '{"applications": [{"type": "IOS", "minVersion": 0}, {"type": "ANDROID", "minVersion": 0}]}', null, null);
INSERT INTO saas_page_element (id, group_code, code, name, type, link_url, terminal, create_at, update_at, is_delete, create_name, app_type, version, item_code, link_ext, app_id, item_name, ext, create_by, update_by) VALUES (364185, 'h5:cmp_invite_team_page', 'h5:cmp_invite_qr_code_btn', '项目通讯录-邀请班组-二维码邀请', 'COMPONENT', '', 'NT_CMP_APP_GENERAL', '2024-09-02 11:19:33', '2024-11-22 15:55:22', 0, '', 'H5', 0, 'h5:member_33771704', '', '__UNI__33771704', '通讯录H5', '{"applications": [{"type": "IOS", "minVersion": 0}, {"type": "ANDROID", "minVersion": 0}]}', null, null);
#-->SaasRoleUserRelationServiceImplTest.sql

View File

@ -188,6 +188,13 @@ CREATE TABLE `saas_page_element` (
`create_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`is_delete` bigint NOT NULL DEFAULT '0' COMMENT '删除标识',
`create_name` varchar(64) NOT NULL DEFAULT '' COMMENT '创建人名',
`app_type` varchar(32) NOT NULL DEFAULT '' COMMENT 'app类型APP:原生H5:h5页面',
`version` bigint NOT NULL DEFAULT '0' COMMENT '客户端版本号',
`item_code` varchar(64) NOT NULL DEFAULT '' COMMENT '项目code',
`link_ext` varchar(4096) NOT NULL DEFAULT '' COMMENT 'APP适配参数',
`app_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'AppID',
`item_name` varchar(64) NOT NULL DEFAULT '' COMMENT '项目名称',
PRIMARY KEY (`id`),
KEY `idx_page_element_gcode` (`group_code`),
KEY `idx_page_element_code` (`code`)
@ -314,5 +321,28 @@ CREATE TABLE `permission_rule` (
alter table saas_role_group add column `path` varchar(255) DEFAULT '0' COMMENT 'ID层级路径 逗号分隔';
CREATE TABLE `saas_page_element_category` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
`item_code` varchar(64) NOT NULL DEFAULT '' COMMENT '项目编码',
`item_name` varchar(128) NOT NULL DEFAULT '' COMMENT '项目名称',
`terminal` varchar(64) NOT NULL DEFAULT '' COMMENT '',
`is_delete` bigint NOT NULL DEFAULT '0' COMMENT '删除标志',
`create_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`create_by` bigint NOT NULL DEFAULT '0' COMMENT '创建人',
`update_by` bigint NOT NULL DEFAULT '0' COMMENT '更新人',
PRIMARY KEY (`id`),
UNIQUE KEY `saas_page_element_category_item_code` (`item_code`),
KEY `saas_page_element_category_item_name` (`item_name`)
) ENGINE=InnoDB AUTO_INCREMENT=41 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='前端元素类型';
-- alter table saas_page_element add column `ext` JSON NULL COMMENT '额外信息, 使用json便于查询';
alter table saas_page_element add column `ext` VARCHAR(2048) NOT NULL DEFAULT '{}' COMMENT '额外信息';
alter table saas_page_element add column `create_by` bigint DEFAULT NULL COMMENT '创建人';
alter table saas_page_element add column `update_by` bigint DEFAULT NULL COMMENT '更新人';
alter table saas_feature_resource modify column feature_code varchar(100) not null comment '资源编码-权限码';
alter table saas_feature_resource modify column uni_code varchar(100) default '' not null comment '唯一编码用于pre环境菜单同步';