diff --git a/openhis-server-new/core-system/src/main/java/com/core/system/mapper/SysMenuMapper.java b/openhis-server-new/core-system/src/main/java/com/core/system/mapper/SysMenuMapper.java index b994cad6..5b2830b1 100644 --- a/openhis-server-new/core-system/src/main/java/com/core/system/mapper/SysMenuMapper.java +++ b/openhis-server-new/core-system/src/main/java/com/core/system/mapper/SysMenuMapper.java @@ -140,4 +140,11 @@ public interface SysMenuMapper { * @return 结果 */ public SysMenu checkMenuNameUnique(@Param("menuName") String menuName, @Param("parentId") Long parentId); + + /** + * 查询所有菜单信息 + * + * @return 菜单列表 + */ + public List selectAllMenus(); } diff --git a/openhis-server-new/core-system/src/main/java/com/core/system/service/impl/SysMenuServiceImpl.java b/openhis-server-new/core-system/src/main/java/com/core/system/service/impl/SysMenuServiceImpl.java index c1ff3b8c..bd55b734 100644 --- a/openhis-server-new/core-system/src/main/java/com/core/system/service/impl/SysMenuServiceImpl.java +++ b/openhis-server-new/core-system/src/main/java/com/core/system/service/impl/SysMenuServiceImpl.java @@ -59,6 +59,7 @@ public class SysMenuServiceImpl implements ISysMenuService { * @return 菜单列表 */ @Override + @org.springframework.cache.annotation.Cacheable(value = "menu", key = "'menuList:' + #userId + ':' + (#menu == null ? 'all' : #menu.menuName)") public List selectMenuList(SysMenu menu, Long userId) { List menuList = null; // 管理员显示所有菜单信息 @@ -224,23 +225,133 @@ public class SysMenuServiceImpl implements ISysMenuService { @Override public List buildMenuTreeWithFullPath(List menus) { List menuTree = buildMenuTree(menus); - // 为每个菜单项添加完整路径 - addFullPathToMenuTree(menuTree); + // 一次性获取所有菜单信息,避免N+1查询问题 + List allMenus = menuMapper.selectAllMenus(); + Map menuMap = allMenus.stream() + .collect(Collectors.toMap(SysMenu::getMenuId, menu -> menu)); + + // 为每个菜单项添加完整路径(优化版本,避免N+1查询问题) + addFullPathsToMenuTreeOptimized(menuTree, menuMap); return menuTree; } /** - * 为菜单树添加完整路径 + * 为菜单树添加完整路径(优化版本) * * @param menus 菜单树 + * @param menuMap 菜单映射 */ - private void addFullPathToMenuTree(List menus) { + private void addFullPathsToMenuTreeOptimized(List menus, Map menuMap) { for (SysMenu menu : menus) { - // 计算当前菜单的完整路径 - menu.setFullPath(getMenuFullPath(menu.getMenuId())); + // 使用优化的路径计算方法 + menu.setFullPath(computeMenuFullPathOptimized(menu, menuMap)); + // 递归处理子菜单 if (menu.getChildren() != null && !menu.getChildren().isEmpty()) { - addFullPathToMenuTree(menu.getChildren()); + addFullPathsToMenuTreeOptimized(menu.getChildren(), menuMap); + } + } + } + + /** + * 优化的计算菜单完整路径方法 + * + * @param menu 菜单 + * @param menuMap 菜单映射 + * @return 完整路径 + */ + private String computeMenuFullPathOptimized(SysMenu menu, Map menuMap) { + if (menu == null || menu.getMenuId() == null) { + return ""; + } + + StringBuilder fullPath = new StringBuilder(); + buildMenuPathOptimized(menu, fullPath, menuMap); + return normalizePath(fullPath.toString()); + } + + /** + * 优化的递归构建菜单路径 + * + * @param menu 菜单信息 + * @param path 路径构建器 + * @param menuMap 菜单映射 + */ + private void buildMenuPathOptimized(SysMenu menu, StringBuilder path, Map menuMap) { + if (menu == null || menu.getMenuId() == null) { + return; + } + + // 如果不是根节点,则递归查找父节点 + if (menu.getParentId() != null && menu.getParentId() > 0) { + SysMenu parentMenu = menuMap.get(menu.getParentId()); + if (parentMenu != null) { + buildMenuPathOptimized(parentMenu, path, menuMap); + } + } + + // 添加当前菜单的路径,避免双斜杠 + 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); + } + } + } + + /** + * 递归收集菜单树中的所有菜单ID + * + * @param menus 菜单树 + * @return 菜单ID列表 + */ + private List collectMenuIds(List menus) { + List menuIds = new ArrayList<>(); + for (SysMenu menu : menus) { + menuIds.add(menu.getMenuId()); + if (menu.getChildren() != null && !menu.getChildren().isEmpty()) { + menuIds.addAll(collectMenuIds(menu.getChildren())); + } + } + return menuIds; + } + + /** + * 批量获取菜单完整路径 + * + * @param menuIds 菜单ID列表 + * @return 菜单ID到完整路径的映射 + */ + private Map batchGetMenuFullPaths(List menuIds) { + Map fullPathMap = new HashMap<>(); + for (Long menuId : menuIds) { + // 使用缓存的getMenuFullPath方法 + fullPathMap.put(menuId, getMenuFullPath(menuId)); + } + return fullPathMap; + } + + /** + * 为菜单树设置完整路径 + * + * @param menus 菜单树 + * @param fullPathMap 完整路径映射 + */ + private void setFullPathsToMenuTree(List menus, Map fullPathMap) { + for (SysMenu menu : menus) { + // 设置当前菜单的完整路径 + menu.setFullPath(fullPathMap.get(menu.getMenuId())); + // 递归处理子菜单 + if (menu.getChildren() != null && !menu.getChildren().isEmpty()) { + setFullPathsToMenuTree(menu.getChildren(), fullPathMap); } } } @@ -299,6 +410,9 @@ public class SysMenuServiceImpl implements ISysMenuService { * @return 结果 */ @Override + @org.springframework.cache.annotation.Caching(evict = { + @org.springframework.cache.annotation.CacheEvict(value = "menu", allEntries = true) + }) public int insertMenu(SysMenu menu) { //路径Path唯一性判断 SysMenu sysMenu = menuMapper.selectMenuByPath(menu.getPath()); @@ -315,13 +429,17 @@ public class SysMenuServiceImpl implements ISysMenuService { * @return 结果 */ @Override + @org.springframework.cache.annotation.Caching(evict = { + @org.springframework.cache.annotation.CacheEvict(value = "menu", allEntries = true), + @org.springframework.cache.annotation.CacheEvict(value = "menu", key = "'fullPath:' + #menu.menuId") + }) public int updateMenu(SysMenu menu) { //路径Path唯一性判断(排除当前菜单本身) String path = menu.getPath(); if (StringUtils.isNotBlank(path)) { SysMenu sysMenu = menuMapper.selectMenuByPathExcludeId(menu.getPath(), menu.getMenuId()); if (sysMenu != null) { - log.warn("路由地址已存在 - menuId: {}, path: {}, 存在的menuId: {}", + log.warn("路由地址已存在 - menuId: {}, path: {}, 存在的menuId: {}", menu.getMenuId(), menu.getPath(), sysMenu.getMenuId()); return -1; // 路由地址已存在 } @@ -337,6 +455,10 @@ public class SysMenuServiceImpl implements ISysMenuService { * @return 结果 */ @Override + @org.springframework.cache.annotation.Caching(evict = { + @org.springframework.cache.annotation.CacheEvict(value = "menu", allEntries = true), + @org.springframework.cache.annotation.CacheEvict(value = "menu", key = "'fullPath:' + #menuId") + }) public int deleteMenuById(Long menuId) { return menuMapper.deleteMenuById(menuId); } @@ -533,6 +655,7 @@ public class SysMenuServiceImpl implements ISysMenuService { * @return 完整路径 */ @Override + @org.springframework.cache.annotation.Cacheable(value = "menu", key = "'fullPath:' + #menuId", unless = "#result == null || #result.isEmpty()") public String getMenuFullPath(Long menuId) { SysMenu menu = menuMapper.selectMenuById(menuId); if (menu == null) { diff --git a/openhis-server-new/core-system/src/main/resources/mapper/system/SysMenuMapper.xml b/openhis-server-new/core-system/src/main/resources/mapper/system/SysMenuMapper.xml index 69344dbe..4ccb720d 100644 --- a/openhis-server-new/core-system/src/main/resources/mapper/system/SysMenuMapper.xml +++ b/openhis-server-new/core-system/src/main/resources/mapper/system/SysMenuMapper.xml @@ -274,4 +274,27 @@ where menu_id = #{menuId} + + \ No newline at end of file diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/IDoctorScheduleAppService.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/IDoctorScheduleAppService.java index a32b3009..9a18e335 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/IDoctorScheduleAppService.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/IDoctorScheduleAppService.java @@ -7,6 +7,8 @@ public interface IDoctorScheduleAppService { R getDoctorScheduleList(); + R getTodayDoctorScheduleList(); + R addDoctorSchedule(DoctorSchedule doctorSchedule); R removeDoctorSchedule(Integer doctorScheduleId); diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/impl/DoctorScheduleAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/impl/DoctorScheduleAppServiceImpl.java index 576e9e1e..9cfee9f6 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/impl/DoctorScheduleAppServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/impl/DoctorScheduleAppServiceImpl.java @@ -1,6 +1,7 @@ package com.openhis.web.appointmentmanage.appservice.impl; import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.core.common.core.domain.R; import com.openhis.appointmentmanage.domain.DoctorSchedule; import com.openhis.appointmentmanage.mapper.DoctorScheduleMapper; @@ -9,6 +10,8 @@ import com.openhis.web.appointmentmanage.appservice.IDoctorScheduleAppService; import org.springframework.stereotype.Service; import javax.annotation.Resource; +import java.time.DayOfWeek; +import java.time.LocalDate; import java.util.List; @Service @@ -26,6 +29,50 @@ public class DoctorScheduleAppServiceImpl implements IDoctorScheduleAppService { return R.ok(list); } + @Override + public R getTodayDoctorScheduleList() { + // 获取今天的日期 + LocalDate today = LocalDate.now(); + DayOfWeek dayOfWeek = today.getDayOfWeek(); + + // 将 Java 的 DayOfWeek 转换为字符串表示 + String weekdayStr = convertDayOfWeekToString(dayOfWeek); + + // 查询今天排班的医生 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(DoctorSchedule::getWeekday, weekdayStr) // 根据星期几查询 + .eq(DoctorSchedule::getIsStopped, false); // 只查询未停止的排班 + + List list = doctorScheduleService.list(queryWrapper); + return R.ok(list); + } + + /** + * 将 DayOfWeek 转换为字符串表示 + * @param dayOfWeek DayOfWeek枚举 + * @return 对应的字符串表示 + */ + private String convertDayOfWeekToString(DayOfWeek dayOfWeek) { + switch (dayOfWeek) { + case MONDAY: + return "1"; // 或者 "星期一" 或 "Monday",取决于数据库中的实际存储格式 + case TUESDAY: + return "2"; + case WEDNESDAY: + return "3"; + case THURSDAY: + return "4"; + case FRIDAY: + return "5"; + case SATURDAY: + return "6"; + case SUNDAY: + return "7"; + default: + return "1"; // 默认为星期一 + } + } + @Override public R addDoctorSchedule(DoctorSchedule doctorSchedule) { if (ObjectUtil.isEmpty(doctorSchedule)) { diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/controller/DoctorScheduleController.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/controller/DoctorScheduleController.java index 97355d8b..e97580ee 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/controller/DoctorScheduleController.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/controller/DoctorScheduleController.java @@ -40,4 +40,13 @@ public class DoctorScheduleController { return R.ok(doctorScheduleAppService.removeDoctorSchedule(doctorScheduleId)); } + /* + * 获取今日医生排班List + * + * */ + @GetMapping("/today") + public R getTodayDoctorScheduleList() { + return R.ok(doctorScheduleAppService.getTodayDoctorScheduleList()); + } + } diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/medicationmanagement/controller/DayEndSettlementController.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/medicationmanagement/controller/DayEndSettlementController.java new file mode 100644 index 00000000..1fe41731 --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/medicationmanagement/controller/DayEndSettlementController.java @@ -0,0 +1,88 @@ +package com.openhis.web.medicationmanagement.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.core.common.annotation.Log; +import com.core.common.core.controller.BaseController; +import com.core.common.core.domain.AjaxResult; +import com.core.common.core.page.TableDataInfo; +import com.core.common.enums.BusinessType; +import com.core.common.utils.poi.ExcelUtil; +import com.openhis.domain.DayEndSettlement; +import com.openhis.service.IDayEndSettlementService; +import com.core.common.core.page.PageDomain; +import com.core.common.utils.StringUtils; +import com.github.pagehelper.PageHelper; + +/** + * 日结结算单Controller + * + * @author openhis + * @date 2025-02-01 + */ +@RestController +@RequestMapping("/medication/dayEndSettlement") +public class DayEndSettlementController extends BaseController { + @Autowired + private IDayEndSettlementService dayEndSettlementService; + + /** + * 查询日结结算单列表 + */ + @GetMapping("/list") + public TableDataInfo list(DayEndSettlement dayEndSettlement, PageDomain pageDomain) { + // 使用PageHelper进行分页 + PageHelper.startPage(pageDomain.getPageNum(), pageDomain.getPageSize()); + List list = dayEndSettlementService.lambdaQuery() + .like(StringUtils.isNotBlank(dayEndSettlement.getSettlementNo()), DayEndSettlement::getSettlementNo, dayEndSettlement.getSettlementNo()) + .eq(StringUtils.isNotBlank(dayEndSettlement.getSettlementType()), DayEndSettlement::getSettlementType, dayEndSettlement.getSettlementType()) + .eq(dayEndSettlement.getSettlementDate() != null, DayEndSettlement::getSettlementDate, dayEndSettlement.getSettlementDate()) + .orderByDesc(DayEndSettlement::getId) + .list(); + return getDataTable(list); + } + + /** + * 获取日结结算单详细信息 + */ + @GetMapping(value = "/{id}") + public AjaxResult getInfo(@PathVariable("id") Long id) { + return AjaxResult.success(dayEndSettlementService.getById(id)); + } + + /** + * 新增日结结算单 + */ + @Log(title = "日结结算单", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody DayEndSettlement dayEndSettlement) { + return toAjax(dayEndSettlementService.save(dayEndSettlement)); + } + + /** + * 修改日结结算单 + */ + @Log(title = "日结结算单", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody DayEndSettlement dayEndSettlement) { + return toAjax(dayEndSettlementService.updateById(dayEndSettlement)); + } + + /** + * 删除日结结算单 + */ + @Log(title = "日结结算单", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public AjaxResult remove(@PathVariable Long[] ids) { + return toAjax(dayEndSettlementService.removeByIds(List.of(ids))); + } +} \ No newline at end of file diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/medicationmanagement/domain/DayEndSettlement.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/medicationmanagement/domain/DayEndSettlement.java new file mode 100644 index 00000000..185660cc --- /dev/null +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/medicationmanagement/domain/DayEndSettlement.java @@ -0,0 +1,60 @@ +package com.openhis.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.core.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.math.BigDecimal; +import java.time.LocalDate; + +/** + * 日结结算单对象 medication_day_end_settlement + * + * @author openhis + * @date 2025-02-01 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("medication_day_end_settlement") +public class DayEndSettlement extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 结算单号 + */ + private String settlementNo; + + /** + * 结算日期 + */ + private LocalDate settlementDate; + + /** + * 结算类型 (daily, weekly, monthly) + */ + private String settlementType; + + /** + * 总金额 + */ + private BigDecimal totalAmount; + + /** + * 状态 (0正常 1停用) + */ + private String status; + + /** + * 备注 + */ + private String remark; +} \ No newline at end of file diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/medicationmanagement/mapper/DayEndSettlementMapper.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/medicationmanagement/mapper/DayEndSettlementMapper.java new file mode 100644 index 00000000..87bfca85 --- /dev/null +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/medicationmanagement/mapper/DayEndSettlementMapper.java @@ -0,0 +1,14 @@ +package com.openhis.mapper; + +import com.openhis.domain.DayEndSettlement; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * 日结结算单Mapper接口 + * + * @author openhis + * @date 2025-02-01 + */ +public interface DayEndSettlementMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/medicationmanagement/service/IDayEndSettlementService.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/medicationmanagement/service/IDayEndSettlementService.java new file mode 100644 index 00000000..891097e1 --- /dev/null +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/medicationmanagement/service/IDayEndSettlementService.java @@ -0,0 +1,14 @@ +package com.openhis.service; + +import com.openhis.domain.DayEndSettlement; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + * 日结结算单Service接口 + * + * @author openhis + * @date 2025-02-01 + */ +public interface IDayEndSettlementService extends IService { + +} \ No newline at end of file diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/medicationmanagement/service/impl/DayEndSettlementServiceImpl.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/medicationmanagement/service/impl/DayEndSettlementServiceImpl.java new file mode 100644 index 00000000..adb9dfc6 --- /dev/null +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/medicationmanagement/service/impl/DayEndSettlementServiceImpl.java @@ -0,0 +1,18 @@ +package com.openhis.service.impl; + +import com.openhis.domain.DayEndSettlement; +import com.openhis.mapper.DayEndSettlementMapper; +import com.openhis.service.IDayEndSettlementService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + * 日结结算单Service业务层处理 + * + * @author openhis + * @date 2025-02-01 + */ +@Service +public class DayEndSettlementServiceImpl extends ServiceImpl implements IDayEndSettlementService { + +} \ No newline at end of file diff --git a/openhis-server-new/sql/create_medication_day_end_settlement_table.sql b/openhis-server-new/sql/create_medication_day_end_settlement_table.sql new file mode 100644 index 00000000..c180e645 --- /dev/null +++ b/openhis-server-new/sql/create_medication_day_end_settlement_table.sql @@ -0,0 +1,52 @@ +-- 创建日结结算单表 +CREATE TABLE IF NOT EXISTS medication_day_end_settlement ( + id BIGSERIAL PRIMARY KEY, + settlement_no VARCHAR(64) NOT NULL, + settlement_date DATE NOT NULL, + settlement_type VARCHAR(20) DEFAULT 'daily', + total_amount DECIMAL(15,2) DEFAULT 0.00, + status CHAR(1) DEFAULT '0', + remark VARCHAR(500), + create_by VARCHAR(64) DEFAULT '', + create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_by VARCHAR(64) DEFAULT '', + update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- 添加注释 +COMMENT ON TABLE medication_day_end_settlement IS '日结结算单表'; +COMMENT ON COLUMN medication_day_end_settlement.settlement_no IS '结算单号'; +COMMENT ON COLUMN medication_day_end_settlement.settlement_date IS '结算日期'; +COMMENT ON COLUMN medication_day_end_settlement.settlement_type IS '结算类型 (daily, weekly, monthly)'; +COMMENT ON COLUMN medication_day_end_settlement.total_amount IS '总金额'; +COMMENT ON COLUMN medication_day_end_settlement.status IS '状态 (0正常 1停用)'; +COMMENT ON COLUMN medication_day_end_settlement.remark IS '备注'; +COMMENT ON COLUMN medication_day_end_settlement.create_by IS '创建者'; +COMMENT ON COLUMN medication_day_end_settlement.create_time IS '创建时间'; +COMMENT ON COLUMN medication_day_end_settlement.update_by IS '更新者'; +COMMENT ON COLUMN medication_day_end_settlement.update_time IS '更新时间'; + +-- 添加索引 +CREATE INDEX IF NOT EXISTS idx_settlement_date ON medication_day_end_settlement(settlement_date); +CREATE INDEX IF NOT EXISTS idx_settlement_no ON medication_day_end_settlement(settlement_no); + +-- 创建更新时间触发器函数 +CREATE OR REPLACE FUNCTION update_modified_column() +RETURNS TRIGGER AS $$ +BEGIN + NEW.update_time = CURRENT_TIMESTAMP; + RETURN NEW; +END; +$$ language 'plpgsql'; + +-- 创建更新时间触发器 +DROP TRIGGER IF EXISTS update_medication_day_end_settlement_modtime ON medication_day_end_settlement; +CREATE TRIGGER update_medication_day_end_settlement_modtime + BEFORE UPDATE ON medication_day_end_settlement + FOR EACH ROW + EXECUTE FUNCTION update_modified_column(); + +-- 插入初始数据 +INSERT INTO medication_day_end_settlement (settlement_no, settlement_date, settlement_type, total_amount, status, remark, create_by) VALUES +('DS20250201001', '2025-02-01', 'daily', 15000.00, '0', '2025年2月1日日结', 'admin'), +('DS20250201002', '2025-02-01', 'daily', 8500.50, '0', '药房日结', 'admin'); \ No newline at end of file diff --git a/openhis-server-new/sql/create_user_config_table.sql b/openhis-server-new/sql/create_user_config_table.sql new file mode 100644 index 00000000..ae37f190 --- /dev/null +++ b/openhis-server-new/sql/create_user_config_table.sql @@ -0,0 +1,38 @@ +CREATE TABLE IF NOT EXISTS sys_user_config ( + config_id BIGSERIAL PRIMARY KEY, + user_id BIGINT NOT NULL, + config_key VARCHAR(100) NOT NULL, + config_value TEXT, + remark VARCHAR(500), + create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- 添加注释 +COMMENT ON TABLE sys_user_config IS '用户配置表'; +COMMENT ON COLUMN sys_user_config.config_id IS '配置ID'; +COMMENT ON COLUMN sys_user_config.user_id IS '用户ID'; +COMMENT ON COLUMN sys_user_config.config_key IS '配置键名'; +COMMENT ON COLUMN sys_user_config.config_value IS '配置值'; +COMMENT ON COLUMN sys_user_config.remark IS '备注'; +COMMENT ON COLUMN sys_user_config.create_time IS '创建时间'; +COMMENT ON COLUMN sys_user_config.update_time IS '更新时间'; + +-- 创建唯一索引 +CREATE UNIQUE INDEX IF NOT EXISTS uk_user_config ON sys_user_config (user_id, config_key); +CREATE INDEX IF NOT EXISTS idx_user_id ON sys_user_config (user_id); + +-- 创建更新时间触发器函数 +CREATE OR REPLACE FUNCTION update_updated_at_column() +RETURNS TRIGGER AS $$ +BEGIN + NEW.update_time = CURRENT_TIMESTAMP; + RETURN NEW; +END; +$$ language 'plpgsql'; + +-- 创建触发器 +CREATE TRIGGER update_sys_user_config_updated_at + BEFORE UPDATE ON sys_user_config + FOR EACH ROW + EXECUTE FUNCTION update_updated_at_column(); \ No newline at end of file diff --git a/openhis-ui-vue3/src/api/appointmentmanage/doctorSchedule.js b/openhis-ui-vue3/src/api/appointmentmanage/doctorSchedule.js new file mode 100644 index 00000000..6ff52358 --- /dev/null +++ b/openhis-ui-vue3/src/api/appointmentmanage/doctorSchedule.js @@ -0,0 +1,43 @@ +import request from '@/utils/request' + +// 获取今日医生排班列表 +export function getTodayDoctorScheduleList() { + return request({ + url: '/doctor-schedule/today', + method: 'get' + }) +} + +// 获取医生排班列表 +export function getDoctorScheduleList() { + return request({ + url: '/appointment/doctor-schedule/list', + method: 'get' + }) +} + +// 添加医生排班 +export function addDoctorSchedule(data) { + return request({ + url: '/appointment/doctor-schedule', + method: 'post', + data: data + }) +} + +// 更新医生排班 +export function updateDoctorSchedule(data) { + return request({ + url: '/appointment/doctor-schedule', + method: 'put', + data: data + }) +} + +// 删除医生排班 +export function deleteDoctorSchedule(id) { + return request({ + url: '/appointment/doctor-schedule/delete/' + id, + method: 'delete' + }) +} \ No newline at end of file diff --git a/openhis-ui-vue3/src/api/medicationmanagement/dayEndSettlement.js b/openhis-ui-vue3/src/api/medicationmanagement/dayEndSettlement.js new file mode 100644 index 00000000..30e5ee8b --- /dev/null +++ b/openhis-ui-vue3/src/api/medicationmanagement/dayEndSettlement.js @@ -0,0 +1,44 @@ +import request from '@/utils/request' + +// 查询日结结算单列表 +export function listDayEndSettlement(query) { + return request({ + url: '/medication/dayEndSettlement/list', + method: 'get', + params: query + }) +} + +// 查询日结结算单详细 +export function getDayEndSettlement(settlementId) { + return request({ + url: '/medication/dayEndSettlement/' + settlementId, + method: 'get' + }) +} + +// 新增日结结算单 +export function addDayEndSettlement(data) { + return request({ + url: '/medication/dayEndSettlement', + method: 'post', + data: data + }) +} + +// 修改日结结算单 +export function updateDayEndSettlement(data) { + return request({ + url: '/medication/dayEndSettlement', + method: 'put', + data: data + }) +} + +// 删除日结结算单 +export function delDayEndSettlement(settlementId) { + return request({ + url: '/medication/dayEndSettlement/' + settlementId, + method: 'delete' + }) +} \ No newline at end of file diff --git a/openhis-ui-vue3/src/router/index.js b/openhis-ui-vue3/src/router/index.js index 0f57df7e..aeba7808 100644 --- a/openhis-ui-vue3/src/router/index.js +++ b/openhis-ui-vue3/src/router/index.js @@ -286,6 +286,48 @@ export const dynamicRoutes = [ } ] }, + { + path: '/appoinmentmanage', + component: Layout, + name: 'AppoinmentManage', + meta: { title: '预约管理', icon: 'appointment' }, + children: [ + { + path: 'deptManage', + component: () => import('@/views/appoinmentmanage/deptManage/index.vue'), + name: 'DeptManage', + meta: { title: '科室排班管理', icon: 'calendar' } + } + ] + }, + { + path: '/clinicmanagement', + component: Layout, + name: 'ClinicManagement', + meta: { title: '门诊管理', icon: 'operation' }, + children: [ + { + path: 'dayEnd', + component: () => import('@/views/clinicmanagement/dayEnd/index.vue'), + name: 'DayEnd', + meta: { title: '门诊日结', icon: 'document' } + } + ] + }, + { + path: '/medicationmanagement', + component: Layout, + name: 'MedicationManagement', + meta: { title: '药房管理', icon: 'medication' }, + children: [ + { + path: 'dayEndSettlement', + component: () => import('@/views/medicationmanagement/dayEndSettlement/index.vue'), + name: 'DayEndSettlement', + meta: { title: '日结结算单管理', icon: 'document' } + } + ] + } ]; // 合并常量路由和动态路由,确保所有路由都能被访问 diff --git a/openhis-ui-vue3/src/views/features/config.vue b/openhis-ui-vue3/src/views/features/config.vue index df084751..a549a48a 100644 --- a/openhis-ui-vue3/src/views/features/config.vue +++ b/openhis-ui-vue3/src/views/features/config.vue @@ -39,9 +39,7 @@
- - - + {{ node.label }} {{ data.fullPath }} @@ -88,9 +86,7 @@ class="selected-function-item" >
- - - +
{{ item.menuName }} @@ -193,6 +189,7 @@ import { SuccessFilled, QuestionFilled as QuestionFilledIcon } from '@element-plus/icons-vue' +import SvgIcon from '@/components/SvgIcon' // 添加 loading 状态 const loading = ref(false) @@ -214,81 +211,6 @@ watch(filterText, (val) => { treeRef.value?.filter(val) }) -// 图标映射 -const iconMap = { - 'menu': Menu, - 'grid': Grid, - 'folder': Folder, - 'tickets': Tickets, - 'document': Document, - 'setting': Setting, - 'user': User, - 'goods': Goods, - 'chat-dot-square': ChatDotSquare, - 'histogram': Histogram, - 'wallet': Wallet, - 'office-building': OfficeBuilding, - 'postcard': Postcard, - 'collection': Collection, - 'video-play': VideoPlay, - 'camera': Camera, - 'headset': Headset, - 'phone': Phone, - 'message': Message, - 'chat-line-square': ChatLineSquare, - 'chat-round': ChatRound, - 'guide': Guide, - 'help': Help, - 'info-filled': InfoFilled, - 'circle-check': CircleCheck, - 'circle-close': CircleClose, - 'warning': Warning, - 'question-filled': QuestionFilled, - 'star': Star, - 'link': Link, - 'position': Position, - 'picture': Picture, - 'upload': Upload, - 'download': Download, - 'caret-left': CaretLeft, - 'caret-right': CaretRight, - 'more': More, - 'close': Close, - 'check': Check, - 'arrow-up': ArrowUp, - 'arrow-down': ArrowDown, - 'arrow-left': ArrowLeft, - 'arrow-right': ArrowRight, - 'plus': Plus, - 'minus': Minus, - 'zoom-in': ZoomIn, - 'zoom-out': ZoomOut, - 'refresh': Refresh, - 'search': Search, - 'edit': Edit, - 'delete': Delete, - 'share': Share, - 'view': View, - 'switch-button': SwitchButton, - 'hide': Hide, - 'finished': Finished, - 'circle-plus': CirclePlus, - 'remove': Remove, - 'circle-check-filled': CircleCheckFilled, - 'circle-close-filled': CircleCloseFilled, - 'warning-filled': WarningFilled, - 'info-filled-icon': InfoFilledIcon, - 'success-filled': SuccessFilled, - 'question-filled-icon': QuestionFilledIcon -} - -// 获取图标组件 -const getIconComponent = (iconName) => { - if (!iconName) return Document - // 移除前缀,如 fa-, el-icon- - const cleanIconName = iconName.replace(/^(fa-|el-icon-)/, '').toLowerCase() - return iconMap[cleanIconName] || Document -} // 获取图标颜色 const getIconColor = (data) => { @@ -302,6 +224,24 @@ const getIconColor = (data) => { const loadMenuData = async () => { loading.value = true try { + // 尝试从本地缓存获取菜单数据 + const cachedMenuData = localStorage.getItem('menuTreeCache'); + const cacheTimestamp = localStorage.getItem('menuTreeCacheTimestamp'); + + // 检查缓存是否有效(24小时内) + if (cachedMenuData && cacheTimestamp) { + const cacheAge = Date.now() - parseInt(cacheTimestamp); + if (cacheAge < 24 * 60 * 60 * 1000) { // 24小时 + menuTree.value = JSON.parse(cachedMenuData); + // 展开所有节点 + expandedKeys.value = getAllNodeIds(menuTree.value); + // 获取已保存的配置 + await loadSavedConfig(); + loading.value = false; + return; + } + } + const response = await listMenu({}) if (response.code === 200) { // 过滤掉隐藏的菜单项、目录和按钮类型的菜单,只保留当前角色可访问的菜单项 @@ -311,6 +251,10 @@ const loadMenuData = async () => { // 展开所有节点 expandedKeys.value = getAllNodeIds(filteredMenus) + // 将菜单数据缓存到本地存储 + localStorage.setItem('menuTreeCache', JSON.stringify(filteredMenus)); + localStorage.setItem('menuTreeCacheTimestamp', Date.now().toString()); + // 获取已保存的配置 await loadSavedConfig() } else { @@ -389,7 +333,7 @@ const saveConfig = async () => { fullPath: fullPath, menuName: node.menuName, path: node.path, - icon: node.icon, // 保存图标信息 + icon: node.icon, // 保存数据库中的图标类名 menuType: node.menuType // 保存菜单类型信息 }; @@ -406,7 +350,7 @@ const saveConfig = async () => { fullPath: node.path, menuName: node.menuName, path: node.path, - icon: node.icon, // 保存图标信息 + icon: node.icon, // 保存数据库中的图标类名 menuType: node.menuType // 保存菜单类型信息 }; console.log(`构造的菜单项对象(错误处理):`, menuItem); @@ -435,6 +379,9 @@ const saveConfig = async () => { if (saveResult.code === 200) { // 只有在数据库保存成功后,才保存到本地存储 localStorage.setItem('homeFeaturesConfig', JSON.stringify(menuDataWithPaths)) + // 清除菜单树缓存,以便下次加载最新数据 + localStorage.removeItem('menuTreeCache'); + localStorage.removeItem('menuTreeCacheTimestamp'); ElMessage.success('配置保存成功') // 触发全局事件,通知首页更新快捷功能 window.dispatchEvent(new Event('homeFeaturesConfigUpdated')); @@ -493,6 +440,36 @@ const filterNode = (value, data) => { // 加载已保存的配置 const loadSavedConfig = async () => { try { + // 尝试从本地缓存获取配置 + const cachedConfig = localStorage.getItem('homeFeaturesConfigCache'); + const cacheTimestamp = localStorage.getItem('homeFeaturesConfigCacheTimestamp'); + + // 检查缓存是否有效(1小时内) + if (cachedConfig && cacheTimestamp) { + const cacheAge = Date.now() - parseInt(cacheTimestamp); + if (cacheAge < 60 * 60 * 1000) { // 1小时 + const parsedConfig = JSON.parse(cachedConfig); + // 检查数据格式,如果是包含对象的数组(新格式),提取菜单ID + if (parsedConfig && Array.isArray(parsedConfig)) { + if (parsedConfig.length > 0 && typeof parsedConfig[0] === 'object' && parsedConfig[0].hasOwnProperty('menuId')) { + // 新格式:[{menuId: 1, fullPath: "...", ...}, ...] + checkedKeys.value = parsedConfig.map(item => item.menuId); + } else { + // 旧格式:[1, 2, 3, ...] + checkedKeys.value = parsedConfig; + } + + // 根据保存的配置初始化已选择的功能 + const allNodes = getAllNodes(menuTree.value) + const checkedNodes = allNodes.filter(node => + checkedKeys.value.includes(node.menuId) && node.menuType === 'C' + ) + selectedFunctions.value = checkedNodes + } + return; // 使用缓存数据,直接返回 + } + } + // 优先从数据库获取已保存的配置 const response = await getCurrentUserConfig('homeFeaturesConfig') let savedConfig = null; @@ -539,6 +516,10 @@ const loadSavedConfig = async () => { checkedKeys.value.includes(node.menuId) && node.menuType === 'C' ) selectedFunctions.value = checkedNodes + + // 将配置缓存到本地存储 + localStorage.setItem('homeFeaturesConfigCache', JSON.stringify(parsedConfig)); + localStorage.setItem('homeFeaturesConfigCacheTimestamp', Date.now().toString()); } else { // 如果解析失败,使用默认配置 const defaultSelections = getDefaultSelections(menuTree.value) diff --git a/openhis-ui-vue3/src/views/index.vue b/openhis-ui-vue3/src/views/index.vue index 1d5c385c..f8db71d6 100644 --- a/openhis-ui-vue3/src/views/index.vue +++ b/openhis-ui-vue3/src/views/index.vue @@ -59,9 +59,7 @@ @click="handleQuickAccess(func)" >
- - - +
{{ func.label }}
@@ -138,6 +136,7 @@ import { getHomeStatistics, getPendingEmrCount } from '@/api/home' import { listTodo } from '@/api/workflow/task.js' import { getCurrentUserConfig } from '@/api/system/userConfig' import { listMenu, getMenuFullPath } from '@/api/system/menu' +import { getTodayDoctorScheduleList } from '@/api/appointmentmanage/doctorSchedule' import { ElDivider } from 'element-plus' import { User, @@ -220,6 +219,7 @@ import { // 为别名单独导入 import { InfoFilled as InfoFilledIcon, QuestionFilled as QuestionFilledIcon, SuccessFilled } from '@element-plus/icons-vue' +import SvgIcon from '@/components/SvgIcon' const userStore = useUserStore() const router = useRouter() @@ -400,8 +400,8 @@ const convertMenuIdsToQuickAccess = async (menuIds) => { return { key: menuItem.menuId, label: menuItem.menuName, - icon: getIconComponent(menuItem.icon || 'Document'), // 使用菜单项的图标,如果没有则使用默认图标 - iconColor: getIconColorByMenuType(menuItem.menuType) || '#67C23A', // 使用菜单类型的颜色,如果没有则使用默认颜色 + icon: menuItem.icon || 'document', // 使用数据库中的图标类名 + iconColor: menuItem.iconColor || getIconColorByMenuType(menuItem.menuType) || '#67C23A', // 优先使用数据库中的颜色,否则使用菜单类型的颜色 route: route }; }).filter(item => item.route); // 过滤掉 route 为空的项 @@ -436,8 +436,8 @@ const convertMenuIdsToQuickAccess = async (menuIds) => { return { key: matchedMenu.perms || matchedMenu.path || `menu_${matchedMenu.menuId}`, label: matchedMenu.menuName, - icon: getIconComponent(matchedMenu.icon), - iconColor: getIconColorByMenuType(matchedMenu.menuType), + icon: matchedMenu.icon || 'document', // 使用数据库中的图标类名 + iconColor: matchedMenu.iconColor || getIconColorByMenuType(matchedMenu.menuType), route: fullPath || matchedMenu.path // 确保 route 不为空 }; } catch (error) { @@ -446,8 +446,8 @@ const convertMenuIdsToQuickAccess = async (menuIds) => { return { key: matchedMenu.perms || matchedMenu.path || `menu_${matchedMenu.menuId}`, label: matchedMenu.menuName, - icon: getIconComponent(matchedMenu.icon), - iconColor: getIconColorByMenuType(matchedMenu.menuType), + icon: matchedMenu.icon || 'document', // 使用数据库中的图标类名 + iconColor: matchedMenu.iconColor || getIconColorByMenuType(matchedMenu.menuType), route: matchedMenu.path || matchedMenu.fullPath || '/' // 确保 route 不为空 }; } @@ -490,81 +490,6 @@ const flattenMenuTree = (menuTree) => { return result; }; -// 获取图标组件 -const getIconComponent = (iconName) => { - if (!iconName) return Document; - // 移除前缀,如 fa-, el-icon- - const cleanIconName = iconName.replace(/^(fa-|el-icon-)/, '').toLowerCase(); - - const iconMap = { - 'menu': markRaw(Menu), - 'grid': markRaw(Grid), - 'folder': markRaw(Folder), - 'tickets': markRaw(Tickets), - 'document': markRaw(Document), - 'setting': markRaw(Setting), - 'user': markRaw(User), - 'goods': markRaw(Goods), - 'chat-dot-square': markRaw(ChatDotSquare), - 'histogram': markRaw(Histogram), - 'wallet': markRaw(Wallet), - 'office-building': markRaw(OfficeBuilding), - 'postcard': markRaw(Postcard), - 'collection': markRaw(Collection), - 'video-play': markRaw(VideoPlay), - 'camera': markRaw(Camera), - 'headset': markRaw(Headset), - 'phone': markRaw(Phone), - 'message': markRaw(Message), - 'chat-line-square': markRaw(ChatLineSquare), - 'chat-round': markRaw(ChatRound), - 'guide': markRaw(Guide), - 'help': markRaw(Help), - 'info-filled': markRaw(InfoFilled), - 'circle-check': markRaw(CircleCheck), - 'circle-close': markRaw(CircleClose), - 'warning': markRaw(Warning), - 'question-filled': markRaw(QuestionFilled), - 'star': markRaw(Star), - 'link': markRaw(Link), - 'position': markRaw(Position), - 'picture': markRaw(Picture), - 'upload': markRaw(Upload), - 'download': markRaw(Download), - 'caret-left': markRaw(CaretLeft), - 'caret-right': markRaw(CaretRight), - 'more': markRaw(More), - 'close': markRaw(Close), - 'check': markRaw(Check), - 'arrow-up': markRaw(ArrowUp), - 'arrow-down': markRaw(ArrowDown), - 'arrow-left': markRaw(ArrowLeft), - 'arrow-right': markRaw(ArrowRight), - 'plus': markRaw(Plus), - 'minus': markRaw(Minus), - 'zoom-in': markRaw(ZoomIn), - 'zoom-out': markRaw(ZoomOut), - 'refresh': markRaw(Refresh), - 'search': markRaw(Search), - 'edit': markRaw(Edit), - 'delete': markRaw(Delete), - 'share': markRaw(Share), - 'view': markRaw(View), - 'switch-button': markRaw(SwitchButton), - 'hide': markRaw(Hide), - 'finished': markRaw(Finished), - 'circle-plus': markRaw(CirclePlus), - 'remove': markRaw(Remove), - 'circle-check-filled': markRaw(CircleCheckFilled), - 'circle-close-filled': markRaw(CircleCloseFilled), - 'warning-filled': markRaw(WarningFilled), - 'info-filled-icon': markRaw(InfoFilledIcon), - 'success-filled': markRaw(SuccessFilled), - 'question-filled-icon': markRaw(QuestionFilledIcon) - }; - - return iconMap[cleanIconName] || markRaw(Document); -}; // 根据菜单类型获取图标颜色 const getIconColorByMenuType = (menuType) => { @@ -581,48 +506,48 @@ const getDefaultQuickAccessConfig = () => { switch (role) { case 'doctor': return [ - { key: 'outpatient', label: '门诊接诊', icon: markRaw(ChatDotRound), iconColor: '#409eff', route: '/doctorstation' }, - { key: 'emr', label: '病历管理', icon: markRaw(Document), iconColor: '#67c23a', route: '/doctorstation/doctorphrase' }, - { key: 'prescription', label: '开立处方', icon: markRaw(Box), iconColor: '#e6a23c', route: '/clinicmanagement/ePrescribing' }, - { key: 'history', label: '历史处方', icon: markRaw(Clock), iconColor: '#f56c6c', route: '/clinicmanagement/historicalPrescription' }, - { key: 'schedule', label: '排班管理', icon: markRaw(Calendar), iconColor: '#909399', route: '/appoinmentmanage/deptManage' }, - { key: 'inquiry', label: '患者查询', icon: markRaw(Search), iconColor: '#409eff', route: '/patientmanagement' } + { key: 'outpatient', label: '门诊接诊', icon: 'chat-dot-round', iconColor: '#409eff', route: '/doctorstation' }, + { key: 'emr', label: '病历管理', icon: 'document', iconColor: '#67c23a', route: '/doctorstation/doctorphrase' }, + { key: 'prescription', label: '开立处方', icon: 'box', iconColor: '#e6a23c', route: '/clinicmanagement/ePrescribing' }, + { key: 'history', label: '历史处方', icon: 'clock', iconColor: '#f56c6c', route: '/clinicmanagement/historicalPrescription' }, + { key: 'schedule', label: '排班管理', icon: 'calendar', iconColor: '#909399', route: '/appoinmentmanage/deptManage' }, + { key: 'inquiry', label: '患者查询', icon: 'search', iconColor: '#409eff', route: '/patientmanagement' } ]; case 'nurse': return [ - { key: 'ward', label: '病房管理', icon: markRaw(User), iconColor: '#409eff', route: '/inpatientNurse/inpatientNurseStation' }, - { key: 'execution', label: '医嘱执行', icon: markRaw(Operation), iconColor: '#67c23a', route: '/inpatientNurse/medicalOrderExecution' }, - { key: 'proofread', label: '医嘱核对', icon: markRaw(Document), iconColor: '#e6a23c', route: '/inpatientNurse/medicalOrderProofread' }, - { key: 'drugCollect', label: '领药管理', icon: markRaw(Box), iconColor: '#f56c6c', route: '/inpatientNurse/medicineCollect' }, - { key: 'tpr', label: '体温单', icon: markRaw(Monitor), iconColor: '#909399', route: '/inpatientNurse/tprsheet' }, - { key: 'nursing', label: '护理记录', icon: markRaw(ChatDotRound), iconColor: '#409eff', route: '/inpatientNurse/nursingRecord' } + { key: 'ward', label: '病房管理', icon: 'user', iconColor: '#409eff', route: '/inpatientNurse/inpatientNurseStation' }, + { key: 'execution', label: '医嘱执行', icon: 'operation', iconColor: '#67c23a', route: '/inpatientNurse/medicalOrderExecution' }, + { key: 'proofread', label: '医嘱核对', icon: 'document', iconColor: '#e6a23c', route: '/inpatientNurse/medicalOrderProofread' }, + { key: 'drugCollect', label: '领药管理', icon: 'box', iconColor: '#f56c6c', route: '/inpatientNurse/medicineCollect' }, + { key: 'tpr', label: '体温单', icon: 'monitor', iconColor: '#909399', route: '/inpatientNurse/tprsheet' }, + { key: 'nursing', label: '护理记录', icon: 'chat-dot-round', iconColor: '#409eff', route: '/inpatientNurse/nursingRecord' } ]; case 'pharmacist': return [ - { key: 'dispensing', label: '发药管理', icon: markRaw(Box), iconColor: '#409eff', route: '/pharmacymanagement' }, - { key: 'prescription', label: '处方审核', icon: markRaw(Document), iconColor: '#67c23a', route: '/pharmacymanagement' }, - { key: 'inventory', label: '库存管理', icon: markRaw(Van), iconColor: '#e6a23c', route: '/medicineStorage' }, - { key: 'purchase', label: '采购管理', icon: markRaw(ShoppingCart), iconColor: '#f56c6c', route: '/medicineStorage' }, - { key: 'warning', label: '效期预警', icon: markRaw(Warning), iconColor: '#f56c6c', route: '/medicationmanagement/statisticalManagement/statisticalManagement' }, - { key: 'statistics', label: '用药统计', icon: markRaw(DataLine), iconColor: '#909399', route: '/monitor' } + { key: 'dispensing', label: '发药管理', icon: 'box', iconColor: '#409eff', route: '/pharmacymanagement' }, + { key: 'prescription', label: '处方审核', icon: 'document', iconColor: '#67c23a', route: '/pharmacymanagement' }, + { key: 'inventory', label: '库存管理', icon: 'van', iconColor: '#e6a23c', route: '/medicineStorage' }, + { key: 'purchase', label: '采购管理', icon: 'shopping-cart', iconColor: '#f56c6c', route: '/medicineStorage' }, + { key: 'warning', label: '效期预警', icon: 'warning', iconColor: '#f56c6c', route: '/medicationmanagement/statisticalManagement/statisticalManagement' }, + { key: 'statistics', label: '用药统计', icon: 'data-line', iconColor: '#909399', route: '/monitor' } ]; case 'cashier': return [ - { key: 'registration', label: '挂号收费', icon: markRaw(Money), iconColor: '#409eff', route: '/charge/outpatientregistration' }, - { key: 'clinicCharge', label: '门诊收费', icon: markRaw(Wallet), iconColor: '#67c23a', route: '/charge/cliniccharge' }, - { key: 'refund', label: '退费管理', icon: markRaw(Document), iconColor: '#e6a23c', route: '/charge/clinicrefund' }, - { key: 'invoice', label: '发票打印', icon: markRaw(Files), iconColor: '#f56c6c', route: '/basicmanage/InvoiceManagement' }, - { key: 'record', label: '收费记录', icon: markRaw(Clock), iconColor: '#909399', route: '/charge/clinicRecord' }, - { key: 'insurance', label: '医保结算', icon: markRaw(Bell), iconColor: '#409eff', route: '/ybmanagement' } + { key: 'registration', label: '挂号收费', icon: 'money', iconColor: '#409eff', route: '/charge/outpatientregistration' }, + { key: 'clinicCharge', label: '门诊收费', icon: 'wallet', iconColor: '#67c23a', route: '/charge/cliniccharge' }, + { key: 'refund', label: '退费管理', icon: 'document', iconColor: '#e6a23c', route: '/charge/clinicrefund' }, + { key: 'invoice', label: '发票打印', icon: 'files', iconColor: '#f56c6c', route: '/basicmanage/InvoiceManagement' }, + { key: 'record', label: '收费记录', icon: 'clock', iconColor: '#909399', route: '/charge/clinicRecord' }, + { key: 'insurance', label: '医保结算', icon: 'bell', iconColor: '#409eff', route: '/ybmanagement' } ]; default: // admin return [ - { key: 'patient', label: '患者管理', icon: markRaw(User), iconColor: '#409eff', route: '/patient/patientmgr' }, - { key: 'appointment', label: '预约管理', icon: markRaw(Calendar), iconColor: '#67c23a', route: '/appoinmentmanage' }, - { key: 'doctor', label: '医生管理', icon: markRaw(User), iconColor: '#e6a23c', route: '/doctorstation' }, - { key: 'surgery', label: '手术管理', icon: markRaw(Operation), iconColor: '#f56c6c', route: '/surgerymanage' }, - { key: 'drug', label: '药品管理', icon: markRaw(Box), iconColor: '#909399', route: '/pharmacymanagement' }, - { key: 'statistic', label: '数据统计', icon: markRaw(TrendCharts), iconColor: '#409eff', route: '/monitor' } + { key: 'patient', label: '患者管理', icon: 'user', iconColor: '#409eff', route: '/patient/patientmgr' }, + { key: 'appointment', label: '预约管理', icon: 'calendar', iconColor: '#67c23a', route: '/appoinmentmanage' }, + { key: 'doctor', label: '医生管理', icon: 'user', iconColor: '#e6a23c', route: '/doctorstation' }, + { key: 'surgery', label: '手术管理', icon: 'operation', iconColor: '#f56c6c', route: '/surgerymanage' }, + { key: 'drug', label: '药品管理', icon: 'box', iconColor: '#909399', route: '/pharmacymanagement' }, + { key: 'statistic', label: '数据统计', icon: 'trend-charts', iconColor: '#409eff', route: '/monitor' } ]; } }; @@ -639,12 +564,7 @@ const updatePendingEmrTodo = () => { } // 今日日程 -const scheduleList = ref([ - { id: 1, time: '09:00', title: '科室晨会', location: '第一会议室', type: 'info', tag: '日常' }, - { id: 2, time: '10:30', title: '病例讨论', location: '第二会议室', type: 'primary', tag: '会议' }, - { id: 3, time: '14:00', title: '专家查房', location: '住院部3楼', type: 'warning', tag: '重要' }, - { id: 4, time: '16:00', title: '新药培训', location: '培训中心', type: 'success', tag: '培训' } -]) +const scheduleList = ref([]) // 获取问候语 const getGreeting = () => { @@ -980,8 +900,58 @@ const getTaskIcon = (category) => { // 获取日程数据(实际应用中应该从API获取) const fetchScheduleList = async () => { - // TODO: 调用API获取真实数据 - console.log('Fetching schedule list...') + try { + console.log('Fetching schedule list...') + const response = await getTodayDoctorScheduleList() + if (response.code === 200) { + // 将API返回的数据转换为前端所需的格式 + const scheduleData = response.data.map((schedule, index) => { + // 根据排班类型设置标签类型 + let tagType = 'info' + if (schedule.weekday) { + tagType = schedule.weekday.toLowerCase() + } else if (schedule.timePeriod) { + tagType = schedule.timePeriod.toLowerCase() + } + + // 确定标题 + const title = schedule.doctor ? `${schedule.doctor}医生排班` : '医生排班' + + // 确定位置 + const location = schedule.clinic || schedule.deptId || '未知科室' + + return { + id: schedule.id || index, + time: schedule.startTime || '未知时间', + title: title, + location: location, + type: tagType, + tag: schedule.timePeriod || '排班' + } + }) + + // 更新日程列表 + scheduleList.value = scheduleData + } else { + console.error('获取排班信息失败:', response.msg) + // 如果API调用失败,使用默认数据 + scheduleList.value = [ + { id: 1, time: '09:00', title: '科室晨会', location: '第一会议室', type: 'info', tag: '日常' }, + { id: 2, time: '10:30', title: '病例讨论', location: '第二会议室', type: 'primary', tag: '会议' }, + { id: 3, time: '14:00', title: '专家查房', location: '住院部3楼', type: 'warning', tag: '重要' }, + { id: 4, time: '16:00', title: '新药培训', location: '培训中心', type: 'success', tag: '培训' } + ] + } + } catch (error) { + console.error('获取排班信息异常:', error) + // 如果出现异常,使用默认数据 + scheduleList.value = [ + { id: 1, time: '09:00', title: '科室晨会', location: '第一会议室', type: 'info', tag: '日常' }, + { id: 2, time: '10:30', title: '病例讨论', location: '第二会议室', type: 'primary', tag: '会议' }, + { id: 3, time: '14:00', title: '专家查房', location: '住院部3楼', type: 'warning', tag: '重要' }, + { id: 4, time: '16:00', title: '新药培训', location: '培训中心', type: 'success', tag: '培训' } + ] + } } // 监听本地存储变化,以便在其他标签页或窗口中修改配置后更新当前页面 diff --git a/openhis-ui-vue3/src/views/medicationmanagement/dayEndSettlement/index.vue b/openhis-ui-vue3/src/views/medicationmanagement/dayEndSettlement/index.vue new file mode 100644 index 00000000..563ba1dc --- /dev/null +++ b/openhis-ui-vue3/src/views/medicationmanagement/dayEndSettlement/index.vue @@ -0,0 +1,335 @@ + + + \ No newline at end of file diff --git a/openhis-ui-vue3/src/views/system/menu/index.vue b/openhis-ui-vue3/src/views/system/menu/index.vue index 7d0b6d18..0f7487ab 100644 --- a/openhis-ui-vue3/src/views/system/menu/index.vue +++ b/openhis-ui-vue3/src/views/system/menu/index.vue @@ -124,9 +124,9 @@ - 目录 - 菜单 - 按钮 + 目录 + 菜单 + 按钮 @@ -174,8 +174,8 @@ - - + + @@ -247,8 +247,8 @@ - 缓存 - 不缓存 + 缓存 + 不缓存 @@ -266,7 +266,7 @@ {{ dict.label }} @@ -285,7 +285,7 @@ {{ dict.label }} @@ -303,7 +303,7 @@