refactor: 路由参数从 varchar 调整到 json 适配调整

This commit is contained in:
Ray.Hao
2026-03-10 20:41:17 +08:00
parent 6119d730d8
commit 6b7cfee7b4
4 changed files with 29 additions and 49 deletions

View File

@@ -129,7 +129,7 @@ CREATE TABLE `sys_menu` (
`redirect` varchar(128) COMMENT '跳转路径',
`create_time` datetime NULL COMMENT '创建时间',
`update_time` datetime NULL COMMENT '更新时间',
`params` varchar(255) NULL COMMENT '路由参数',
`params` json NULL COMMENT '路由参数',
PRIMARY KEY (`id`) USING BTREE
) 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 (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 (2701, 270, '0,1,270', '系统配置查询', 'B', NULL, '', NULL, 'sys:config:list', 0, 1, 1, 1, '', NULL, now(), now(), NULL);

View File

@@ -1,11 +1,12 @@
package com.youlai.boot.system.model.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
import java.util.Map;
/**
* 菜单实体
@@ -13,7 +14,7 @@ import java.time.LocalDateTime;
* @author Ray.Hao
* @since 2023/3/6
*/
@TableName("sys_menu")
@TableName(value = "sys_menu", autoResultMap = true)
@Getter
@Setter
public class Menu {
@@ -96,8 +97,8 @@ public class Menu {
/**
* 路由参数
*/
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private String params;
@TableField(updateStrategy = FieldStrategy.ALWAYS, typeHandler = JacksonTypeHandler.class)
private Map<String, Object> params;
@TableField(fill = FieldFill.INSERT)
@@ -109,4 +110,4 @@ public class Menu {
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
}
}

View File

@@ -4,12 +4,9 @@ import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
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.update.LambdaUpdateWrapper;
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.security.util.SecurityUtils;
import com.youlai.boot.system.converter.MenuConverter;
@@ -159,7 +156,7 @@ public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements Me
} else {
// 普通用户:通过角色获取菜单(权限控制已过滤)
menuList = this.baseMapper.getMenusByRoleCodes(roleCodes);
// 双重保障:动态查询"平台管理"目录,过滤其子菜单
// 通过路由路径识别平台管理目录,避免硬编码
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())
.last("LIMIT 1")
);
if (platformMenu != null) {
final Long platformMenuId = platformMenu.getId();
menuList = menuList.stream()
@@ -188,10 +185,10 @@ public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements Me
/**
* 获取当前用户的菜单路由列表(指定数据源)
*
*
* @param datasource 数据源名称
* - master: 主库菜单数据
* - naiveui: NaiveUI项目菜单数据
* - naiveui: NaiveUI项目菜单数据
* - template: 模板项目菜单数据
*/
@Override
@@ -260,17 +257,11 @@ public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements Me
}
meta.setAlwaysShow(ObjectUtil.equals(menu.getAlwaysShow(), 1));
String paramsJson = menu.getParams();
// 将 JSON 字符串转换为 Map<String, String>
if (StrUtil.isNotBlank(paramsJson)) {
ObjectMapper objectMapper = new ObjectMapper();
try {
Map<String, String> paramMap = objectMapper.readValue(paramsJson, new TypeReference<>() {
});
meta.setParams(paramMap);
} catch (Exception e) {
throw new RuntimeException("解析参数失败", e);
}
Map<String, Object> paramsMap = menu.getParams();
if (paramsMap != null && !paramsMap.isEmpty()) {
Map<String, String> paramMap = paramsMap.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> String.valueOf(e.getValue())));
meta.setParams(paramMap);
}
routeVo.setMeta(meta);
return routeVo;
@@ -305,10 +296,9 @@ public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements Me
entity.setTreePath(treePath);
List<KeyValue> params = menuForm.getParams();
// 路由参数 [{key:"id",value:"1"}{key:"name",value:"张三"}] 转换为 [{"id":"1"},{"name":"张三"}]
if (CollectionUtil.isNotEmpty(params)) {
entity.setParams(JSONUtil.toJsonStr(params.stream()
.collect(Collectors.toMap(KeyValue::getKey, KeyValue::getValue))));
entity.setParams(params.stream()
.collect(Collectors.toMap(KeyValue::getKey, KeyValue::getValue)));
} else {
entity.setParams(null);
}
@@ -400,27 +390,14 @@ public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements Me
Menu entity = this.getById(id);
Assert.isTrue(entity != null, "菜单不存在");
MenuForm formData = menuConverter.toForm(entity);
// 路由参数字符串 {"id":"1","name":"张三"} 转换为 [{key:"id", value:"1"}, {key:"name", value:"张三"}]
String params = entity.getParams();
if (StrUtil.isNotBlank(params)) {
ObjectMapper objectMapper = new ObjectMapper();
try {
// 解析 JSON 字符串为 Map<String, String>
Map<String, String> paramMap = objectMapper.readValue(params, new TypeReference<>() {
});
// 转换为 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);
}
// 路由参数 Map 转换为 [{key:"id", value:"1"}, {key:"name", value:"张三"}]
Map<String, Object> paramsMap = entity.getParams();
if (paramsMap != null && !paramsMap.isEmpty()) {
List<KeyValue> transformedList = paramsMap.entrySet().stream()
.map(entry -> new KeyValue(entry.getKey(), String.valueOf(entry.getValue())))
.toList();
formData.setParams(transformedList);
}
return formData;
}

View File

@@ -84,6 +84,7 @@ security:
- /api/v1/auth/sms/code # 发送登录短信验证码
- /api/v1/auth/refresh-token # 刷新令牌接口
- /api/v1/wechat/miniapp/auth/** # 微信小程序认证接口(静默登录/手机号快捷登录/绑定手机号)
- /api/v1/statistics/** # 统计分析接口(访问趋势/访问概览)
- /ws/** # WebSocket接口
# 非安全端点路径,完全绕过 Spring Security 的过滤器
unsecured-urls:
@@ -215,5 +216,5 @@ captcha:
# 微信小程序配置
wx:
miniapp:
appid: xxxxxx
secret: xxxxxx
appid: wx99a151dc43d2637b
secret: fa2d74fd9f340ff1017c96fcbd19f5ad