mirror of https://gitee.com/xiaonuobase/snowy
【更新】完善移动端菜单,menu的pages改为path,增加了menuType字段,与后端一致,前端记得修改
parent
b61371b722
commit
660b1e91a9
|
@ -0,0 +1 @@
|
|||
#移动端API接口
|
|
@ -10,4 +10,34 @@
|
|||
* 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
|
||||
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
||||
*/
|
||||
package vip.xiaonuo.biz;
|
||||
package vip.xiaonuo.mobile.api;
|
||||
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
import cn.hutool.json.JSONObject;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 移动端菜单API
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2023/1/31 10:09
|
||||
**/
|
||||
public interface MobileMenuApi {
|
||||
|
||||
/**
|
||||
* 获取移动端菜单授权树
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2023/1/31 10:10
|
||||
**/
|
||||
List<JSONObject> mobileMenuTreeSelector();
|
||||
|
||||
/**
|
||||
* 获取移动端登录菜单树
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2023/1/31 10:29
|
||||
**/
|
||||
List<Tree<String>> loginMobileMenuTree(List<String> menuIdList);
|
||||
}
|
|
@ -29,4 +29,12 @@ public interface SysRelationApi {
|
|||
* @date 2022/6/6 11:43
|
||||
**/
|
||||
List<String> getUserIdListByRoleIdList(List<String> roleIdList);
|
||||
|
||||
/**
|
||||
* 根据移动端菜单Id集合移除角色和移动端菜单关系
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2023/1/31 9:54
|
||||
**/
|
||||
void removeRoleHasMobileMenuRelationByMenuIdList(List<String> targetIdList);
|
||||
}
|
||||
|
|
|
@ -85,13 +85,13 @@ public class GenBasicServiceImpl extends ServiceImpl<GenBasicMapper, GenBasic> i
|
|||
|
||||
private static final String DB_PASSWORD_KEY = "spring.datasource.dynamic.datasource.master.password";
|
||||
|
||||
private static final String MODULE_KEY = "mobile";
|
||||
private static final String MODULE_KEY = "biz";
|
||||
|
||||
private static final String GEN_PROJECT_FRONT_PLUGIN_KEY = "snowy-admin-web";
|
||||
|
||||
private static final String GEN_PROJECT_PLUGIN_KEY = "snowy-plugin";
|
||||
|
||||
private static final String GEN_PROJECT_PLUGIN_BIZ_KEY = GEN_PROJECT_PLUGIN_KEY + File.separator + "snowy-plugin-mobile";
|
||||
private static final String GEN_PROJECT_PLUGIN_BIZ_KEY = GEN_PROJECT_PLUGIN_KEY + File.separator + "snowy-plugin-biz";
|
||||
|
||||
private static final List<JSONObject> GEN_SQL_FILE_LIST = CollectionUtil.newArrayList(
|
||||
JSONUtil.createObj().set("name", "Mysql.sql.btl"),
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 引入系统接口,用于授权角色等功能 -->
|
||||
<!-- 引入系统接口,用于授权菜单等功能 -->
|
||||
<dependency>
|
||||
<groupId>vip.xiaonuo</groupId>
|
||||
<artifactId>snowy-plugin-sys-api</artifactId>
|
||||
|
|
|
@ -93,6 +93,21 @@ public class MobileMenuController {
|
|||
return CommonResult.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更改移动端菜单所属模块
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2022/4/24 20:47
|
||||
*/
|
||||
@ApiOperationSupport(order = 5)
|
||||
@ApiOperation("更改移动端菜单所属模块")
|
||||
@CommonLog("更改移动端菜单所属模块")
|
||||
@PostMapping("/mobile/menu/changeModule")
|
||||
public CommonResult<String> changeModule(@RequestBody @Valid MobileMenuChangeModuleParam mobileMenuChangeModuleParam) {
|
||||
mobileMenuService.changeModule(mobileMenuChangeModuleParam);
|
||||
return CommonResult.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除移动端菜单
|
||||
*
|
||||
|
|
|
@ -49,40 +49,44 @@ public class MobileMenu extends CommonEntity {
|
|||
@ApiModelProperty(value = "编码", position = 4)
|
||||
private String code;
|
||||
|
||||
/** 路径 */
|
||||
@ApiModelProperty(value = "路径", position = 5)
|
||||
private String pages;
|
||||
|
||||
/** 分类 */
|
||||
@ApiModelProperty(value = "分类", position = 6)
|
||||
@ApiModelProperty(value = "分类", position = 5)
|
||||
private String category;
|
||||
|
||||
/** 模块 */
|
||||
@ApiModelProperty(value = "模块", position = 7)
|
||||
@ApiModelProperty(value = "模块", position = 6)
|
||||
private String module;
|
||||
|
||||
/** 菜单类型 */
|
||||
@ApiModelProperty(value = "菜单类型", position = 7)
|
||||
private String menuType;
|
||||
|
||||
/** 路径 */
|
||||
@ApiModelProperty(value = "路径", position = 8)
|
||||
private String path;
|
||||
|
||||
/** 图标 */
|
||||
@ApiModelProperty(value = "图标", position = 8)
|
||||
@ApiModelProperty(value = "图标", position = 9)
|
||||
private String icon;
|
||||
|
||||
/** 颜色 */
|
||||
@ApiModelProperty(value = "颜色", position = 9)
|
||||
@ApiModelProperty(value = "颜色", position = 10)
|
||||
private String color;
|
||||
|
||||
/** 规则类型 */
|
||||
@ApiModelProperty(value = "规则类型", position = 10)
|
||||
@ApiModelProperty(value = "规则类型", position = 11)
|
||||
private String regType;
|
||||
|
||||
/** 可用状态 */
|
||||
@ApiModelProperty(value = "可用状态", position = 11)
|
||||
@ApiModelProperty(value = "可用状态", position = 12)
|
||||
private String status;
|
||||
|
||||
/** 排序码 */
|
||||
@ApiModelProperty(value = "排序码", position = 12)
|
||||
@ApiModelProperty(value = "排序码", position = 13)
|
||||
private Integer sortCode;
|
||||
|
||||
/** 扩展信息 */
|
||||
@ApiModelProperty(value = "扩展信息", position = 13)
|
||||
@ApiModelProperty(value = "扩展信息", position = 14)
|
||||
@TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED)
|
||||
private String extJson;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright [2022] [https://www.xiaonuo.vip]
|
||||
*
|
||||
* Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
|
||||
*
|
||||
* 1.请不要删除和修改根目录下的LICENSE文件。
|
||||
* 2.请不要删除和修改Snowy源码头部的版权声明。
|
||||
* 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
|
||||
* 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
|
||||
* 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
|
||||
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
||||
*/
|
||||
package vip.xiaonuo.mobile.modular.resource.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import vip.xiaonuo.common.exception.CommonException;
|
||||
|
||||
/**
|
||||
* 移动端资菜单状态枚举
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2022/4/21 19:56
|
||||
**/
|
||||
@Getter
|
||||
public enum MobileResourceMenuStatusEnum {
|
||||
|
||||
/** 可用 */
|
||||
ENABLE("ENABLE"),
|
||||
|
||||
/** 不可用 */
|
||||
DISABLED("DISABLED");
|
||||
|
||||
private final String value;
|
||||
|
||||
MobileResourceMenuStatusEnum(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static void validate(String value) {
|
||||
boolean flag = ENABLE.getValue().equals(value) || DISABLED.getValue().equals(value);
|
||||
if(!flag) {
|
||||
throw new CommonException("不支持的资源分类:{}", value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright [2022] [https://www.xiaonuo.vip]
|
||||
*
|
||||
* Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
|
||||
*
|
||||
* 1.请不要删除和修改根目录下的LICENSE文件。
|
||||
* 2.请不要删除和修改Snowy源码头部的版权声明。
|
||||
* 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
|
||||
* 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
|
||||
* 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
|
||||
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
||||
*/
|
||||
package vip.xiaonuo.mobile.modular.resource.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import vip.xiaonuo.common.exception.CommonException;
|
||||
|
||||
/**
|
||||
* 移动端菜单类型枚举
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2022/4/21 19:56
|
||||
**/
|
||||
@Getter
|
||||
public enum MobileResourceMenuTypeEnum {
|
||||
|
||||
/** 目录 */
|
||||
CATALOG("CATALOG"),
|
||||
|
||||
/** 组件 */
|
||||
MENU("MENU"),
|
||||
|
||||
/** 内链 */
|
||||
IFRAME("IFRAME"),
|
||||
|
||||
/** 外链 */
|
||||
LINK("LINK");
|
||||
|
||||
private final String value;
|
||||
|
||||
MobileResourceMenuTypeEnum(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static void validate(String value) {
|
||||
boolean flag = CATALOG.getValue().equals(value) || MENU.getValue().equals(value) || IFRAME.getValue().equals(value) ||
|
||||
LINK.getValue().equals(value);
|
||||
if(!flag) {
|
||||
throw new CommonException("不支持的菜单类型:{}", value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -38,43 +38,47 @@ public class MobileMenuAddParam {
|
|||
@NotBlank(message = "title不能为空")
|
||||
private String title;
|
||||
|
||||
/** 界面路径 */
|
||||
@ApiModelProperty(value = "界面路径", required = true, position = 3)
|
||||
@NotBlank(message = "pages不能为空")
|
||||
private String pages;
|
||||
|
||||
/** 分类 */
|
||||
@ApiModelProperty(value = "分类", required = true, position = 4)
|
||||
@ApiModelProperty(value = "分类", required = true, position = 3)
|
||||
@NotBlank(message = "category不能为空")
|
||||
private String category;
|
||||
|
||||
/** 模块 */
|
||||
@ApiModelProperty(value = "模块", required = true, position = 5)
|
||||
@ApiModelProperty(value = "模块", required = true, position = 4)
|
||||
@NotBlank(message = "module不能为空")
|
||||
private String module;
|
||||
|
||||
/** 菜单类型 */
|
||||
@ApiModelProperty(value = "菜单类型", position = 5)
|
||||
@NotBlank(message = "menuType不能为空")
|
||||
private String menuType;
|
||||
|
||||
/** 路径 */
|
||||
@ApiModelProperty(value = "路径", position = 6)
|
||||
@NotBlank(message = "path不能为空")
|
||||
private String path;
|
||||
|
||||
/** 图标 */
|
||||
@ApiModelProperty(value = "图标", required = true, position = 6)
|
||||
@ApiModelProperty(value = "图标", required = true, position = 7)
|
||||
@NotBlank(message = "icon不能为空")
|
||||
private String icon;
|
||||
|
||||
/** 颜色 */
|
||||
@ApiModelProperty(value = "颜色", required = true, position = 7)
|
||||
@ApiModelProperty(value = "颜色", required = true, position = 8)
|
||||
@NotBlank(message = "color不能为空")
|
||||
private String color;
|
||||
|
||||
/** 规则类型 */
|
||||
@ApiModelProperty(value = "规则类型", required = true, position = 8)
|
||||
@ApiModelProperty(value = "规则类型", required = true, position = 9)
|
||||
@NotBlank(message = "regType不能为空")
|
||||
private String regType;
|
||||
|
||||
/** 可用状态 */
|
||||
@ApiModelProperty(value = "可用状态", required = true, position = 9)
|
||||
@ApiModelProperty(value = "可用状态", required = true, position = 10)
|
||||
@NotBlank(message = "status不能为空")
|
||||
private String status;
|
||||
|
||||
/** 排序码 */
|
||||
@ApiModelProperty(value = "排序码", position = 10)
|
||||
@ApiModelProperty(value = "排序码", position = 11)
|
||||
private Integer sortCode;
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright [2022] [https://www.xiaonuo.vip]
|
||||
*
|
||||
* Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
|
||||
*
|
||||
* 1.请不要删除和修改根目录下的LICENSE文件。
|
||||
* 2.请不要删除和修改Snowy源码头部的版权声明。
|
||||
* 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
|
||||
* 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
|
||||
* 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
|
||||
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
||||
*/
|
||||
package vip.xiaonuo.mobile.modular.resource.param.menu;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* 移动端菜单更改所属模块参数
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2022/7/27 18:40
|
||||
**/
|
||||
@Getter
|
||||
@Setter
|
||||
public class MobileMenuChangeModuleParam {
|
||||
|
||||
/** id */
|
||||
@ApiModelProperty(value = "id", required = true)
|
||||
@NotBlank(message = "id不能为空")
|
||||
private String id;
|
||||
|
||||
/** 模块 */
|
||||
@ApiModelProperty(value = "module", required = true)
|
||||
@NotBlank(message = "module不能为空")
|
||||
private String module;
|
||||
}
|
|
@ -43,21 +43,26 @@ public class MobileMenuEditParam {
|
|||
@NotBlank(message = "title不能为空")
|
||||
private String title;
|
||||
|
||||
/** 界面路径 */
|
||||
@ApiModelProperty(value = "界面路径", required = true, position = 5)
|
||||
@NotBlank(message = "pages不能为空")
|
||||
private String pages;
|
||||
|
||||
/** 分类 */
|
||||
@ApiModelProperty(value = "分类", required = true, position = 6)
|
||||
@ApiModelProperty(value = "分类", required = true, position = 4)
|
||||
@NotBlank(message = "category不能为空")
|
||||
private String category;
|
||||
|
||||
/** 模块 */
|
||||
@ApiModelProperty(value = "模块", required = true, position = 7)
|
||||
@ApiModelProperty(value = "模块", required = true, position = 5)
|
||||
@NotBlank(message = "module不能为空")
|
||||
private String module;
|
||||
|
||||
/** 菜单类型 */
|
||||
@ApiModelProperty(value = "菜单类型", position = 6)
|
||||
@NotBlank(message = "menuType不能为空")
|
||||
private String menuType;
|
||||
|
||||
/** 路径 */
|
||||
@ApiModelProperty(value = "路径", position = 7)
|
||||
@NotBlank(message = "path不能为空")
|
||||
private String path;
|
||||
|
||||
/** 图标 */
|
||||
@ApiModelProperty(value = "图标", required = true, position = 8)
|
||||
@NotBlank(message = "icon不能为空")
|
||||
|
@ -81,5 +86,4 @@ public class MobileMenuEditParam {
|
|||
/** 排序码 */
|
||||
@ApiModelProperty(value = "排序码", position = 12)
|
||||
private Integer sortCode;
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright [2022] [https://www.xiaonuo.vip]
|
||||
*
|
||||
* Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
|
||||
*
|
||||
* 1.请不要删除和修改根目录下的LICENSE文件。
|
||||
* 2.请不要删除和修改Snowy源码头部的版权声明。
|
||||
* 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
|
||||
* 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
|
||||
* 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
|
||||
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
||||
*/
|
||||
package vip.xiaonuo.mobile.modular.resource.provider;
|
||||
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import org.springframework.stereotype.Service;
|
||||
import vip.xiaonuo.mobile.api.MobileMenuApi;
|
||||
import vip.xiaonuo.mobile.modular.resource.service.MobileMenuService;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 移动端菜单API接口提供者
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2023/1/31 10:12
|
||||
**/
|
||||
@Service
|
||||
public class MobileMenuApiProvider implements MobileMenuApi {
|
||||
|
||||
@Resource
|
||||
private MobileMenuService mobileMenuService;
|
||||
|
||||
@Override
|
||||
public List<JSONObject> mobileMenuTreeSelector() {
|
||||
return mobileMenuService.mobileMenuTreeSelector();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Tree<String>> loginMobileMenuTree(List<String> menuIdList) {
|
||||
return mobileMenuService.loginMobileMenuTree(menuIdList);
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@
|
|||
package vip.xiaonuo.mobile.modular.resource.service;
|
||||
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import vip.xiaonuo.mobile.modular.resource.entity.MobileMenu;
|
||||
import vip.xiaonuo.mobile.modular.resource.entity.MobileModule;
|
||||
|
@ -52,6 +53,14 @@ public interface MobileMenuService extends IService<MobileMenu> {
|
|||
*/
|
||||
void edit(MobileMenuEditParam mobileMenuEditParam);
|
||||
|
||||
/**
|
||||
* 更改移动端菜单所属模块
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2022/9/26 13:09
|
||||
**/
|
||||
void changeModule(MobileMenuChangeModuleParam mobileMenuChangeModuleParam);
|
||||
|
||||
/**
|
||||
* 删除移动端菜单
|
||||
*
|
||||
|
@ -76,6 +85,24 @@ public interface MobileMenuService extends IService<MobileMenu> {
|
|||
**/
|
||||
MobileMenu queryEntity(String id);
|
||||
|
||||
/* ====以下为各种递归方法==== */
|
||||
|
||||
/**
|
||||
* 根据id获取所有的子数据列表
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2022/8/2 14:52
|
||||
*/
|
||||
List<MobileMenu> getChildListById(List<MobileMenu> originDataList, String id, boolean includeSelf);
|
||||
|
||||
/**
|
||||
* 根据id获取所有的父数据列表
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2022/8/2 14:52
|
||||
*/
|
||||
List<MobileMenu> getParentListById(List<MobileMenu> originDataList, String id, boolean includeSelf);
|
||||
|
||||
/**
|
||||
* 获取模块选择器
|
||||
*
|
||||
|
@ -91,4 +118,20 @@ public interface MobileMenuService extends IService<MobileMenu> {
|
|||
* @date 2023/01/28 22:42
|
||||
**/
|
||||
List<Tree<String>> menuTreeSelector(MobileMenuSelectorMenuParam mobileMenuSelectorMenuParam);
|
||||
|
||||
/**
|
||||
* 获取移动端菜单授权树
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2023/1/31 10:14
|
||||
**/
|
||||
List<JSONObject> mobileMenuTreeSelector();
|
||||
|
||||
/**
|
||||
* 获取移动端登录菜单树
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2023/1/31 10:30
|
||||
**/
|
||||
List<Tree<String>> loginMobileMenuTree(List<String> menuIdList);
|
||||
}
|
||||
|
|
|
@ -14,10 +14,14 @@ package vip.xiaonuo.mobile.modular.resource.service.impl;
|
|||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollStreamUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
import cn.hutool.core.lang.tree.TreeNode;
|
||||
import cn.hutool.core.lang.tree.TreeUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
|
@ -31,9 +35,13 @@ import vip.xiaonuo.mobile.modular.resource.mapper.MobileMenuMapper;
|
|||
import vip.xiaonuo.mobile.modular.resource.param.menu.*;
|
||||
import vip.xiaonuo.mobile.modular.resource.service.MobileMenuService;
|
||||
import vip.xiaonuo.mobile.modular.resource.service.MobileModuleService;
|
||||
import vip.xiaonuo.sys.api.SysRelationApi;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
|
@ -48,6 +56,9 @@ public class MobileMenuServiceImpl extends ServiceImpl<MobileMenuMapper, MobileM
|
|||
@Resource
|
||||
private MobileModuleService mobileModuleService;
|
||||
|
||||
@Resource
|
||||
private SysRelationApi sysRelationApi;
|
||||
|
||||
@Override
|
||||
public List<Tree<String>> tree(MobileMenuTreeParam mobileMenuTreeParam) {
|
||||
LambdaQueryWrapper<MobileMenu> lambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
|
@ -70,6 +81,23 @@ public class MobileMenuServiceImpl extends ServiceImpl<MobileMenuMapper, MobileM
|
|||
@Override
|
||||
public void add(MobileMenuAddParam mobileMenuAddParam) {
|
||||
MobileMenu mobileMenu = BeanUtil.toBean(mobileMenuAddParam, MobileMenu.class);
|
||||
boolean repeatTitle = this.count(new LambdaQueryWrapper<MobileMenu>().eq(MobileMenu::getParentId, mobileMenu.getParentId())
|
||||
.eq(MobileMenu::getCategory, MobileResourceCategoryEnum.MENU.getValue()).eq(MobileMenu::getTitle, mobileMenu.getTitle())) > 0;
|
||||
if(repeatTitle) {
|
||||
throw new CommonException("存在重复的菜单,名称为:{}", mobileMenu.getTitle());
|
||||
}
|
||||
List<MobileMenu> originDataList = this.list(new LambdaQueryWrapper<MobileMenu>().eq(MobileMenu::getCategory,
|
||||
MobileResourceCategoryEnum.MENU.getValue()));
|
||||
if(!mobileMenuAddParam.getParentId().equals("0")) {
|
||||
MobileMenu parentMenu = this.getById(originDataList, mobileMenuAddParam.getParentId());
|
||||
if(ObjectUtil.isEmpty(parentMenu)) {
|
||||
throw new CommonException("上级菜单不存在,id值为:{}", mobileMenuAddParam.getParentId());
|
||||
}
|
||||
if(!parentMenu.getModule().equals(mobileMenuAddParam.getModule())) {
|
||||
throw new CommonException("module与上级菜单不一致");
|
||||
}
|
||||
}
|
||||
mobileMenu.setCategory(MobileResourceCategoryEnum.MENU.getValue());
|
||||
this.save(mobileMenu);
|
||||
}
|
||||
|
||||
|
@ -77,14 +105,62 @@ public class MobileMenuServiceImpl extends ServiceImpl<MobileMenuMapper, MobileM
|
|||
public void edit(MobileMenuEditParam mobileMenuEditParam) {
|
||||
MobileMenu mobileMenu = this.queryEntity(mobileMenuEditParam.getId());
|
||||
BeanUtil.copyProperties(mobileMenuEditParam, mobileMenu);
|
||||
boolean repeatTitle = this.count(new LambdaQueryWrapper<MobileMenu>().eq(MobileMenu::getParentId, mobileMenu.getParentId())
|
||||
.eq(MobileMenu::getCategory, MobileResourceCategoryEnum.MENU.getValue()).eq(MobileMenu::getTitle, mobileMenu.getTitle())
|
||||
.ne(MobileMenu::getId, mobileMenu.getId())) > 0;
|
||||
if(repeatTitle) {
|
||||
throw new CommonException("存在重复的菜单,名称为:{}", mobileMenu.getTitle());
|
||||
}
|
||||
List<MobileMenu> originDataList = this.list(new LambdaQueryWrapper<MobileMenu>().eq(MobileMenu::getCategory,
|
||||
MobileResourceCategoryEnum.MENU.getValue()));
|
||||
boolean errorLevel = this.getChildListById(originDataList, mobileMenu.getId(), true).stream()
|
||||
.map(MobileMenu::getId).collect(Collectors.toList()).contains(mobileMenu.getParentId());
|
||||
if(errorLevel) {
|
||||
throw new CommonException("不可选择上级菜单:{}", this.getById(originDataList, mobileMenu.getParentId()).getTitle());
|
||||
}
|
||||
if(!mobileMenuEditParam.getParentId().equals("0")) {
|
||||
MobileMenu parentMenu = this.getById(originDataList, mobileMenuEditParam.getParentId());
|
||||
if(ObjectUtil.isEmpty(parentMenu)) {
|
||||
throw new CommonException("上级菜单不存在,id值为:{}", mobileMenuEditParam.getParentId());
|
||||
}
|
||||
if(!parentMenu.getModule().equals(mobileMenuEditParam.getModule())) {
|
||||
throw new CommonException("module与上级菜单不一致");
|
||||
}
|
||||
}
|
||||
this.updateById(mobileMenu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeModule(MobileMenuChangeModuleParam mobileMenuChangeModuleParam) {
|
||||
MobileMenu mobileMenu = this.queryEntity(mobileMenuChangeModuleParam.getId());
|
||||
if(!mobileMenu.getParentId().equals("0")) {
|
||||
throw new CommonException("非顶级菜单不可修改所属模块");
|
||||
}
|
||||
List<MobileMenu> mobileMenuList = this.list(new LambdaQueryWrapper<MobileMenu>().eq(MobileMenu::getCategory,
|
||||
MobileResourceCategoryEnum.MENU.getValue()));
|
||||
List<MobileMenu> mobileMenuChildList = this.getChildListById(mobileMenuList, mobileMenu.getId(), true).stream()
|
||||
.peek(mobileMenuTemp -> mobileMenuTemp.setModule(mobileMenuChangeModuleParam.getModule())).collect(Collectors.toList());
|
||||
this.updateBatchById(mobileMenuChildList);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void delete(List<MobileMenuIdParam> mobileMenuIdParamList) {
|
||||
// 执行删除
|
||||
this.removeBatchByIds(CollStreamUtil.toList(mobileMenuIdParamList, MobileMenuIdParam::getId));
|
||||
List<String> mobileMenuIdList = CollStreamUtil.toList(mobileMenuIdParamList, MobileMenuIdParam::getId);
|
||||
if(ObjectUtil.isNotEmpty(mobileMenuIdList)) {
|
||||
// 获取菜单下的菜单
|
||||
List<MobileMenu> allMenuList = this.list(new LambdaQueryWrapper<MobileMenu>()
|
||||
.in(MobileMenu::getCategory, CollectionUtil.newArrayList(MobileResourceCategoryEnum.MENU.getValue())));
|
||||
List<String> toDeleteMenuIdList = CollectionUtil.newArrayList();
|
||||
mobileMenuIdList.forEach(menuId -> toDeleteMenuIdList.addAll(this.getChildListById(allMenuList, menuId, true).stream()
|
||||
.map(MobileMenu::getId).collect(Collectors.toList())));
|
||||
if(ObjectUtil.isNotEmpty(toDeleteMenuIdList)) {
|
||||
// 清除对应的角色与移动端资源信息
|
||||
sysRelationApi.removeRoleHasMobileMenuRelationByMenuIdList(toDeleteMenuIdList);
|
||||
// 执行删除
|
||||
this.removeBatchByIds(toDeleteMenuIdList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -120,10 +196,270 @@ public class MobileMenuServiceImpl extends ServiceImpl<MobileMenuMapper, MobileM
|
|||
lambdaQueryWrapper.eq(MobileMenu::getModule, mobileMenuSelectorMenuParam.getModule());
|
||||
}
|
||||
List<MobileMenu> resourceList = this.list(lambdaQueryWrapper);
|
||||
List<TreeNode<String>> treeNodeList = resourceList.stream().map(sysMenu ->
|
||||
new TreeNode<>(sysMenu.getId(), sysMenu.getParentId(),
|
||||
sysMenu.getTitle(), sysMenu.getSortCode()).setExtra(JSONUtil.parseObj(sysMenu)))
|
||||
List<TreeNode<String>> treeNodeList = resourceList.stream().map(mobileMenu ->
|
||||
new TreeNode<>(mobileMenu.getId(), mobileMenu.getParentId(),
|
||||
mobileMenu.getTitle(), mobileMenu.getSortCode()).setExtra(JSONUtil.parseObj(mobileMenu)))
|
||||
.collect(Collectors.toList());
|
||||
return TreeUtil.build(treeNodeList, "0");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JSONObject> mobileMenuTreeSelector() {
|
||||
LambdaQueryWrapper<MobileMenu> lambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
lambdaQueryWrapper.in(MobileMenu::getCategory, MobileResourceCategoryEnum.MODULE.getValue(), MobileResourceCategoryEnum.MENU.getValue());
|
||||
List<MobileMenu> allModuleAndMenuList = this.list(lambdaQueryWrapper);
|
||||
List<MobileMenu> mobileModuleList = CollectionUtil.newArrayList();
|
||||
List<MobileMenu> mobileMenuList = CollectionUtil.newArrayList();
|
||||
allModuleAndMenuList.forEach(mobileMenu -> {
|
||||
if (mobileMenu.getCategory().equals(MobileResourceCategoryEnum.MODULE.getValue())) mobileModuleList.add(mobileMenu);
|
||||
if (mobileMenu.getCategory().equals(MobileResourceCategoryEnum.MENU.getValue())) mobileMenuList.add(mobileMenu);
|
||||
});
|
||||
List<JSONObject> leafMenuList = CollectionUtil.newArrayList();
|
||||
MobileMenu rootMobileMenu = new MobileMenu();
|
||||
rootMobileMenu.setId("0");
|
||||
rootMobileMenu.setParentId("-1");
|
||||
rootMobileMenu.setSortCode(-1);
|
||||
mobileMenuList.add(rootMobileMenu);
|
||||
List<TreeNode<String>> treeNodeList = mobileMenuList.stream().map(mobileMenu ->
|
||||
new TreeNode<>(mobileMenu.getId(), mobileMenu.getParentId(),
|
||||
mobileMenu.getTitle(), mobileMenu.getSortCode())).collect(Collectors.toList());
|
||||
List<Tree<String>> treeList = TreeUtil.build(treeNodeList, "-1");
|
||||
mobileMenuList.forEach(mobileMenu -> {
|
||||
boolean isLeafMenu = this.getChildListById(mobileMenuList, mobileMenu.getId(), false).size() == 0;
|
||||
if(isLeafMenu) {
|
||||
JSONObject mobileRoleGrantResourceMenuResult = JSONUtil.createObj();
|
||||
BeanUtil.copyProperties(mobileMenu, mobileRoleGrantResourceMenuResult);
|
||||
JSONObject parentJsonObject = getParentNode(treeList, mobileMenu);
|
||||
List<String> parentIdSplitList = StrUtil.split(parentJsonObject.getStr("parentId"), StrUtil.DASHED);
|
||||
List<String> parentNameSplitList = StrUtil.split(parentJsonObject.getStr("parentName"), StrUtil.DASHED);
|
||||
if(parentNameSplitList.size() > 1) {
|
||||
mobileRoleGrantResourceMenuResult.set("parentId", parentIdSplitList.get(3));
|
||||
mobileRoleGrantResourceMenuResult.set("parentName", parentNameSplitList.get(0));
|
||||
StringBuilder selfNamePrefix = new StringBuilder();
|
||||
for(int i = 1; i< parentNameSplitList.size(); i++) {
|
||||
selfNamePrefix.append(parentNameSplitList.get(i)).append(StrUtil.DASHED);
|
||||
}
|
||||
mobileRoleGrantResourceMenuResult.set("title", selfNamePrefix + mobileRoleGrantResourceMenuResult.getStr("title"));
|
||||
} else {
|
||||
mobileRoleGrantResourceMenuResult.set("parentName", parentJsonObject.getStr("parentName"));
|
||||
}
|
||||
leafMenuList.add(mobileRoleGrantResourceMenuResult);
|
||||
}
|
||||
});
|
||||
Map<String, List<JSONObject>> menuListGroup = leafMenuList.stream()
|
||||
.collect(Collectors.groupingBy(jsonObject -> jsonObject.getStr("module")));
|
||||
return mobileModuleList.stream().map(mobileModule -> {
|
||||
JSONObject mobileRoleGrantResourceTreeResult = JSONUtil.createObj();
|
||||
mobileRoleGrantResourceTreeResult.set("id", mobileModule.getId());
|
||||
mobileRoleGrantResourceTreeResult.set("title", mobileModule.getTitle());
|
||||
mobileRoleGrantResourceTreeResult.set("icon", mobileModule.getIcon());
|
||||
mobileRoleGrantResourceTreeResult.set("menu", menuListGroup.get(mobileModule.getId()));
|
||||
return mobileRoleGrantResourceTreeResult;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Tree<String>> loginMobileMenuTree(List<String> menuIdList) {
|
||||
// 获取所有的菜单和模块以及单页面列表,并按分类和排序码排序
|
||||
List<MobileMenu> allModuleAndMenuAndSpaList = this.list(new LambdaQueryWrapper<MobileMenu>()
|
||||
.in(MobileMenu::getCategory, MobileResourceCategoryEnum.MODULE.getValue(), MobileResourceCategoryEnum.MENU.getValue())
|
||||
.orderByAsc(CollectionUtil.newArrayList(MobileMenu::getCategory, MobileMenu::getSortCode)));
|
||||
// 全部以菜单承载
|
||||
List<MobileMenu> allModuleList = CollectionUtil.newArrayList();
|
||||
List<MobileMenu> allMenuList = CollectionUtil.newArrayList();
|
||||
// 根据类型抽取
|
||||
allModuleAndMenuAndSpaList.forEach(mobileMenu -> {
|
||||
boolean isModule = mobileMenu.getCategory().equals(MobileResourceCategoryEnum.MODULE.getValue());
|
||||
if (isModule) {
|
||||
// 抽取所有的模块列表
|
||||
allModuleList.add(mobileMenu);
|
||||
}
|
||||
boolean isMenu = mobileMenu.getCategory().equals(MobileResourceCategoryEnum.MENU.getValue());
|
||||
if (isMenu) {
|
||||
// 抽取所有的菜单列表
|
||||
allMenuList.add(mobileMenu);
|
||||
}
|
||||
});
|
||||
|
||||
// 定义结果
|
||||
List<MobileMenu> resultList = CollectionUtil.newArrayList();
|
||||
|
||||
// 获取拥有的菜单列表
|
||||
List<MobileMenu> menuList = allMenuList.stream().filter(mobileMenu ->
|
||||
menuIdList.contains(mobileMenu.getId())).collect(Collectors.toList());
|
||||
|
||||
// 对获取到的角色对应的菜单列表进行处理,获取父列表
|
||||
menuList.forEach(mobileMenu -> execRecursionFindParent(allMenuList, mobileMenu.getId(), resultList));
|
||||
|
||||
// 将拥有的菜单列表添加
|
||||
resultList.addAll(menuList);
|
||||
|
||||
// 获取模块id集合
|
||||
Set<String> moduleIdSet = resultList.stream().map(MobileMenu::getModule).collect(Collectors.toSet());
|
||||
|
||||
// 抽取拥有的模块列表
|
||||
List<MobileMenu> moduleList = allModuleList.stream().filter(mobileMenu ->
|
||||
moduleIdSet.contains(mobileMenu.getId())).collect(Collectors.toList());
|
||||
|
||||
// 如果一个模块都没拥有
|
||||
if (ObjectUtil.isEmpty(moduleList)) {
|
||||
// 返回空列表
|
||||
return CollectionUtil.newArrayList();
|
||||
}
|
||||
|
||||
// 将拥有的模块放入集合
|
||||
resultList.addAll(moduleList);
|
||||
|
||||
// 最终处理,构造meta
|
||||
List<JSONObject> resultJsonObjectList = resultList.stream().map(mobileMenu -> {
|
||||
|
||||
// 将模块的父id设置为0,设置随机pages
|
||||
if (mobileMenu.getCategory().equals(MobileResourceCategoryEnum.MODULE.getValue())) {
|
||||
mobileMenu.setParentId("0");
|
||||
mobileMenu.setPath(StrUtil.SLASH + RandomUtil.randomString(10));
|
||||
}
|
||||
// 将根菜单的父id设置为模块的id
|
||||
if (mobileMenu.getCategory().equals(MobileResourceCategoryEnum.MENU.getValue())) {
|
||||
if (mobileMenu.getParentId().equals("0")) {
|
||||
mobileMenu.setParentId(mobileMenu.getModule());
|
||||
}
|
||||
}
|
||||
JSONObject menuJsonObject = JSONUtil.parseObj(mobileMenu);
|
||||
JSONObject metaJsonObject = JSONUtil.createObj();
|
||||
metaJsonObject.set("icon", mobileMenu.getIcon());
|
||||
metaJsonObject.set("title", mobileMenu.getTitle());
|
||||
metaJsonObject.set("type", mobileMenu.getCategory().toLowerCase());
|
||||
// 如果是菜单,则设置type菜单类型为小写
|
||||
if (mobileMenu.getCategory().equals(MobileResourceCategoryEnum.MENU.getValue())) {
|
||||
metaJsonObject.set("type", mobileMenu.getMenuType().toLowerCase());
|
||||
}
|
||||
menuJsonObject.set("meta", metaJsonObject);
|
||||
return menuJsonObject;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
// 执行构造树
|
||||
List<TreeNode<String>> treeNodeList = resultJsonObjectList.stream().map(jsonObject ->
|
||||
new TreeNode<>(jsonObject.getStr("id"), jsonObject.getStr("parentId"),
|
||||
jsonObject.getStr("title"), jsonObject.getInt("sortCode")).setExtra(JSONUtil.parseObj(jsonObject)))
|
||||
.collect(Collectors.toList());
|
||||
return TreeUtil.build(treeNodeList, "0");
|
||||
}
|
||||
|
||||
/* ====以下为各种递归方法==== */
|
||||
|
||||
public JSONObject getParentNode(List<Tree<String>> treeList, MobileMenu mobileMenu) {
|
||||
List<Tree<String>> resultList = CollectionUtil.newArrayList();
|
||||
getNode(treeList, mobileMenu.getId(), resultList);
|
||||
JSONObject jsonObject = JSONUtil.createObj();
|
||||
if(ObjectUtil.isNotEmpty(resultList)) {
|
||||
Tree<String> currentNode = resultList.get(0);
|
||||
if(currentNode.getId().equals("0") || currentNode.getParentId().equals("0")) {
|
||||
jsonObject.set("parentId", mobileMenu.getId());
|
||||
jsonObject.set("parentName", mobileMenu.getTitle());
|
||||
} else {
|
||||
jsonObject.set("parentId", StrUtil.join(StrUtil.DASHED, CollectionUtil.reverse(CollectionUtil
|
||||
.removeNull(this.getParentsId(currentNode, false)))));
|
||||
jsonObject.set("parentName", StrUtil.join(StrUtil.DASHED, CollectionUtil.reverse(CollectionUtil
|
||||
.removeNull(TreeUtil.getParentsName(currentNode, false)))));
|
||||
}
|
||||
} else {
|
||||
jsonObject.set("parentId", mobileMenu.getId());
|
||||
jsonObject.set("parentName", mobileMenu.getTitle());
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
public List<String> getParentsId(Tree<String> node, boolean includeCurrentNode) {
|
||||
final List<String> result = new ArrayList<>();
|
||||
if (null == node) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (includeCurrentNode) {
|
||||
result.add(node.getId());
|
||||
}
|
||||
|
||||
Tree<String> parent = node.getParent();
|
||||
while (null != parent) {
|
||||
result.add(parent.getId());
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void getNode(List<Tree<String>> treeList, String id, List<Tree<String>> resultList) {
|
||||
for (Tree<String> tree: treeList) {
|
||||
if(tree.getId().equals(id)) {
|
||||
resultList.add(tree);
|
||||
break;
|
||||
} else {
|
||||
List<Tree<String>> children = tree.getChildren();
|
||||
if(ObjectUtil.isNotEmpty(children)) {
|
||||
getNode(children, id, resultList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MobileMenu> getChildListById(List<MobileMenu> originDataList, String id, boolean includeSelf) {
|
||||
List<MobileMenu> resultList = CollectionUtil.newArrayList();
|
||||
execRecursionFindChild(originDataList, id, resultList);
|
||||
if(includeSelf) {
|
||||
MobileMenu self = this.getById(originDataList, id);
|
||||
if(ObjectUtil.isNotEmpty(self)) {
|
||||
resultList.add(self);
|
||||
}
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MobileMenu> getParentListById(List<MobileMenu> originDataList, String id, boolean includeSelf) {
|
||||
List<MobileMenu> resultList = CollectionUtil.newArrayList();
|
||||
execRecursionFindParent(originDataList, id, resultList);
|
||||
if(includeSelf) {
|
||||
MobileMenu self = this.getById(originDataList, id);
|
||||
if(ObjectUtil.isNotEmpty(self)) {
|
||||
resultList.add(self);
|
||||
}
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
public void execRecursionFindChild(List<MobileMenu> originDataList, String id, List<MobileMenu> resultList) {
|
||||
originDataList.forEach(item -> {
|
||||
if(item.getParentId().equals(id)) {
|
||||
resultList.add(item);
|
||||
execRecursionFindChild(originDataList, item.getId(), resultList);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void execRecursionFindParent(List<MobileMenu> originDataList, String id, List<MobileMenu> resultList) {
|
||||
originDataList.forEach(item -> {
|
||||
if(item.getId().equals(id)) {
|
||||
MobileMenu parent = this.getById(originDataList, item.getParentId());
|
||||
if(ObjectUtil.isNotEmpty(parent)) {
|
||||
resultList.add(parent);
|
||||
}
|
||||
execRecursionFindParent(originDataList, item.getParentId(), resultList);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public MobileMenu getById(List<MobileMenu> originDataList, String id) {
|
||||
int index = CollStreamUtil.toList(originDataList, MobileMenu::getId).indexOf(id);
|
||||
return index == -1?null:originDataList.get(index);
|
||||
}
|
||||
|
||||
public MobileMenu getParentById(List<MobileMenu> originDataList, String id) {
|
||||
MobileMenu self = this.getById(originDataList, id);
|
||||
return ObjectUtil.isNotEmpty(self)?self:this.getById(originDataList, self.getParentId());
|
||||
}
|
||||
|
||||
public MobileMenu getChildById(List<MobileMenu> originDataList, String id) {
|
||||
int index = CollStreamUtil.toList(originDataList, MobileMenu::getParentId).indexOf(id);
|
||||
return index == -1?null:originDataList.get(index);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
package vip.xiaonuo.mobile.modular.resource.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollStreamUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
@ -24,6 +26,7 @@ import org.springframework.stereotype.Service;
|
|||
import vip.xiaonuo.common.enums.CommonSortOrderEnum;
|
||||
import vip.xiaonuo.common.exception.CommonException;
|
||||
import vip.xiaonuo.common.page.CommonPageRequest;
|
||||
import vip.xiaonuo.mobile.modular.resource.entity.MobileMenu;
|
||||
import vip.xiaonuo.mobile.modular.resource.entity.MobileModule;
|
||||
import vip.xiaonuo.mobile.modular.resource.enums.MobileResourceCategoryEnum;
|
||||
import vip.xiaonuo.mobile.modular.resource.mapper.MobileModuleMapper;
|
||||
|
@ -33,9 +36,11 @@ import vip.xiaonuo.mobile.modular.resource.param.module.MobileModuleIdParam;
|
|||
import vip.xiaonuo.mobile.modular.resource.param.module.MobileModulePageParam;
|
||||
import vip.xiaonuo.mobile.modular.resource.service.MobileMenuService;
|
||||
import vip.xiaonuo.mobile.modular.resource.service.MobileModuleService;
|
||||
import vip.xiaonuo.sys.api.SysRelationApi;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 模块Service接口实现类
|
||||
|
@ -49,10 +54,8 @@ public class MobileModuleServiceImpl extends ServiceImpl<MobileModuleMapper, Mob
|
|||
@Resource
|
||||
private MobileMenuService mobileMenuService;
|
||||
|
||||
/*
|
||||
@Resource
|
||||
private MobileRelationService mobileRelationService;
|
||||
*/
|
||||
private SysRelationApi sysRelationApi;
|
||||
|
||||
@Override
|
||||
public Page<MobileModule> page(MobileModulePageParam mobileModulePageParam) {
|
||||
|
@ -99,16 +102,10 @@ public class MobileModuleServiceImpl extends ServiceImpl<MobileModuleMapper, Mob
|
|||
|
||||
@Override
|
||||
public void delete(List<MobileModuleIdParam> mobileModuleIdParamList) {
|
||||
/*List<String> mobileModuleIdList = CollStreamUtil.toList(mobileModuleIdParamList, MobileModuleIdParam::getId);
|
||||
List<String> mobileModuleIdList = CollStreamUtil.toList(mobileModuleIdParamList, MobileModuleIdParam::getId);
|
||||
if(ObjectUtil.isNotEmpty(mobileModuleIdList)) {
|
||||
boolean containsMobiletemModule = this.listByIds(mobileModuleIdList).stream().map(MobileModule::getCode)
|
||||
.collect(Collectors.toSet()).contains(MobileBuildInEnum.BUILD_IN_MODULE_CODE.getValue());
|
||||
if(containsMobiletemModule) {
|
||||
throw new CommonException("不可删除系统内置模块");
|
||||
}
|
||||
|
||||
// 获取模块下的菜单
|
||||
List<MobileMenu> allMenuList = mobileMenuService.list(new LambdaUpdateWrapper<MobileMenu>()
|
||||
List<MobileMenu> allMenuList = mobileMenuService.list(new LambdaQueryWrapper<MobileMenu>()
|
||||
.in(MobileMenu::getCategory, CollectionUtil.newArrayList(MobileResourceCategoryEnum.MENU.getValue())));
|
||||
if(ObjectUtil.isNotEmpty(allMenuList)) {
|
||||
List<String> toDeleteMenuIdList = CollectionUtil.newArrayList(mobileModuleIdList);
|
||||
|
@ -118,14 +115,12 @@ public class MobileModuleServiceImpl extends ServiceImpl<MobileModuleMapper, Mob
|
|||
.map(MobileMenu::getId).collect(Collectors.toList())));
|
||||
if(ObjectUtil.isNotEmpty(toDeleteMenuIdList)) {
|
||||
// 清除对应的角色与移动端资源信息
|
||||
mobileRelationService.remove(new LambdaUpdateWrapper<MobileRelation>().in(MobileRelation::getTargetId, toDeleteMenuIdList)
|
||||
.eq(MobileRelation::getCategory, MobileRelationCategoryEnum.MOBILE_ROLE_HAS_RESOURCE.getValue()));
|
||||
sysRelationApi.removeRoleHasMobileMenuRelationByMenuIdList(toDeleteMenuIdList);
|
||||
// 执行删除
|
||||
this.removeBatchByIds(toDeleteMenuIdList);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -35,5 +35,12 @@
|
|||
<artifactId>snowy-plugin-dev-api</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 引入移动端接口,用于移动端菜单信息 -->
|
||||
<dependency>
|
||||
<groupId>vip.xiaonuo</groupId>
|
||||
<artifactId>snowy-plugin-mobile-api</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -16,7 +16,6 @@ import cn.dev33.satoken.stp.StpUtil;
|
|||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import vip.xiaonuo.auth.core.pojo.SaBaseLoginUser;
|
||||
import vip.xiaonuo.auth.core.util.StpLoginUserUtil;
|
||||
|
|
|
@ -36,7 +36,7 @@ public enum SysRelationCategoryEnum {
|
|||
SYS_ROLE_HAS_RESOURCE("SYS_ROLE_HAS_RESOURCE"),
|
||||
|
||||
/** 角色拥有移动端菜单 */
|
||||
SYS_ROLE_HAS_MENU_MOBILE("SYS_ROLE_HAS_MOBILE_MENU"),
|
||||
SYS_ROLE_HAS_MOBILE_MENU("SYS_ROLE_HAS_MOBILE_MENU"),
|
||||
|
||||
/** 角色拥有权限 */
|
||||
SYS_ROLE_HAS_PERMISSION("SYS_ROLE_HAS_PERMISSION");
|
||||
|
|
|
@ -12,8 +12,10 @@
|
|||
*/
|
||||
package vip.xiaonuo.sys.modular.relation.provider;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import vip.xiaonuo.sys.api.SysRelationApi;
|
||||
import vip.xiaonuo.sys.modular.relation.entity.SysRelation;
|
||||
import vip.xiaonuo.sys.modular.relation.enums.SysRelationCategoryEnum;
|
||||
import vip.xiaonuo.sys.modular.relation.service.SysRelationService;
|
||||
|
||||
|
@ -37,4 +39,10 @@ public class SysRelationApiProvider implements SysRelationApi {
|
|||
return sysRelationService.getRelationObjectIdListByTargetIdListAndCategory(roleIdList,
|
||||
SysRelationCategoryEnum.SYS_USER_HAS_ROLE.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRoleHasMobileMenuRelationByMenuIdList(List<String> targetIdList) {
|
||||
sysRelationService.remove(new LambdaQueryWrapper<SysRelation>().in(SysRelation::getTargetId, targetIdList)
|
||||
.eq(SysRelation::getCategory, SysRelationCategoryEnum.SYS_ROLE_HAS_MOBILE_MENU.getValue()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,9 +28,7 @@ import vip.xiaonuo.common.pojo.CommonResult;
|
|||
import vip.xiaonuo.common.pojo.CommonValidList;
|
||||
import vip.xiaonuo.sys.modular.role.entity.SysRole;
|
||||
import vip.xiaonuo.sys.modular.role.param.*;
|
||||
import vip.xiaonuo.sys.modular.role.result.SysRoleGrantResourceTreeResult;
|
||||
import vip.xiaonuo.sys.modular.role.result.SysRoleOwnPermissionResult;
|
||||
import vip.xiaonuo.sys.modular.role.result.SysRoleOwnResourceResult;
|
||||
import vip.xiaonuo.sys.modular.role.result.*;
|
||||
import vip.xiaonuo.sys.modular.role.service.SysRoleService;
|
||||
import vip.xiaonuo.sys.modular.user.entity.SysUser;
|
||||
|
||||
|
@ -163,7 +161,7 @@ public class SysRoleController {
|
|||
@ApiOperationSupport(order = 8)
|
||||
@ApiOperation("获取角色拥有移动端菜单")
|
||||
@GetMapping("/sys/role/ownMobileMenu")
|
||||
public CommonResult<SysRoleOwnResourceResult> ownMobileMenu(@Valid SysRoleIdParam sysRoleIdParam) {
|
||||
public CommonResult<SysRoleOwnMobileMenuResult> ownMobileMenu(@Valid SysRoleIdParam sysRoleIdParam) {
|
||||
return CommonResult.data(sysRoleService.ownMobileMenu(sysRoleIdParam));
|
||||
}
|
||||
|
||||
|
@ -267,12 +265,25 @@ public class SysRoleController {
|
|||
}
|
||||
|
||||
/**
|
||||
* 获取权限授权树
|
||||
* 获取移动端菜单授权树
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2022/4/24 20:00
|
||||
*/
|
||||
@ApiOperationSupport(order = 16)
|
||||
@ApiOperation("获取移动端菜单授权树")
|
||||
@GetMapping("/sys/role/mobileMenuTreeSelector")
|
||||
public CommonResult<List<SysRoleGrantMobileMenuTreeResult>> mobileMenuTreeSelector() {
|
||||
return CommonResult.data(sysRoleService.mobileMenuTreeSelector());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取权限授权树
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2022/4/24 20:00
|
||||
*/
|
||||
@ApiOperationSupport(order = 17)
|
||||
@ApiOperation("获取权限授权树")
|
||||
@GetMapping("/sys/role/permissionTreeSelector")
|
||||
public CommonResult<List<String>> permissionTreeSelector() {
|
||||
|
@ -285,7 +296,7 @@ public class SysRoleController {
|
|||
* @author xuyuxiang
|
||||
* @date 2022/4/24 20:00
|
||||
*/
|
||||
@ApiOperationSupport(order = 17)
|
||||
@ApiOperationSupport(order = 18)
|
||||
@ApiOperation("获取角色选择器")
|
||||
@GetMapping("/sys/role/roleSelector")
|
||||
public CommonResult<List<SysRole>> roleSelector(SysRoleSelectorRoleParam sysRoleSelectorRoleParam) {
|
||||
|
@ -298,7 +309,7 @@ public class SysRoleController {
|
|||
* @author xuyuxiang
|
||||
* @date 2022/4/24 20:00
|
||||
*/
|
||||
@ApiOperationSupport(order = 18)
|
||||
@ApiOperationSupport(order = 19)
|
||||
@ApiOperation("获取用户选择器")
|
||||
@GetMapping("/sys/role/userSelector")
|
||||
public CommonResult<List<SysUser>> userSelector(SysRoleSelectorUserParam sysRoleSelectorUserParam) {
|
||||
|
|
|
@ -28,12 +28,12 @@ import java.util.List;
|
|||
@Setter
|
||||
public class SysRoleGrantMobileMenuTreeResult {
|
||||
|
||||
/** 分类id */
|
||||
@ApiModelProperty(value = "分类id", position = 1)
|
||||
/** 模块id */
|
||||
@ApiModelProperty(value = "模块id", position = 1)
|
||||
private String id;
|
||||
|
||||
/** 分类名称*/
|
||||
@ApiModelProperty(value = "分类名称", position = 2)
|
||||
/** 模块名称*/
|
||||
@ApiModelProperty(value = "模块名称", position = 2)
|
||||
private String title;
|
||||
|
||||
/** 模块图标 */
|
||||
|
@ -73,28 +73,5 @@ public class SysRoleGrantMobileMenuTreeResult {
|
|||
/** 模块 */
|
||||
@ApiModelProperty(value = "菜单模块", position = 5)
|
||||
private String module;
|
||||
|
||||
/** 菜单下按钮集合 */
|
||||
@ApiModelProperty(value = "菜单下按钮集合", position = 6)
|
||||
private List<SysRoleGrantResourceButtonResult> button;
|
||||
|
||||
/**
|
||||
* 授权按钮类
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2022/8/13 16:54
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public static class SysRoleGrantResourceButtonResult {
|
||||
|
||||
/** 按钮id */
|
||||
@ApiModelProperty(value = "按钮id", position = 1)
|
||||
private String id;
|
||||
|
||||
/** 标题 */
|
||||
@ApiModelProperty(value = "按钮标题", position = 2)
|
||||
private String title;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,9 +17,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import vip.xiaonuo.sys.modular.role.entity.SysRole;
|
||||
import vip.xiaonuo.sys.modular.role.param.*;
|
||||
import vip.xiaonuo.sys.modular.role.result.SysRoleGrantResourceTreeResult;
|
||||
import vip.xiaonuo.sys.modular.role.result.SysRoleOwnPermissionResult;
|
||||
import vip.xiaonuo.sys.modular.role.result.SysRoleOwnResourceResult;
|
||||
import vip.xiaonuo.sys.modular.role.result.*;
|
||||
import vip.xiaonuo.sys.modular.user.entity.SysUser;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -102,7 +100,7 @@ public interface SysRoleService extends IService<SysRole> {
|
|||
* @author xuyuxiang
|
||||
* @date 2022/5/13 20:51
|
||||
*/
|
||||
SysRoleOwnResourceResult ownMobileMenu(SysRoleIdParam SysRoleIdParam);
|
||||
SysRoleOwnMobileMenuResult ownMobileMenu(SysRoleIdParam SysRoleIdParam);
|
||||
|
||||
/**
|
||||
* 给角色授权移动端菜单
|
||||
|
@ -162,6 +160,14 @@ public interface SysRoleService extends IService<SysRole> {
|
|||
*/
|
||||
List<SysRoleGrantResourceTreeResult> resourceTreeSelector();
|
||||
|
||||
/**
|
||||
* 获取移动端菜单授权树
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2022/4/24 20:08
|
||||
*/
|
||||
List<SysRoleGrantMobileMenuTreeResult> mobileMenuTreeSelector();
|
||||
|
||||
/**
|
||||
* 获取权限授权树
|
||||
*
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl
|
|||
import vip.xiaonuo.common.enums.CommonSortOrderEnum;
|
||||
import vip.xiaonuo.common.exception.CommonException;
|
||||
import vip.xiaonuo.common.page.CommonPageRequest;
|
||||
import vip.xiaonuo.mobile.api.MobileMenuApi;
|
||||
import vip.xiaonuo.sys.core.enums.SysBuildInEnum;
|
||||
import vip.xiaonuo.sys.modular.org.entity.SysOrg;
|
||||
import vip.xiaonuo.sys.modular.org.service.SysOrgService;
|
||||
|
@ -51,9 +52,7 @@ import vip.xiaonuo.sys.modular.role.entity.SysRole;
|
|||
import vip.xiaonuo.sys.modular.role.enums.SysRoleCategoryEnum;
|
||||
import vip.xiaonuo.sys.modular.role.mapper.SysRoleMapper;
|
||||
import vip.xiaonuo.sys.modular.role.param.*;
|
||||
import vip.xiaonuo.sys.modular.role.result.SysRoleGrantResourceTreeResult;
|
||||
import vip.xiaonuo.sys.modular.role.result.SysRoleOwnPermissionResult;
|
||||
import vip.xiaonuo.sys.modular.role.result.SysRoleOwnResourceResult;
|
||||
import vip.xiaonuo.sys.modular.role.result.*;
|
||||
import vip.xiaonuo.sys.modular.role.service.SysRoleService;
|
||||
import vip.xiaonuo.sys.modular.user.entity.SysUser;
|
||||
import vip.xiaonuo.sys.modular.user.service.SysUserService;
|
||||
|
@ -85,6 +84,9 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
|
|||
@Resource
|
||||
private SysUserService sysUserService;
|
||||
|
||||
@Resource
|
||||
private MobileMenuApi mobileMenuApi;
|
||||
|
||||
@Override
|
||||
public Page<SysRole> page(SysRolePageParam sysRolePageParam) {
|
||||
QueryWrapper<SysRole> queryWrapper = new QueryWrapper<>();
|
||||
|
@ -212,14 +214,24 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
|
|||
}
|
||||
|
||||
@Override
|
||||
public SysRoleOwnResourceResult ownMobileMenu(SysRoleIdParam SysRoleIdParam) {
|
||||
// TODO
|
||||
return null;
|
||||
public SysRoleOwnMobileMenuResult ownMobileMenu(SysRoleIdParam sysRoleIdParam) {
|
||||
SysRoleOwnMobileMenuResult sysRoleOwnMobileMenuResult = new SysRoleOwnMobileMenuResult();
|
||||
sysRoleOwnMobileMenuResult.setId(sysRoleIdParam.getId());
|
||||
sysRoleOwnMobileMenuResult.setGrantInfoList(sysRelationService.getRelationListByObjectIdAndCategory(sysRoleIdParam.getId(),
|
||||
SysRelationCategoryEnum.SYS_ROLE_HAS_MOBILE_MENU.getValue()).stream().map(sysRelation ->
|
||||
JSONUtil.toBean(sysRelation.getExtJson(), SysRoleOwnMobileMenuResult.SysRoleOwnMobileMenu.class)).collect(Collectors.toList()));
|
||||
return sysRoleOwnMobileMenuResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void grantMobileMenu(SysRoleGrantMobileMenuParam sysRoleGrantMobileMenuParam) {
|
||||
// TODO
|
||||
String id = sysRoleGrantMobileMenuParam.getId();
|
||||
List<String> menuIdList = sysRoleGrantMobileMenuParam.getGrantInfoList().stream()
|
||||
.map(SysRoleGrantMobileMenuParam.SysRoleGrantMobileMenu::getMenuId).collect(Collectors.toList());
|
||||
List<String> extJsonList = sysRoleGrantMobileMenuParam.getGrantInfoList().stream()
|
||||
.map(JSONUtil::toJsonStr).collect(Collectors.toList());
|
||||
sysRelationService.saveRelationBatchWithClear(id, menuIdList, SysRelationCategoryEnum.SYS_ROLE_HAS_MOBILE_MENU.getValue(),
|
||||
extJsonList);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -353,6 +365,11 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
|
|||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SysRoleGrantMobileMenuTreeResult> mobileMenuTreeSelector() {
|
||||
return BeanUtil.copyToList(mobileMenuApi.mobileMenuTreeSelector(), SysRoleGrantMobileMenuTreeResult.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> permissionTreeSelector() {
|
||||
List<String> permissionResult = CollectionUtil.newArrayList();
|
||||
|
|
|
@ -56,6 +56,7 @@ import vip.xiaonuo.dev.api.DevConfigApi;
|
|||
import vip.xiaonuo.dev.api.DevEmailApi;
|
||||
import vip.xiaonuo.dev.api.DevMessageApi;
|
||||
import vip.xiaonuo.dev.api.DevSmsApi;
|
||||
import vip.xiaonuo.mobile.api.MobileMenuApi;
|
||||
import vip.xiaonuo.sys.core.enums.SysBuildInEnum;
|
||||
import vip.xiaonuo.sys.modular.org.entity.SysOrg;
|
||||
import vip.xiaonuo.sys.modular.org.service.SysOrgService;
|
||||
|
@ -124,6 +125,9 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||
@Resource
|
||||
private DevMessageApi devMessageApi;
|
||||
|
||||
@Resource
|
||||
private MobileMenuApi mobileMenuApi;
|
||||
|
||||
@Resource
|
||||
private SysOrgService sysOrgService;
|
||||
|
||||
|
@ -679,8 +683,14 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||
|
||||
@Override
|
||||
public List<Tree<String>> ownMobileMenu(SysUserIdParam sysUserIdParam) {
|
||||
// TODO 获取移动菜单树
|
||||
return null;
|
||||
// 获取角色id列表
|
||||
List<String> roleIdList = this.ownRole(sysUserIdParam);
|
||||
List<Tree<String>> resultList = CollectionUtil.newArrayList();
|
||||
if (ObjectUtil.isNotEmpty(roleIdList)) {
|
||||
resultList = mobileMenuApi.loginMobileMenuTree(sysRelationService.getRelationTargetIdListByObjectIdListAndCategory(roleIdList,
|
||||
SysRelationCategoryEnum.SYS_ROLE_HAS_RESOURCE.getValue()));
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -168,6 +168,8 @@ public class GlobalConfigure implements WebMvcConfigurer {
|
|||
"/dev/sms/page",
|
||||
"/dev/sms/delete",
|
||||
"/dev/sms/detail",
|
||||
"/mobile/menu/**",
|
||||
"/mobile/module/**",
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -10,9 +10,10 @@ CREATE TABLE `mobile_resource` (
|
|||
`PARENT_ID` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '父ID',
|
||||
`TITLE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '名称',
|
||||
`CODE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '编码',
|
||||
`PAGES` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '界面路径',
|
||||
`CATEGORY` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '分类',
|
||||
`MODULE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '模块',
|
||||
`MENU_TYPE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '菜单类型',
|
||||
`PATH` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '路径',
|
||||
`ICON` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图标',
|
||||
`COLOR` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '颜色',
|
||||
`REG_TYPE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '规则类型',
|
||||
|
|
Loading…
Reference in New Issue