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) {
|
public R<Void> add(@Validated @RequestBody SysMenu menu) {
|
||||||
if (!menuService.checkMenuNameUnique(menu)) {
|
if (!menuService.checkMenuNameUnique(menu)) {
|
||||||
return R.fail("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
|
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())) {
|
} else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) {
|
||||||
return R.fail("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
|
return R.fail("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
|
||||||
}
|
}
|
||||||
@@ -99,6 +101,8 @@ public class SysMenuController extends BaseController {
|
|||||||
public R<Void> edit(@Validated @RequestBody SysMenu menu) {
|
public R<Void> edit(@Validated @RequestBody SysMenu menu) {
|
||||||
if (!menuService.checkMenuNameUnique(menu)) {
|
if (!menuService.checkMenuNameUnique(menu)) {
|
||||||
return R.fail("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
|
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())) {
|
} else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) {
|
||||||
return R.fail("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
|
return R.fail("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
|
||||||
} else if (menu.getMenuId().equals(menu.getParentId())) {
|
} else if (menu.getMenuId().equals(menu.getParentId())) {
|
||||||
@@ -124,4 +128,29 @@ public class SysMenuController extends BaseController {
|
|||||||
}
|
}
|
||||||
return toAjax(menuService.deleteMenuById(menuId));
|
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}个字符")
|
@Size(min = 0, max = 50, message = "菜单名称长度不能超过{max}个字符")
|
||||||
private String menuName;
|
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);
|
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 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
boolean checkMenuNameUnique(SysMenu menu);
|
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;
|
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">
|
<resultMap type="SysMenu" id="SysMenuResult">
|
||||||
<id property="menuId" column="menu_id"/>
|
<id property="menuId" column="menu_id"/>
|
||||||
<result property="menuName" column="menu_name"/>
|
<result property="menuName" column="menu_name"/>
|
||||||
|
<result property="menuKey" column="menu_key"/>
|
||||||
<result property="parentName" column="parent_name"/>
|
<result property="parentName" column="parent_name"/>
|
||||||
<result property="parentId" column="parent_id"/>
|
<result property="parentId" column="parent_id"/>
|
||||||
<result property="orderNum" column="order_num"/>
|
<result property="orderNum" column="order_num"/>
|
||||||
@@ -29,7 +30,7 @@
|
|||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<select id="selectMenuListByUserId" parameterType="SysMenu" resultMap="SysMenuResult">
|
<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
|
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
|
from sys_menu m
|
||||||
left join sys_role_menu rm on m.menu_id = rm.menu_id
|
left join sys_role_menu rm on m.menu_id = rm.menu_id
|
||||||
@@ -42,6 +43,7 @@
|
|||||||
select distinct m.menu_id,
|
select distinct m.menu_id,
|
||||||
m.parent_id,
|
m.parent_id,
|
||||||
m.menu_name,
|
m.menu_name,
|
||||||
|
m.menu_key,
|
||||||
m.path,
|
m.path,
|
||||||
m.component,
|
m.component,
|
||||||
m.query_param,
|
m.query_param,
|
||||||
|
|||||||
@@ -729,7 +729,13 @@ export default {
|
|||||||
...this.detailQueryParams,
|
...this.detailQueryParams,
|
||||||
testMainId: this.currentTestId
|
testMainId: this.currentTestId
|
||||||
}).then(response => {
|
}).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.detailTotal = response.total
|
||||||
this.detailLoading = false
|
this.detailLoading = false
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user