Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X
This commit is contained in:
@@ -84,6 +84,8 @@ public class SysMenuController extends BaseController {
|
||||
public R<Void> add(@Validated @RequestBody SysMenu menu) {
|
||||
if (!menuService.checkMenuNameUnique(menu)) {
|
||||
return R.fail("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
|
||||
} else if (StringUtils.isNotBlank(menu.getMenuKey()) && !menuService.checkMenuKeyUnique(menu)) {
|
||||
return R.fail("新增菜单'" + menu.getMenuName() + "'失败,菜单唯一标识'" + menu.getMenuKey() + "'已存在");
|
||||
} else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) {
|
||||
return R.fail("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
|
||||
}
|
||||
@@ -99,6 +101,8 @@ public class SysMenuController extends BaseController {
|
||||
public R<Void> edit(@Validated @RequestBody SysMenu menu) {
|
||||
if (!menuService.checkMenuNameUnique(menu)) {
|
||||
return R.fail("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
|
||||
} else if (StringUtils.isNotBlank(menu.getMenuKey()) && !menuService.checkMenuKeyUnique(menu)) {
|
||||
return R.fail("修改菜单'" + menu.getMenuName() + "'失败,菜单唯一标识'" + menu.getMenuKey() + "'已存在");
|
||||
} else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) {
|
||||
return R.fail("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
|
||||
} else if (menu.getMenuId().equals(menu.getParentId())) {
|
||||
@@ -124,4 +128,29 @@ public class SysMenuController extends BaseController {
|
||||
}
|
||||
return toAjax(menuService.deleteMenuById(menuId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 menuKey 获取菜单信息(供流程图等外部固定引用跳转)
|
||||
*
|
||||
* @param menuKey 菜单唯一标识
|
||||
*/
|
||||
@GetMapping("/getByKey")
|
||||
public R<SysMenu> getByKey(@RequestParam String menuKey) {
|
||||
SysMenu menu = menuService.selectMenuByMenuKey(menuKey);
|
||||
if (menu == null) {
|
||||
return R.fail("菜单唯一标识 '" + menuKey + "' 不存在");
|
||||
}
|
||||
return R.ok(menu);
|
||||
}
|
||||
|
||||
/**
|
||||
* 为现有菜单自动生成 menu_key(仅处理 menu_key 为空且类型为 C/M 的菜单)
|
||||
*/
|
||||
@SaCheckPermission("system:menu:edit")
|
||||
@Log(title = "菜单管理", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/generateMenuKeys")
|
||||
public R<Void> generateMenuKeys() {
|
||||
int count = menuService.generateMenuKeys();
|
||||
return R.ok("成功为 " + count + " 个菜单生成 menu_key");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,12 @@ public class SysMenu extends TreeEntity<SysMenu> {
|
||||
@Size(min = 0, max = 50, message = "菜单名称长度不能超过{max}个字符")
|
||||
private String menuName;
|
||||
|
||||
/**
|
||||
* 菜单唯一标识(外部固定引用,不受目录变动影响)
|
||||
*/
|
||||
@Size(min = 0, max = 64, message = "菜单唯一标识长度不能超过{max}个字符")
|
||||
private String menuKey;
|
||||
|
||||
/**
|
||||
* 显示顺序
|
||||
*/
|
||||
|
||||
@@ -79,4 +79,16 @@ public interface SysMenuMapper extends BaseMapperPlus<SysMenuMapper, SysMenu, Sy
|
||||
*/
|
||||
List<Long> selectMenuListByRoleId(@Param("roleId") Long roleId, @Param("menuCheckStrictly") boolean menuCheckStrictly);
|
||||
|
||||
/**
|
||||
* 根据 menuKey 查询菜单
|
||||
*
|
||||
* @param menuKey 菜单唯一标识
|
||||
* @return 菜单信息
|
||||
*/
|
||||
default SysMenu selectMenuByMenuKey(String menuKey) {
|
||||
LambdaQueryWrapper<SysMenu> lqw = new LambdaQueryWrapper<SysMenu>()
|
||||
.eq(SysMenu::getMenuKey, menuKey);
|
||||
return this.selectOne(lqw);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -134,4 +134,27 @@ public interface ISysMenuService {
|
||||
* @return 结果
|
||||
*/
|
||||
boolean checkMenuNameUnique(SysMenu menu);
|
||||
|
||||
/**
|
||||
* 校验 menu_key 是否唯一
|
||||
*
|
||||
* @param menu 菜单信息
|
||||
* @return 结果 true=唯一 false=不唯一
|
||||
*/
|
||||
boolean checkMenuKeyUnique(SysMenu menu);
|
||||
|
||||
/**
|
||||
* 根据 menuKey 查询菜单
|
||||
*
|
||||
* @param menuKey 菜单唯一标识
|
||||
* @return 菜单信息
|
||||
*/
|
||||
SysMenu selectMenuByMenuKey(String menuKey);
|
||||
|
||||
/**
|
||||
* 为现有菜单自动生成 menu_key(仅处理 menu_key 为空且 menu_type 为 C/M 的记录)
|
||||
*
|
||||
* @return 更新条数
|
||||
*/
|
||||
int generateMenuKeys();
|
||||
}
|
||||
|
||||
@@ -303,6 +303,92 @@ public class SysMenuServiceImpl implements ISysMenuService {
|
||||
return !exist;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验 menu_key 是否唯一
|
||||
*/
|
||||
@Override
|
||||
public boolean checkMenuKeyUnique(SysMenu menu) {
|
||||
if (StringUtils.isBlank(menu.getMenuKey())) {
|
||||
return true;
|
||||
}
|
||||
boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysMenu>()
|
||||
.eq(SysMenu::getMenuKey, menu.getMenuKey())
|
||||
.ne(ObjectUtil.isNotNull(menu.getMenuId()), SysMenu::getMenuId, menu.getMenuId()));
|
||||
return !exist;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 menuKey 查询菜单
|
||||
*/
|
||||
@Override
|
||||
public SysMenu selectMenuByMenuKey(String menuKey) {
|
||||
return baseMapper.selectMenuByMenuKey(menuKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 为现有菜单自动生成 menu_key
|
||||
* 规则:
|
||||
* C(菜单):去掉 path 的首尾 /,剩余 / 替换为 _,如 /mes/qc/tensile → mes_qc_tensile
|
||||
* M(目录):同上,若 path 为空则用 menu_name 转拼音首字母
|
||||
* F(按钮):不处理
|
||||
*/
|
||||
@Override
|
||||
public int generateMenuKeys() {
|
||||
List<SysMenu> allMenus = baseMapper.selectList(new LambdaQueryWrapper<SysMenu>()
|
||||
.isNull(SysMenu::getMenuKey)
|
||||
.in(SysMenu::getMenuType, UserConstants.TYPE_DIR, UserConstants.TYPE_MENU)
|
||||
.eq(SysMenu::getStatus, UserConstants.MENU_NORMAL));
|
||||
|
||||
int count = 0;
|
||||
for (SysMenu menu : allMenus) {
|
||||
String key = buildMenuKey(menu);
|
||||
if (StringUtils.isBlank(key)) {
|
||||
continue;
|
||||
}
|
||||
// 确保唯一:如果已有同 key 的菜单,追加数字后缀
|
||||
String uniqueKey = key;
|
||||
int suffix = 1;
|
||||
while (baseMapper.exists(new LambdaQueryWrapper<SysMenu>()
|
||||
.eq(SysMenu::getMenuKey, uniqueKey)
|
||||
.ne(SysMenu::getMenuId, menu.getMenuId()))) {
|
||||
uniqueKey = key + "_" + suffix;
|
||||
suffix++;
|
||||
}
|
||||
menu.setMenuKey(uniqueKey);
|
||||
baseMapper.updateById(menu);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据菜单信息构建 menu_key
|
||||
*/
|
||||
private String buildMenuKey(SysMenu menu) {
|
||||
// 优先使用 path
|
||||
if (StringUtils.isNotBlank(menu.getPath())) {
|
||||
String path = menu.getPath().trim();
|
||||
// 去掉首尾 /
|
||||
if (path.startsWith("/")) {
|
||||
path = path.substring(1);
|
||||
}
|
||||
if (path.endsWith("/")) {
|
||||
path = path.substring(0, path.length() - 1);
|
||||
}
|
||||
// 剩余 / 替换为 _,非字母数字替换为 _
|
||||
return path.replaceAll("[^a-zA-Z0-9_\\u4e00-\\u9fa5]", "_")
|
||||
.replaceAll("_+", "_")
|
||||
.replaceAll("(^_|_$)", "");
|
||||
}
|
||||
// path 为空时,使用 menuName 作为 key
|
||||
if (StringUtils.isNotBlank(menu.getMenuName())) {
|
||||
return menu.getMenuName().trim().replaceAll("[^a-zA-Z0-9_\\u4e00-\\u9fa5]", "_")
|
||||
.replaceAll("_+", "_")
|
||||
.replaceAll("(^_|_$)", "");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取路由名称
|
||||
*
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<resultMap type="SysMenu" id="SysMenuResult">
|
||||
<id property="menuId" column="menu_id"/>
|
||||
<result property="menuName" column="menu_name"/>
|
||||
<result property="menuKey" column="menu_key"/>
|
||||
<result property="parentName" column="parent_name"/>
|
||||
<result property="parentId" column="parent_id"/>
|
||||
<result property="orderNum" column="order_num"/>
|
||||
@@ -29,7 +30,7 @@
|
||||
</resultMap>
|
||||
|
||||
<select id="selectMenuListByUserId" parameterType="SysMenu" resultMap="SysMenuResult">
|
||||
select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.query_param, m.visible, m.status,
|
||||
select distinct m.menu_id, m.parent_id, m.menu_name, m.menu_key, m.path, m.component, m.query_param, m.visible, m.status,
|
||||
m.perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.style, m.order_num, m.create_time
|
||||
from sys_menu m
|
||||
left join sys_role_menu rm on m.menu_id = rm.menu_id
|
||||
@@ -42,6 +43,7 @@
|
||||
select distinct m.menu_id,
|
||||
m.parent_id,
|
||||
m.menu_name,
|
||||
m.menu_key,
|
||||
m.path,
|
||||
m.component,
|
||||
m.query_param,
|
||||
|
||||
@@ -729,7 +729,13 @@ export default {
|
||||
...this.detailQueryParams,
|
||||
testMainId: this.currentTestId
|
||||
}).then(response => {
|
||||
this.detailList = response.rows
|
||||
// 归一化单字母前缀字段名:Jackson将cContent序列化为ccontent
|
||||
this.detailList = (response.rows || []).map(row => ({
|
||||
...row,
|
||||
cContent: row.ccontent ?? row.cContent,
|
||||
pContent: row.pcontent ?? row.pContent,
|
||||
sContent: row.scontent ?? row.sContent
|
||||
}))
|
||||
this.detailTotal = response.total
|
||||
this.detailLoading = false
|
||||
}).catch(() => {
|
||||
|
||||
Reference in New Issue
Block a user