feat(menu): 添加菜单完整路径功能和待写病历管理

- 在SysMenu实体类中新增fullPath字段用于存储完整路径
- 实现buildMenuTreeWithFullPath方法构建带完整路径的菜单树
- 添加getMenuFullPath和generateFullPath服务方法获取和生成完整路径
- 在菜单控制器中增加获取完整路径的API接口
- 前端菜单组件显示完整路径并在新增修改时使用后端返回的路径
- 添加待写病历管理功能包括获取待写病历列表、数量统计和检查接口
- 在医生工作站界面集成待写病历选项卡和相关处理逻辑
- 更新首页统计数据接口路径并添加待写病历数量获取功能
- 重构首页快捷功能配置为动态从数据库获取用户自定义配置
- 优化菜单列表查询使用异步方式处理带完整路径的菜单数据
- 添加菜单完整路径的数据库映射配置和前端API调用支持
This commit is contained in:
2026-02-01 14:50:22 +08:00
parent 29ecfd90f2
commit 0a08088ada
14 changed files with 1240 additions and 163 deletions

View File

@@ -3,7 +3,6 @@ package com.core.system.service;
import com.core.common.core.domain.TreeSelect;
import com.core.common.core.domain.entity.SysMenu;
import com.core.system.domain.vo.RouterVo;
import java.util.List;
import java.util.Set;
@@ -22,7 +21,7 @@ public interface ISysMenuService {
public List<SysMenu> selectMenuList(Long userId);
/**
* 根据用户查询系统菜单列表
* 查询系统菜单列表
*
* @param menu 菜单信息
* @param userId 用户ID
@@ -50,7 +49,7 @@ public interface ISysMenuService {
* 根据用户ID查询菜单树信息
*
* @param userId 用户ID
* @return 菜单列表
* @return 菜单树信息
*/
public List<SysMenu> selectMenuTreeByUserId(Long userId);
@@ -72,15 +71,23 @@ public interface ISysMenuService {
/**
* 构建前端所需要树结构
*
*
* @param menus 菜单列表
* @return 树结构列表
*/
public List<SysMenu> buildMenuTree(List<SysMenu> menus);
/**
* 构建前端所需要树结构(包含完整路径)
*
* @param menus 菜单列表
* @return 树结构列表
*/
public List<SysMenu> buildMenuTreeWithFullPath(List<SysMenu> menus);
/**
* 构建前端所需要下拉树结构
*
*
* @param menus 菜单列表
* @return 下拉树结构列表
*/
@@ -98,15 +105,15 @@ public interface ISysMenuService {
* 是否存在菜单子节点
*
* @param menuId 菜单ID
* @return 结果 true 存在 false 不存在
* @return 结果
*/
public boolean hasChildByMenuId(Long menuId);
/**
* 查询菜单是否存在角色
* 查询菜单使用数量
*
* @param menuId 菜单ID
* @return 结果 true 存在 false 不存在
* @return 结果
*/
public boolean checkMenuExistRole(Long menuId);
@@ -141,4 +148,21 @@ public interface ISysMenuService {
* @return 结果
*/
public boolean checkMenuNameUnique(SysMenu menu);
}
/**
* 根据菜单ID获取完整路径
*
* @param menuId 菜单ID
* @return 完整路径
*/
public String getMenuFullPath(Long menuId);
/**
* 根据路径参数生成完整路径
*
* @param parentId 父级菜单ID
* @param currentPath 当前路径
* @return 完整路径
*/
public String generateFullPath(Long parentId, String currentPath);
}

View File

@@ -193,7 +193,7 @@ public class SysMenuServiceImpl implements ISysMenuService {
/**
* 构建前端所需要树结构
*
*
* @param menus 菜单列表
* @return 树结构列表
*/
@@ -215,6 +215,36 @@ public class SysMenuServiceImpl implements ISysMenuService {
return returnList;
}
/**
* 构建前端所需要树结构(包含完整路径)
*
* @param menus 菜单列表
* @return 树结构列表
*/
@Override
public List<SysMenu> buildMenuTreeWithFullPath(List<SysMenu> menus) {
List<SysMenu> menuTree = buildMenuTree(menus);
// 为每个菜单项添加完整路径
addFullPathToMenuTree(menuTree);
return menuTree;
}
/**
* 为菜单树添加完整路径
*
* @param menus 菜单树
*/
private void addFullPathToMenuTree(List<SysMenu> menus) {
for (SysMenu menu : menus) {
// 计算当前菜单的完整路径
menu.setFullPath(getMenuFullPath(menu.getMenuId()));
// 递归处理子菜单
if (menu.getChildren() != null && !menu.getChildren().isEmpty()) {
addFullPathToMenuTree(menu.getChildren());
}
}
}
/**
* 构建前端所需要下拉树结构
*
@@ -488,11 +518,139 @@ public class SysMenuServiceImpl implements ISysMenuService {
/**
* 内链域名特殊字符替换
*
*
* @return 替换后的内链域名
*/
public String innerLinkReplaceEach(String path) {
return StringUtils.replaceEach(path, new String[] {Constants.HTTP, Constants.HTTPS, Constants.WWW, ".", ":"},
new String[] {"", "", "", "/", "/"});
}
/**
* 根据菜单ID获取完整路径
*
* @param menuId 菜单ID
* @return 完整路径
*/
@Override
public String getMenuFullPath(Long menuId) {
SysMenu menu = menuMapper.selectMenuById(menuId);
if (menu == null) {
return "";
}
StringBuilder fullPath = new StringBuilder();
buildMenuPath(menu, fullPath);
// 标准化完整路径,确保没有多余的斜杠
return normalizePath(fullPath.toString());
}
/**
* 递归构建菜单路径
*
* @param menu 菜单信息
* @param path 路径构建器
*/
private void buildMenuPath(SysMenu menu, StringBuilder path) {
if (menu == null || menu.getMenuId() == null) {
return;
}
// 如果不是根节点,则递归查找父节点
if (menu.getParentId() != null && menu.getParentId() > 0) {
SysMenu parentMenu = menuMapper.selectMenuById(menu.getParentId());
if (parentMenu != null) {
buildMenuPath(parentMenu, path);
}
}
// 添加当前菜单的路径,避免双斜杠
String currentPath = normalizePathSegment(menu.getPath());
if (currentPath != null && !currentPath.isEmpty()) {
if (path.length() > 0) {
// 确保路径之间只有一个斜杠分隔符
// 如果当前路径不为空,且当前路径不以斜杠结尾,则添加斜杠并追加路径
if (path.charAt(path.length() - 1) != '/') {
path.append("/").append(currentPath);
} else {
path.append(currentPath);
}
} else {
// 对于第一个路径,直接追加
path.append(currentPath);
}
}
}
/**
* 标准化路径片段,移除开头的斜杠
*
* @param path 原始路径
* @return 标准化后的路径片段
*/
private String normalizePathSegment(String path) {
if (path == null) {
return null;
}
// 移除开头的斜杠
if (path.startsWith("/")) {
path = path.substring(1);
}
return path;
}
/**
* 标准化完整路径,移除多余的斜杠
*
* @param path 原始路径
* @return 标准化后的完整路径
*/
private String normalizePath(String path) {
if (path == null) {
return null;
}
// 处理多个连续斜杠,将其替换为单个斜杠
while (path.contains("//")) {
path = path.replace("//", "/");
}
return path;
}
/**
* 根据路径参数生成完整路径
*
* @param parentId 父级菜单ID
* @param currentPath 当前路径
* @return 完整路径
*/
@Override
public String generateFullPath(Long parentId, String currentPath) {
StringBuilder fullPath = new StringBuilder();
// 如果有父级菜单,则先获取父级菜单的完整路径
if (parentId != null && parentId > 0) {
SysMenu parentMenu = menuMapper.selectMenuById(parentId);
if (parentMenu != null) {
String parentFullPath = getMenuFullPath(parentId);
if (StringUtils.isNotEmpty(parentFullPath)) {
fullPath.append(parentFullPath);
}
}
}
// 添加当前路径
if (StringUtils.isNotEmpty(currentPath)) {
if (fullPath.length() > 0) {
fullPath.append("/").append(currentPath);
} else {
fullPath.append(currentPath);
}
}
return normalizePath(fullPath.toString());
}
}

View File

@@ -21,6 +21,7 @@
<result property="status" column="status"/>
<result property="perms" column="perms"/>
<result property="icon" column="icon"/>
<result property="fullPath" column="full_path"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>