refactor: 路由参数从 varchar 调整到 json 适配调整
This commit is contained in:
@@ -129,7 +129,7 @@ CREATE TABLE `sys_menu` (
|
|||||||
`redirect` varchar(128) COMMENT '跳转路径',
|
`redirect` varchar(128) COMMENT '跳转路径',
|
||||||
`create_time` datetime NULL COMMENT '创建时间',
|
`create_time` datetime NULL COMMENT '创建时间',
|
||||||
`update_time` datetime NULL COMMENT '更新时间',
|
`update_time` datetime NULL COMMENT '更新时间',
|
||||||
`params` varchar(255) NULL COMMENT '路由参数',
|
`params` json NULL COMMENT '路由参数',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COMMENT = '系统菜单表';
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COMMENT = '系统菜单表';
|
||||||
|
|
||||||
@@ -188,6 +188,7 @@ INSERT INTO `sys_menu` VALUES (2513, 251, '0,1,251', '字典项编辑', 'B', NUL
|
|||||||
INSERT INTO `sys_menu` VALUES (2514, 251, '0,1,251', '字典项删除', 'B', NULL, '', NULL, 'sys:dict-item:delete', NULL, NULL, 1, 4, '', NULL, now(), now(), NULL);
|
INSERT INTO `sys_menu` VALUES (2514, 251, '0,1,251', '字典项删除', 'B', NULL, '', NULL, 'sys:dict-item:delete', NULL, NULL, 1, 4, '', NULL, now(), now(), NULL);
|
||||||
|
|
||||||
INSERT INTO `sys_menu` VALUES (260, 1, '0,1', '系统日志', 'M', 'Log', 'log', 'system/log/index', NULL, 0, 1, 1, 7, 'document', NULL, now(), now(), NULL);
|
INSERT INTO `sys_menu` VALUES (260, 1, '0,1', '系统日志', 'M', 'Log', 'log', 'system/log/index', NULL, 0, 1, 1, 7, 'document', NULL, now(), now(), NULL);
|
||||||
|
INSERT INTO `sys_menu` VALUES (2601, 260, '0,1,260', '日志查询', 'B', NULL, '', NULL, 'sys:log:list', NULL, NULL, 1, 1, '', NULL, now(), now(), NULL);
|
||||||
|
|
||||||
INSERT INTO `sys_menu` VALUES (270, 1, '0,1', '系统配置', 'M', 'Config', 'config', 'system/config/index', NULL, 0, 1, 1, 8, 'setting', NULL, now(), now(), NULL);
|
INSERT INTO `sys_menu` VALUES (270, 1, '0,1', '系统配置', 'M', 'Config', 'config', 'system/config/index', NULL, 0, 1, 1, 8, 'setting', NULL, now(), now(), NULL);
|
||||||
INSERT INTO `sys_menu` VALUES (2701, 270, '0,1,270', '系统配置查询', 'B', NULL, '', NULL, 'sys:config:list', 0, 1, 1, 1, '', NULL, now(), now(), NULL);
|
INSERT INTO `sys_menu` VALUES (2701, 270, '0,1,270', '系统配置查询', 'B', NULL, '', NULL, 'sys:config:list', 0, 1, 1, 1, '', NULL, now(), now(), NULL);
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
package com.youlai.boot.system.model.entity;
|
package com.youlai.boot.system.model.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 菜单实体
|
* 菜单实体
|
||||||
@@ -13,7 +14,7 @@ import java.time.LocalDateTime;
|
|||||||
* @author Ray.Hao
|
* @author Ray.Hao
|
||||||
* @since 2023/3/6
|
* @since 2023/3/6
|
||||||
*/
|
*/
|
||||||
@TableName("sys_menu")
|
@TableName(value = "sys_menu", autoResultMap = true)
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
public class Menu {
|
public class Menu {
|
||||||
@@ -96,8 +97,8 @@ public class Menu {
|
|||||||
/**
|
/**
|
||||||
* 路由参数
|
* 路由参数
|
||||||
*/
|
*/
|
||||||
@TableField(updateStrategy = FieldStrategy.ALWAYS)
|
@TableField(updateStrategy = FieldStrategy.ALWAYS, typeHandler = JacksonTypeHandler.class)
|
||||||
private String params;
|
private Map<String, Object> params;
|
||||||
|
|
||||||
|
|
||||||
@TableField(fill = FieldFill.INSERT)
|
@TableField(fill = FieldFill.INSERT)
|
||||||
@@ -109,4 +110,4 @@ public class Menu {
|
|||||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
private LocalDateTime updateTime;
|
private LocalDateTime updateTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,9 @@ import cn.hutool.core.collection.CollectionUtil;
|
|||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.json.JSONUtil;
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import tools.jackson.core.type.TypeReference;
|
|
||||||
import tools.jackson.databind.ObjectMapper;
|
|
||||||
import com.youlai.boot.tool.codegen.model.entity.GenTable;
|
import com.youlai.boot.tool.codegen.model.entity.GenTable;
|
||||||
import com.youlai.boot.security.util.SecurityUtils;
|
import com.youlai.boot.security.util.SecurityUtils;
|
||||||
import com.youlai.boot.system.converter.MenuConverter;
|
import com.youlai.boot.system.converter.MenuConverter;
|
||||||
@@ -159,7 +156,7 @@ public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements Me
|
|||||||
} else {
|
} else {
|
||||||
// 普通用户:通过角色获取菜单(权限控制已过滤)
|
// 普通用户:通过角色获取菜单(权限控制已过滤)
|
||||||
menuList = this.baseMapper.getMenusByRoleCodes(roleCodes);
|
menuList = this.baseMapper.getMenusByRoleCodes(roleCodes);
|
||||||
|
|
||||||
// 双重保障:动态查询"平台管理"目录,过滤其子菜单
|
// 双重保障:动态查询"平台管理"目录,过滤其子菜单
|
||||||
// 通过路由路径识别平台管理目录,避免硬编码
|
// 通过路由路径识别平台管理目录,避免硬编码
|
||||||
Menu platformMenu = this.getOne(new LambdaQueryWrapper<Menu>()
|
Menu platformMenu = this.getOne(new LambdaQueryWrapper<Menu>()
|
||||||
@@ -168,7 +165,7 @@ public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements Me
|
|||||||
.eq(Menu::getType, MenuTypeEnum.CATALOG.getValue())
|
.eq(Menu::getType, MenuTypeEnum.CATALOG.getValue())
|
||||||
.last("LIMIT 1")
|
.last("LIMIT 1")
|
||||||
);
|
);
|
||||||
|
|
||||||
if (platformMenu != null) {
|
if (platformMenu != null) {
|
||||||
final Long platformMenuId = platformMenu.getId();
|
final Long platformMenuId = platformMenu.getId();
|
||||||
menuList = menuList.stream()
|
menuList = menuList.stream()
|
||||||
@@ -188,10 +185,10 @@ public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements Me
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前用户的菜单路由列表(指定数据源)
|
* 获取当前用户的菜单路由列表(指定数据源)
|
||||||
*
|
*
|
||||||
* @param datasource 数据源名称
|
* @param datasource 数据源名称
|
||||||
* - master: 主库菜单数据
|
* - master: 主库菜单数据
|
||||||
* - naiveui: NaiveUI项目菜单数据
|
* - naiveui: NaiveUI项目菜单数据
|
||||||
* - template: 模板项目菜单数据
|
* - template: 模板项目菜单数据
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -260,17 +257,11 @@ public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements Me
|
|||||||
}
|
}
|
||||||
meta.setAlwaysShow(ObjectUtil.equals(menu.getAlwaysShow(), 1));
|
meta.setAlwaysShow(ObjectUtil.equals(menu.getAlwaysShow(), 1));
|
||||||
|
|
||||||
String paramsJson = menu.getParams();
|
Map<String, Object> paramsMap = menu.getParams();
|
||||||
// 将 JSON 字符串转换为 Map<String, String>
|
if (paramsMap != null && !paramsMap.isEmpty()) {
|
||||||
if (StrUtil.isNotBlank(paramsJson)) {
|
Map<String, String> paramMap = paramsMap.entrySet().stream()
|
||||||
ObjectMapper objectMapper = new ObjectMapper();
|
.collect(Collectors.toMap(Map.Entry::getKey, e -> String.valueOf(e.getValue())));
|
||||||
try {
|
meta.setParams(paramMap);
|
||||||
Map<String, String> paramMap = objectMapper.readValue(paramsJson, new TypeReference<>() {
|
|
||||||
});
|
|
||||||
meta.setParams(paramMap);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("解析参数失败", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
routeVo.setMeta(meta);
|
routeVo.setMeta(meta);
|
||||||
return routeVo;
|
return routeVo;
|
||||||
@@ -305,10 +296,9 @@ public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements Me
|
|||||||
entity.setTreePath(treePath);
|
entity.setTreePath(treePath);
|
||||||
|
|
||||||
List<KeyValue> params = menuForm.getParams();
|
List<KeyValue> params = menuForm.getParams();
|
||||||
// 路由参数 [{key:"id",value:"1"},{key:"name",value:"张三"}] 转换为 [{"id":"1"},{"name":"张三"}]
|
|
||||||
if (CollectionUtil.isNotEmpty(params)) {
|
if (CollectionUtil.isNotEmpty(params)) {
|
||||||
entity.setParams(JSONUtil.toJsonStr(params.stream()
|
entity.setParams(params.stream()
|
||||||
.collect(Collectors.toMap(KeyValue::getKey, KeyValue::getValue))));
|
.collect(Collectors.toMap(KeyValue::getKey, KeyValue::getValue)));
|
||||||
} else {
|
} else {
|
||||||
entity.setParams(null);
|
entity.setParams(null);
|
||||||
}
|
}
|
||||||
@@ -400,27 +390,14 @@ public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements Me
|
|||||||
Menu entity = this.getById(id);
|
Menu entity = this.getById(id);
|
||||||
Assert.isTrue(entity != null, "菜单不存在");
|
Assert.isTrue(entity != null, "菜单不存在");
|
||||||
MenuForm formData = menuConverter.toForm(entity);
|
MenuForm formData = menuConverter.toForm(entity);
|
||||||
// 路由参数字符串 {"id":"1","name":"张三"} 转换为 [{key:"id", value:"1"}, {key:"name", value:"张三"}]
|
// 路由参数 Map 转换为 [{key:"id", value:"1"}, {key:"name", value:"张三"}]
|
||||||
String params = entity.getParams();
|
Map<String, Object> paramsMap = entity.getParams();
|
||||||
if (StrUtil.isNotBlank(params)) {
|
if (paramsMap != null && !paramsMap.isEmpty()) {
|
||||||
ObjectMapper objectMapper = new ObjectMapper();
|
List<KeyValue> transformedList = paramsMap.entrySet().stream()
|
||||||
try {
|
.map(entry -> new KeyValue(entry.getKey(), String.valueOf(entry.getValue())))
|
||||||
// 解析 JSON 字符串为 Map<String, String>
|
.toList();
|
||||||
Map<String, String> paramMap = objectMapper.readValue(params, new TypeReference<>() {
|
formData.setParams(transformedList);
|
||||||
});
|
|
||||||
|
|
||||||
// 转换为 List<KeyValue> 格式 [{key:"id", value:"1"}, {key:"name", value:"张三"}]
|
|
||||||
List<KeyValue> transformedList = paramMap.entrySet().stream()
|
|
||||||
.map(entry -> new KeyValue(entry.getKey(), entry.getValue()))
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
// 将转换后的列表存入 MenuForm
|
|
||||||
formData.setParams(transformedList);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("解析参数失败", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return formData;
|
return formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ security:
|
|||||||
- /api/v1/auth/sms/code # 发送登录短信验证码
|
- /api/v1/auth/sms/code # 发送登录短信验证码
|
||||||
- /api/v1/auth/refresh-token # 刷新令牌接口
|
- /api/v1/auth/refresh-token # 刷新令牌接口
|
||||||
- /api/v1/wechat/miniapp/auth/** # 微信小程序认证接口(静默登录/手机号快捷登录/绑定手机号)
|
- /api/v1/wechat/miniapp/auth/** # 微信小程序认证接口(静默登录/手机号快捷登录/绑定手机号)
|
||||||
|
- /api/v1/statistics/** # 统计分析接口(访问趋势/访问概览)
|
||||||
- /ws/** # WebSocket接口
|
- /ws/** # WebSocket接口
|
||||||
# 非安全端点路径,完全绕过 Spring Security 的过滤器
|
# 非安全端点路径,完全绕过 Spring Security 的过滤器
|
||||||
unsecured-urls:
|
unsecured-urls:
|
||||||
@@ -215,5 +216,5 @@ captcha:
|
|||||||
# 微信小程序配置
|
# 微信小程序配置
|
||||||
wx:
|
wx:
|
||||||
miniapp:
|
miniapp:
|
||||||
appid: xxxxxx
|
appid: wx99a151dc43d2637b
|
||||||
secret: xxxxxx
|
secret: fa2d74fd9f340ff1017c96fcbd19f5ad
|
||||||
|
|||||||
Reference in New Issue
Block a user