Compare commits

..

40 Commits

Author SHA1 Message Date
633cf2c17f 门诊医生站患者病历打不开 不显示数据问题 2025-12-16 17:12:21 +08:00
3188ca5752 build(openhis-ui-vue3): 更新 sass 依赖版本并注释部分路由配置
更新 sass 依赖从 ^1.70.0 到 ^1.77.8,并注释掉 router 中暂时未使用的路由配置项,
包括门诊医生站、套餐管理、预约管理、基础管理、维护系统及系统管理等相关路由。
2025-12-16 13:49:06 +08:00
py
c79e4c2623 需求27:增加挂号收费系统参数维护界面-》挂号处理相关参数 2025-12-16 13:33:50 +08:00
f3c451d0a1 解决首页和门诊挂号保存报错问题 2025-12-15 17:06:25 +08:00
a077bd57d4 预约管理->相关文件转移、号源后端接口实现、前端页面逻辑、数据处理修改。 2025-12-15 16:50:16 +08:00
cf16c497bd 修改路由配置 2025-12-15 16:05:16 +08:00
fd1ab239a9 门诊出诊医生诊室设置 2025-12-15 15:37:23 +08:00
caf65e3113 ```
feat(router): 优化路由配置与注释说明

- 重构 constantRoutes 和 dynamicRoutes 中的路由结构,提升可读性
- 补充详细的路由配置项注释,便于后续维护
- 添加路由名称检查避免重复添加相同路由
- 更新数据库连接地址及 Redis 配置信息
- 完善 .gitignore 忽略文件列表,排除临时文件和日志
```
2025-12-15 14:24:45 +08:00
c18c21ff4c ```
build(openhis-ui-vue3): 更新 package-lock.json 文件

添加 resolutions 字段以解决依赖版本冲突问题,包含 stable、source-map-url、
urix、resolve-url、source-map-resolve 和 sourcemap-codec 等依赖包的版本
锁定,确保项目构建稳定性。
```
2025-12-14 15:01:10 +08:00
ab6849c9eb 根据您提供的信息,没有实际的代码差异内容。但我可以为您提供一个符合Angular规范的commit message模板示例:
```
docs(changelog): 更新版本发布说明

添加新功能描述和bug修复记录到更新日志中,
确保所有重要的变更都已正确记录以便用户查阅。
```

如果您有具体的代码差异信息,请提供详细内容,我将为您生成更准确的commit message。
2025-12-14 14:53:10 +08:00
6b555f2563 fix(openhis-ui-vue3): 降级 element-plus-icons-vue 版本
将 @element-plus/icons-vue 从版本 2.5.0 降级到 2.3.2,以解决可能存在的兼容性问题或回退到稳定版本。
2025-12-14 14:53:02 +08:00
7645405c5b 更新组件 2025-12-14 14:44:43 +08:00
5bfadb9174 fix(login): 修复获取用户绑定租户列表时用户名为空导致的URL错误
确保username参数存在,避免因为空值造成接口调用失败

feat(editor): 重构富文本编辑器组件并优化图片上传逻辑
- 使用 Composition API 重构代码结构,提升可维护性
- 改进图片上传功能,增强对 quill 实例的安全访问
- 更新样式排版,提高组件可读性和一致性

refactor(file-upload): 移除旧代理引用,使用 modern Vue API
替换 `proxy` 调用为 `modal` 插件直接调用,提升代码清晰度与健壮性

refactor(image-upload): 替换旧实例调用方式,强化错误提示机制
统一使用 `modal` 进行消息提示和加载状态控制,改善用户体验

refactor(tree-select): 引入 Composition API 优化节点操作逻辑
移除 `getCurrentInstance` 的不必要使用,改为明确的模板引用管理

chore(main): 添加 util._extend 补丁以消除 Node.js 环境警告
解决开发环境下由于 Node.js 内建模块缺失造成的运行时警告问题

feat(template): 完善跌倒/坠床评估护理记录单模板
- 增加详细注释说明各部分作用,便于后续维护
- 明确组件名称为中文,利于业务识别
- 丰富表单交互细节及数据处理逻辑,支持动态打分、措施选择等功能

refactor(template-index): 加强模板组件自动注册逻辑
增加组件 name 属性校验,防止无效或匿名组件被注册到全局
2025-12-14 14:22:55 +08:00
e1b9d36153 feat(template): 添加股骨头坏死门诊病历模板
新增了一个名为“股骨头坏死(模板1)”的门诊病历模板文件,包含完整的主诉、现病史、既往史、体格检查、辅助检查、诊断和治疗方案等内容,便于医生快速调用和填写。

该模板位于 `src/template/股骨头坏死(模板1).vue`,采用 Vue 单文件组件格式编写,并定义了相应的结构与样式。
2025-12-13 22:23:58 +08:00
fdb8d6c934 更新模板注释测试中文名 2025-12-13 22:18:56 +08:00
22a1ac57b2 改回配置IP地址 2025-12-13 16:06:13 +08:00
4d243815a6 修正格式 2025-12-13 16:03:06 +08:00
882e8c9199 修正问题 2025-12-12 17:06:14 +08:00
a0c87f6335 问题关键 2025-12-12 17:01:24 +08:00
538dde55f7 还原门诊医生站 2025-12-12 15:57:03 +08:00
f33e3c6f15 首页报错和门诊医生站报错 2025-12-12 15:48:07 +08:00
0794782505 TypeScript Vue Plugi 2025-12-12 15:43:58 +08:00
d37fa46b5f 删除rabbitmq 2025-12-12 15:07:27 +08:00
8fcc229ad8 关联套餐设置页面对应字段 2025-12-12 10:59:22 +08:00
39aa710fd3 医生排班后端接口异常修复 2025-12-12 09:12:40 +08:00
49f95b40ea Merge branch 'develop' of https://gitea.gentronhealth.com/Yajentine/his into develop 2025-12-12 09:11:50 +08:00
eb2d7302b7 添加文件 2025-12-11 22:04:00 +08:00
eb26f9db34 添加文件 2025-12-11 22:03:51 +08:00
bd6f3ca587 医生排班页面修复,新增组件间交互功能。 2025-12-11 17:14:48 +08:00
a58e02f2cb 预约管理 2025-12-11 16:23:59 +08:00
8c8ef13021 预约管理需求 2025-12-11 16:06:09 +08:00
d9a0a98f52 预约管理需求 2025-12-11 15:53:00 +08:00
8c84b6eb46 修正可以显示出主页 2025-12-11 15:23:16 +08:00
3d797cc0e0 修正前端问题 2025-12-11 14:47:17 +08:00
df7281a2d4 INDEX.JS修正 2025-12-10 16:33:41 +08:00
f83d7ae520 修改index.js 2025-12-10 16:29:00 +08:00
d9c8525b94 修正问题 2025-12-10 16:04:18 +08:00
bcc5cbb2fb 删除miniapp相关 2025-12-10 15:48:35 +08:00
67a8351d70 Merge remote-tracking branch 'origin/develop' into develop 2025-12-10 15:45:19 +08:00
391506e423 医生排班 2025-12-10 15:44:36 +08:00
95 changed files with 8857 additions and 9611 deletions

4
.gitignore vendored
View File

@@ -58,3 +58,7 @@
PostgreSQL/openHis_DB设计书.xlsx
public.sql
发版记录/2025-11-12/~$发版日志.docx
发版记录/2025-11-12/~$S-管理系统-调价管理.docx
发版记录/2025-11-12/发版日志.docx
.gitignore

View File

@@ -16,6 +16,12 @@
</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Spring 配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
@@ -56,10 +62,10 @@
<artifactId>httpclient</artifactId>
</dependency>
<!-- rabbitMQ -->
<dependency>
<!-- <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
</dependency> -->
</dependencies>

View File

@@ -0,0 +1,45 @@
package com.openhis.web.appointmentmanage.appservice;
import com.core.common.core.domain.R;
import com.openhis.appointmentmanage.domain.ClinicRoom;
public interface IClinicRoomAppService {
/**
* 分页查询诊室列表
* @param pageNum 页码
* @param pageSize 每页条数
* @param orgName 卫生机构名称
* @param roomName 诊室名称
* @return 分页查询结果
*/
R<?> selectClinicRoomPage(Integer pageNum, Integer pageSize, String orgName, String roomName);
/**
* 查询诊室详情
* @param id 诊室ID
* @return 诊室详情
*/
R<?> selectClinicRoomById(Long id);
/**
* 新增诊室
* @param clinicRoom 诊室信息
* @return 新增结果
*/
R<?> insertClinicRoom(ClinicRoom clinicRoom);
/**
* 更新诊室
* @param clinicRoom 诊室信息
* @return 更新结果
*/
R<?> updateClinicRoom(ClinicRoom clinicRoom);
/**
* 删除诊室
* @param id 诊室ID
* @return 删除结果
*/
R<?> deleteClinicRoomById(Long id);
}

View File

@@ -0,0 +1,13 @@
package com.openhis.web.appointmentmanage.appservice;
import com.core.common.core.domain.R;
import com.openhis.appointmentmanage.domain.DoctorSchedule;
public interface IDoctorScheduleAppService {
R<?> getDoctorScheduleList();
R<?> addDoctorSchedule(DoctorSchedule doctorSchedule);
R<?> removeDoctorSchedule(Integer doctorScheduleId);
}

View File

@@ -0,0 +1,8 @@
package com.openhis.web.appointmentmanage.appservice;
import com.core.common.core.domain.R;
import com.openhis.web.appointmentmanage.dto.SchedulePoolDto;
public interface ISchedulePoolAppService {
R<?> addSchedulePool(SchedulePoolDto schedulePoolDto);
}

View File

@@ -0,0 +1,4 @@
package com.openhis.web.appointmentmanage.appservice;
public interface IScheduleSlotAppService {
}

View File

@@ -0,0 +1,121 @@
package com.openhis.web.appointmentmanage.appservice.impl;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.openhis.appointmentmanage.domain.ClinicRoom;
import com.openhis.appointmentmanage.service.IClinicRoomService;
import com.openhis.web.appointmentmanage.appservice.IClinicRoomAppService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class ClinicRoomAppServiceImpl implements IClinicRoomAppService {
@Resource
private IClinicRoomService clinicRoomService;
@Override
public R<?> selectClinicRoomPage(Integer pageNum, Integer pageSize, String orgName, String roomName) {
// 构建查询条件
ClinicRoom clinicRoom = new ClinicRoom();
if (orgName != null && ObjectUtil.isNotEmpty(orgName)) {
clinicRoom.setOrgName(orgName);
}
if (roomName != null && ObjectUtil.isNotEmpty(roomName)) {
clinicRoom.setRoomName(roomName);
}
// 分页查询
Page<ClinicRoom> page = new Page<>(pageNum, pageSize);
Page<ClinicRoom> result = clinicRoomService.selectClinicRoomPage(page, clinicRoom);
return R.ok(result);
}
@Override
public R<?> selectClinicRoomById(Long id) {
ClinicRoom clinicRoom = clinicRoomService.selectClinicRoomById(id);
if (clinicRoom == null) {
return R.fail(404, "诊室不存在");
}
return R.ok(clinicRoom);
}
@Override
public R<?> insertClinicRoom(ClinicRoom clinicRoom) {
// 数据校验
if (ObjectUtil.isEmpty(clinicRoom.getRoomName())) {
return R.fail(400, "诊室名称不能为空");
}
if (ObjectUtil.isEmpty(clinicRoom.getDepartment())) {
return R.fail(400, "科室名称不能为空");
}
if (clinicRoom.getRoomName().length() > 50) {
return R.fail(400, "诊室名称长度不能超过50个字符");
}
if (clinicRoom.getRemarks() != null && clinicRoom.getRemarks().length() > 500) {
return R.fail(400, "备注长度不能超过500个字符");
}
// 新增诊室
int result = clinicRoomService.insertClinicRoom(clinicRoom);
if (result > 0) {
return R.ok(null, "新增成功");
} else {
return R.fail("新增失败");
}
}
@Override
public R<?> updateClinicRoom(ClinicRoom clinicRoom) {
// 数据校验
if (ObjectUtil.isEmpty(clinicRoom.getId())) {
return R.fail(400, "诊室ID不能为空");
}
if (ObjectUtil.isEmpty(clinicRoom.getRoomName())) {
return R.fail(400, "诊室名称不能为空");
}
if (ObjectUtil.isEmpty(clinicRoom.getDepartment())) {
return R.fail(400, "科室名称不能为空");
}
if (clinicRoom.getRoomName().length() > 50) {
return R.fail(400, "诊室名称长度不能超过50个字符");
}
if (clinicRoom.getRemarks() != null && clinicRoom.getRemarks().length() > 500) {
return R.fail(400, "备注长度不能超过500个字符");
}
// 检查诊室是否存在
ClinicRoom existingClinicRoom = clinicRoomService.selectClinicRoomById(clinicRoom.getId());
if (existingClinicRoom == null) {
return R.fail(404, "诊室不存在");
}
// 更新诊室
int result = clinicRoomService.updateClinicRoom(clinicRoom);
if (result > 0) {
return R.ok(null, "修改成功");
} else {
return R.fail("修改失败");
}
}
@Override
public R<?> deleteClinicRoomById(Long id) {
// 检查诊室是否存在
ClinicRoom existingClinicRoom = clinicRoomService.selectClinicRoomById(id);
if (existingClinicRoom == null) {
return R.fail(404, "诊室不存在");
}
// 删除诊室
int result = clinicRoomService.deleteClinicRoomById(id);
if (result > 0) {
return R.ok(null, "删除成功");
} else {
return R.fail("删除失败");
}
}
}

View File

@@ -3,8 +3,8 @@ 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.administration.domain.Dept;
import com.openhis.administration.service.IDeptService;
import com.openhis.appointmentmanage.domain.Dept;
import com.openhis.appointmentmanage.service.IDeptService;
import com.openhis.web.appointmentmanage.appservice.IDeptAppService;
import org.springframework.stereotype.Service;

View File

@@ -0,0 +1,42 @@
package com.openhis.web.appointmentmanage.appservice.impl;
import cn.hutool.core.util.ObjectUtil;
import com.core.common.core.domain.R;
import com.openhis.appointmentmanage.domain.DoctorSchedule;
import com.openhis.appointmentmanage.service.IDoctorScheduleService;
import com.openhis.web.appointmentmanage.appservice.IDoctorScheduleAppService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
public class DoctorScheduleAppServiceImpl implements IDoctorScheduleAppService {
@Resource
private IDoctorScheduleService doctorScheduleService;
@Override
public R<?> getDoctorScheduleList() {
List<DoctorSchedule> list = doctorScheduleService.list();
return R.ok(list);
}
@Override
public R<?> addDoctorSchedule(DoctorSchedule doctorSchedule) {
if (ObjectUtil.isEmpty(doctorSchedule)) {
return R.fail("医生排班不能为空");
}
boolean save = doctorScheduleService.save(doctorSchedule);
return R.ok(save);
}
@Override
public R<?> removeDoctorSchedule(Integer doctorScheduleId) {
if (doctorScheduleId == null && ObjectUtil.isEmpty(doctorScheduleId)) {
return R.fail("排班id不能为空");
}
boolean remove = doctorScheduleService.removeById(doctorScheduleId);
return R.ok(remove);
}
}

View File

@@ -0,0 +1,41 @@
package com.openhis.web.appointmentmanage.appservice.impl;
import cn.hutool.core.util.ObjectUtil;
import com.core.common.core.domain.R;
import com.openhis.appointmentmanage.domain.SchedulePool;
import com.openhis.appointmentmanage.service.ISchedulePoolService;
import com.openhis.web.appointmentmanage.appservice.ISchedulePoolAppService;
import com.openhis.web.appointmentmanage.dto.SchedulePoolDto;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class SchedulePoolAppServiceImpl implements ISchedulePoolAppService {
@Resource
private ISchedulePoolService schedulePoolService;
@Override
public R<?> addSchedulePool(SchedulePoolDto schedulePoolDto) {
//12/15 实体封装过程数据关系复杂 尚未完全理清 下次继续改
if(ObjectUtil.isNull(schedulePoolDto)){
return R.fail("号源不能为空");
}
SchedulePool schedulePool = new SchedulePool();
schedulePool.setHospitalId(schedulePoolDto.getHospitalId());
schedulePool.setDeptId(schedulePoolDto.getDeptId());
schedulePool.setDoctorId(schedulePoolDto.getDoctorId());
schedulePool.setDoctorName(schedulePoolDto.getDoctorName());
schedulePool.setScheduleDate(schedulePoolDto.getScheduleDate());
schedulePool.setShift(schedulePoolDto.getShift());
schedulePool.setStartTime(schedulePoolDto.getStartTime());
schedulePool.setEndTime(schedulePoolDto.getEndTime());
schedulePool.setRegType(schedulePoolDto.getRegType());
schedulePool.setFee(schedulePoolDto.getFee());
boolean save = schedulePoolService.save(schedulePool);
return R.ok(save);
}
}

View File

@@ -0,0 +1,8 @@
package com.openhis.web.appointmentmanage.appservice.impl;
import com.openhis.web.appointmentmanage.appservice.IScheduleSlotAppService;
import org.springframework.stereotype.Service;
@Service
public class ScheduleSlotAppServiceImpl implements IScheduleSlotAppService {
}

View File

@@ -0,0 +1,73 @@
package com.openhis.web.appointmentmanage.controller;
import com.core.common.core.domain.R;
import com.openhis.appointmentmanage.domain.ClinicRoom;
import com.openhis.web.appointmentmanage.appservice.IClinicRoomAppService;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@RestController
@RequestMapping("/appoinment/clinic-room")
public class ClinicRoomController {
@Resource
private IClinicRoomAppService clinicRoomAppService;
/**
* 分页查询诊室列表
* @param pageNum 页码
* @param pageSize 每页条数
* @param orgName 卫生机构名称
* @param roomName 诊室名称
* @return 分页查询结果
*/
@GetMapping("/page")
public R<?> selectClinicRoomPage(
@RequestParam(required = true) Integer pageNum,
@RequestParam(required = true) Integer pageSize,
@RequestParam(required = false) String orgName,
@RequestParam(required = false) String roomName) {
return clinicRoomAppService.selectClinicRoomPage(pageNum, pageSize, orgName, roomName);
}
/**
* 查询诊室详情
* @param id 诊室ID
* @return 诊室详情
*/
@GetMapping("/{id}")
public R<?> selectClinicRoomById(@PathVariable Long id) {
return clinicRoomAppService.selectClinicRoomById(id);
}
/**
* 新增诊室
* @param clinicRoom 诊室信息
* @return 新增结果
*/
@PostMapping
public R<?> insertClinicRoom(@RequestBody ClinicRoom clinicRoom) {
return clinicRoomAppService.insertClinicRoom(clinicRoom);
}
/**
* 更新诊室
* @param clinicRoom 诊室信息
* @return 更新结果
*/
@PutMapping
public R<?> updateClinicRoom(@RequestBody ClinicRoom clinicRoom) {
return clinicRoomAppService.updateClinicRoom(clinicRoom);
}
/**
* 删除诊室
* @param id 诊室ID
* @return 删除结果
*/
@DeleteMapping("/{id}")
public R<?> deleteClinicRoomById(@PathVariable Long id) {
return clinicRoomAppService.deleteClinicRoomById(id);
}
}

View File

@@ -0,0 +1,43 @@
package com.openhis.web.appointmentmanage.controller;
import com.core.common.core.domain.R;
import com.openhis.appointmentmanage.domain.DoctorSchedule;
import com.openhis.web.appointmentmanage.appservice.IDoctorScheduleAppService;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@RestController
@RequestMapping("/doctor-schedule")
public class DoctorScheduleController {
@Resource
private IDoctorScheduleAppService doctorScheduleAppService;
/*
* 获取医生排班List
*
* */
@GetMapping("/list")
public R<?> getDoctorScheduleList() {
return R.ok(doctorScheduleAppService.getDoctorScheduleList());
}
/*
* 新增医生排班
*
* */
@PostMapping("/add")
public R<?> addDoctorSchedule(@RequestBody DoctorSchedule doctorSchedule) {
return R.ok(doctorScheduleAppService.addDoctorSchedule(doctorSchedule));
}
/*
* 删除医生排班
*
* */
@DeleteMapping("/delete/{doctorScheduleId}")
public R<?> removeDoctorSchedule(@PathVariable Integer doctorScheduleId){
return R.ok(doctorScheduleAppService.removeDoctorSchedule(doctorScheduleId));
}
}

View File

@@ -0,0 +1,28 @@
package com.openhis.web.appointmentmanage.controller;
import com.core.common.core.domain.R;
import com.openhis.appointmentmanage.domain.SchedulePool;
import com.openhis.web.appointmentmanage.appservice.ISchedulePoolAppService;
import com.openhis.web.appointmentmanage.dto.SchedulePoolDto;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@RequestMapping("/schedule-pool")
public class SchedulePoolController {
@Resource
private ISchedulePoolAppService schedulePoolAppService;
/*
* 新增号源
*
* */
public R<?> addSchedulePool(@RequestBody SchedulePoolDto schedulePoolDto) {
return R.ok(schedulePoolAppService.addSchedulePool(schedulePoolDto));
}
}

View File

@@ -0,0 +1,9 @@
package com.openhis.web.appointmentmanage.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/schedule-slot")
public class ScheduleSlotController {
}

View File

@@ -0,0 +1,104 @@
package com.openhis.web.appointmentmanage.dto;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
/**
* 号源池Dto
*
* @date 2025-12-12
*/
@Data
public class SchedulePoolDto {
/** id */
private Integer id;
/** 业务编号 */
private String poolCode;
/** 医院ID */
private Integer hospitalId;
/** 科室ID */
private Integer deptId;
/** 医生ID */
private Integer doctorId;
/** 医生姓名 */
private String doctorName;
/** 诊室 */
private String clinicRoom;
/** 出诊日期 */
private LocalDate scheduleDate;
/** 班别 */
private String shift;
/** 开始时间 */
private LocalTime startTime;
/** 结束时间 */
private LocalTime endTime;
/** 总号量 */
private Integer totalQuota;
/** 已约 */
private Integer bookedNum;
/** 铁号数 */
private Integer lockedNum;
/** 剩余号数 */
private Integer availableNum;
/** 号别 */
private String regType;
/** 原价 (元) */
private Double fee;
/** 医保限价 (元) */
private Double insurancePrice;
/** 支持渠道 */
private String supportChannel;
/** 号源状态 */
private Integer status;
/** 停诊原因 */
private String stopReason;
/** 放号时间 */
private LocalDateTime releaseTime;
/** 截止预约时间 */
private LocalDateTime deadlineTime;
/** 乐观锁版本 */
private Integer version;
/** 操作人ID */
private Integer opUserId;
/** 备注 */
private String remark;
/** 排班ID */
private Integer scheduleId;
/** 创建时间 */
private LocalDateTime createTime;
/** 更新时间 */
private LocalDateTime updateTime;
}

View File

@@ -0,0 +1,7 @@
package com.openhis.web.appointmentmanage.mapper;
import org.springframework.stereotype.Repository;
@Repository
public interface DoctorScheduleAppMapper {
}

View File

@@ -0,0 +1,7 @@
package com.openhis.web.appointmentmanage.mapper;
import org.springframework.stereotype.Repository;
@Repository
public interface SchedulePoolAppMapper {
}

View File

@@ -0,0 +1,7 @@
package com.openhis.web.appointmentmanage.mapper;
import org.springframework.stereotype.Repository;
@Repository
public interface ScheduleSlotAppMapper {
}

View File

@@ -179,7 +179,7 @@ public class DiagTreatMAppServiceImpl implements IDiagTreatMAppService {
// 分页查询
IPage<DiagnosisTreatmentDto> diseaseTreatmentPage =
activityDefinitionManageMapper.getDiseaseTreatmentPage(new Page<>(pageNo, pageSize), queryWrapper);
activityDefinitionManageMapper.getDiseaseTreatmentPage(new Page<DiagnosisTreatmentDto>(pageNo, pageSize), queryWrapper);
diseaseTreatmentPage.getRecords().forEach(e -> {
// 医保标记枚举类回显赋值

View File

@@ -7,6 +7,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

View File

@@ -0,0 +1,55 @@
#\u9519\u8bef\u6d88\u606f
not.null=* \u5fc5\u987b\u586b\u5199
user.jcaptcha.error=\u9a8c\u8bc1\u7801\u9519\u8bef
user.jcaptcha.expire=\u9a8c\u8bc1\u7801\u5df2\u5931\u6548
user.not.exists=\u7528\u6237\u4e0d\u5b58\u5728/\u5bc6\u7801\u9519\u8bef
user.password.not.match=\u7528\u6237\u4e0d\u5b58\u5728/\u5bc6\u7801\u9519\u8bef
user.password.retry.limit.count=\u5bc6\u7801\u8f93\u5165\u9519\u8bef{0}\u6b21
user.password.retry.limit.exceed=\u5bc6\u7801\u8f93\u5165\u9519\u8bef{0}\u6b21\uff0c\u5e10\u6237\u9501\u5b9a{1}\u5206\u949f
user.password.delete=\u5bf9\u4e0d\u8d77\uff0c\u60a8\u7684\u8d26\u53f7\u5df2\u88ab\u5220\u9664
user.blocked=\u7528\u6237\u5df2\u5c01\u7981\uff0c\u8bf7\u8054\u7cfb\u7ba1\u7406\u5458
role.blocked=\u89d2\u8272\u5df2\u5c01\u7981\uff0c\u8bf7\u8054\u7cfb\u7ba1\u7406\u5458
login.blocked=\u5f88\u9057\u61be\uff0c\u8bbf\u95eeIP\u5df2\u88ab\u5217\u5165\u7cfb\u7edf\u9ed1\u540d\u5355
user.logout.success=\u9000\u51fa\u6210\u529f
length.not.valid=\u957f\u5ea6\u5fc5\u987b\u5728{min}\u5230{max}\u4e2a\u5b57\u7b26\u4e4b\u95f4
user.username.not.valid=* 2\u523020\u4e2a\u6c49\u5b57\u3001\u5b57\u6bcd\u3001\u6570\u5b57\u6216\u4e0b\u5212\u7ebf\u7ec4\u6210\uff0c\u4e14\u5fc5\u987b\u4ee5\u975e\u6570\u5b57\u5f00\u5934
user.password.not.valid=* 5-50\u4e2a\u5b57\u7b26
user.email.not.valid=\u90ae\u7bb1\u683c\u5f0f\u9519\u8bef
user.mobile.phone.number.not.valid=\u624b\u673a\u53f7\u683c\u5f0f\u9519\u8bef
user.login.success=\u767b\u5f55\u6210\u529f\u6210\u679c
user.register.success=\u6ce8\u518c\u6210\u529f
user.notfound=\u8bf7\u91cd\u65b0\u767b\u5f55
user.forcelogout=\u7ba1\u7406\u5458\u5f3a\u5236\u9000\u51fa\uff0c\u8bf7\u91cd\u65b0\u767b\u5f55
user.unknown.error=\u672a\u77e5\u9519\u8bef\uff0c\u8bf7\u91cd\u65b0\u767b\u5f55
##\u6587\u4ef6\u4e0a\u4f20\u6d88\u606f
upload.exceed.maxSize=\u4e0a\u4f20\u7684\u6587\u4ef6\u5927\u5c0f\u8d85\u51fa\u9650\u5236\u7684\u6587\u4ef6\u5927\u5c0f\uff01<br/>\u5141\u8bb8\u7684\u6587\u4ef6\u6700\u5927\u5927\u5c0f\u662f\uff1a{0}MB\uff01
upload.filename.exceed.length=\u4e0a\u4f20\u7684\u6587\u4ef6\u540d\u6700\u957f{0}\u4e2a\u5b57\u7b26
##\u6743\u9650
no.permission=\u60a8\u6ca1\u6709\u6570\u636e\u7684\u6743\u9650\uff0c\u8bf7\u8054\u7cfb\u7ba1\u7406\u5458\u6dfb\u52a0\u6743\u9650 [{0}]
no.create.permission=\u60a8\u6ca1\u6709\u521b\u5efa\u6570\u636e\u7684\u6743\u9650\uff0c\u8bf7\u8054\u7cfb\u7ba1\u7406\u5458\u6dfb\u52a0\u6743\u9650 [{0}]
no.update.permission=\u60a8\u6ca1\u6709\u4fee\u6539\u6570\u636e\u7684\u6743\u9650\uff0c\u8bf7\u8054\u7cfb\u7ba1\u7406\u5458\u6dfb\u52a0\u6743\u9650 [{0}]
no.delete.permission=\u60a8\u6ca1\u6709\u5220\u9664\u6570\u636e\u7684\u6743\u9650\uff0c\u8bf7\u8054\u7cfb\u7ba1\u7406\u5458\u6dfb\u52a0\u6743\u9650 [{0}]
no.export.permission=\u60a8\u6ca1\u6709\u5bfc\u51fa\u6570\u636e\u7684\u6743\u9650\uff0c\u8bf7\u8054\u7cfb\u7ba1\u7406\u5458\u6dfb\u52a0\u6743\u9650 [{0}]
no.view.permission=\u60a8\u6ca1\u6709\u67e5\u770b\u6570\u636e\u7684\u6743\u9650\uff0c\u8bf7\u8054\u7cfb\u7ba1\u7406\u5458\u6dfb\u52a0\u6743\u9650 [{0}]
apl.common.M00001={0}\u6dfb\u52a0\u6210\u529f
apl.common.M00002={0}\u4fdd\u5b58\u6210\u529f
apl.common.M00003={0}\u5df2\u7ecf\u5b58\u5728
apl.common.M00004={0}\u64cd\u4f5c\u6210\u529f
apl.common.M00005={0}\u5220\u9664\u6210\u529f
apl.common.M00006=\u64cd\u4f5c\u5931\u8d25,\u8be5\u6570\u636e\u5df2\u88ab\u4ed6\u4eba\u5220\u9664,\u8bf7\u5237\u65b0\u540e\u91cd\u8bd5
apl.common.M00007=\u64cd\u4f5c\u5931\u8d25,\u8be5\u6570\u636e\u5df2\u88ab\u4ed6\u4eba\u66f4\u6539,\u8bf7\u5237\u65b0\u540e\u91cd\u8bd5
apl.common.M00008=\u8bf7\u52ff\u91cd\u590d\u63d0\u4ea4
apl.common.M00009=\u67e5\u8be2\u6210\u529f
apl.common.M00010=\u64cd\u4f5c\u5931\u8d25,\u8bf7\u8054\u7cfb\u7ba1\u7406\u5458
apl.chargeRefund.M00001=\u8be5\u6536\u8d39\u5355\u76f8\u5173{0}\u5df2\u7ecf\u53d1\u51fa\uff0c\u8bf7\u5148\u9000\u836f\u540e\u518d\u8fdb\u884c\u9000\u8d39
apl.payment.M00001=\u5404\u7f34\u8d39\u6e20\u9053\u5b9e\u6536\u91d1\u989d\u5408\u8ba1\u4e0d\u7b49\u4e8e\u5b9e\u6536\u91d1\u989d
apl.payment.M00002=\u5b9e\u6536\u91d1\u989d\u5408\u8ba1\u4e0d\u7b49\u4e8e\u5e94\u6536\u91d1\u989d
apl.payment.M00003=\u8bf7\u9009\u62e9\u652f\u4ed8\u65b9\u5f0f
apl.payment.M00004=\u67e5\u8be2\u6210\u529f
apl.payment.M00005=\u64cd\u4f5c\u5931\u8d25,\u8bf7\u8054\u7cfb\u7ba1\u7406\u5458
apl.payment.M00006=\u6210\u529f\u6536\u8d39
apl.payment.M00007=\u672a\u67e5\u8be2\u5230\u6536\u8d39\u9879\u76ee
apl.payment.M00008=\u672a\u67e5\u8be2\u5230{0}\u8d26\u6237\u4fe1\u606f
apl.payment.M00009=\u672a\u67e5\u8be2\u5230\u6536\u8d39\u9879\u76ee\uff0c\u4e0d\u9700\u8981\u8f6c\u6362\u8d26\u6237
apl.adjustPrice.M00001=\u6267\u884c\u5931\u8d25\uff0c\u672a\u52a0\u8f7d\u5230\u4efb\u4f55\u6570\u636e\uff01
apl.adjustPrice.M00002=\u6267\u884c\u5931\u8d25\uff0c\u6539\u4ef7\u5355\u4e2d\u6709\u6b63\u5728\u5ba1\u6838\u4e2d\u7684\u8d27\u54c1\uff0c\u8bf7\u68c0\u67e5\u540e\u91cd\u65b0\u63d0\u4ea4\uff01

View File

@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.openhis.appointmentmanage.mapper.ClinicRoomMapper">
<!-- 通用查询映射结果 -->
<resultMap id="ClinicRoomResult" type="com.openhis.appointmentmanage.domain.ClinicRoom">
<id property="id" column="id" />
<result property="orgName" column="org_name" />
<result property="roomName" column="room_name" />
<result property="department" column="department" />
<result property="building" column="building" />
<result property="floor" column="floor" />
<result property="roomNo" column="room_no" />
<result property="isDisabled" column="is_disabled" />
<result property="remarks" column="remarks" />
<result property="voided" column="void" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, org_name, room_name, department, building, floor, room_no, is_disabled, remarks, void, create_by, create_time, update_by, update_time
</sql>
<!-- 分页查询 -->
<select id="selectClinicRoomPage" parameterType="com.openhis.appointmentmanage.domain.ClinicRoom" resultMap="ClinicRoomResult">
select
<include refid="Base_Column_List" />
from clinic_room
where 1 = 1
<if test="orgName != null and orgName != ''">
and org_name like concat('%', #{orgName}, '%')
</if>
<if test="roomName != null and roomName != ''">
and room_name like concat('%', #{roomName}, '%')
</if>
order by create_time desc
</select>
<!-- 查询详情 -->
<select id="selectClinicRoomById" parameterType="Long" resultMap="ClinicRoomResult">
select
<include refid="Base_Column_List" />
from clinic_room
where id = #{id}
</select>
<!-- 新增 -->
<insert id="insertClinicRoom" parameterType="com.openhis.appointmentmanage.domain.ClinicRoom" useGeneratedKeys="true" keyProperty="id">
insert into clinic_room
(org_name, room_name, department, building, floor, room_no, is_disabled, remarks, void, create_by, create_time, update_by, update_time)
values
(#{orgName}, #{roomName}, #{department}, #{building}, #{floor}, #{roomNo}, #{isDisabled}, #{remarks}, #{voided}, #{createBy}, #{createTime}, #{updateBy}, #{updateTime})
</insert>
<!-- 更新 -->
<update id="updateClinicRoom" parameterType="com.openhis.appointmentmanage.domain.ClinicRoom">
update clinic_room
set
org_name = #{orgName},
room_name = #{roomName},
department = #{department},
building = #{building},
floor = #{floor},
room_no = #{roomNo},
is_disabled = #{isDisabled},
remarks = #{remarks},
void = #{voided},
update_by = #{updateBy},
update_time = #{updateTime}
where id = #{id}
</update>
<!-- 删除 -->
<delete id="deleteClinicRoomById" parameterType="Long">
delete from clinic_room where id = #{id}
</delete>
</mapper>

View File

@@ -93,7 +93,14 @@
T13.charge_item_ids,
T13.id AS payment_id,
ai.picture_url AS picture_url,
T8.birth_date AS birth_date
T8.birth_date AS birth_date,
T14.create_time AS return_date,
T14.return_reason AS return_reason,
T15.name AS operator_name,
T15.id AS operator_id,
T14.display_amount AS refund_amount,
T6.contract_no AS contract_no,
T16.refund_method AS refund_method
FROM adm_encounter AS T1
LEFT JOIN adm_organization AS T2 ON T1.organization_id = T2.ID AND T2.delete_flag = '0'
LEFT JOIN adm_healthcare_service AS T3 ON T1.service_type_id = T3.ID AND T3.delete_flag = '0'

View File

@@ -4,35 +4,6 @@
<select id="getDiseaseTreatmentPage" parameterType="java.util.Map"
resultType="com.openhis.web.datadictionary.dto.DiagnosisTreatmentDto">
SELECT
T3.id,
T3.category_code,
T3.bus_no,
T3.name,
T3.py_str,
T3.wb_str,
T3.type_enum,
T3.permitted_unit_code,
T3.org_id,
T3.location_id,
T3.yb_flag,
T3.yb_no,
T3.yb_match_flag,
T3.status_enum,
T3.body_site_code,
T3.specimen_code,
T3.description_text,
T3.rule_id,
T3.tenant_id,
T3.item_type_code,
T3.yb_type,
T3.retail_price,
T3.maximum_retail_price,
T3.chrgitm_lv,--医保等级
T3.children_json,--子项json
T3.pricing_flag--划价标记
FROM
(
SELECT
T1.id,
T1.category_code,
@@ -57,24 +28,28 @@
T2.type_code as item_type_code,
T2.yb_type,
T2.price as retail_price,--零售价
( SELECT T4.amount
FROM adm_charge_item_definition T5
LEFT JOIN adm_charge_item_def_detail T4 ON T4.definition_id = T5.id
WHERE T4.condition_code = '4'--4:限制
AND T5.instance_id = T1.id
AND T5.instance_table = 'wor_activity_definition'
) as maximum_retail_price,--最高零售价
T4.amount as maximum_retail_price,--最高零售价
T1.children_json,--子项json
T1.pricing_flag--划价标记
FROM wor_activity_definition T1
LEFT JOIN adm_charge_item_definition T2 ON T1.id = T2.instance_id
LEFT JOIN adm_charge_item_definition T5 ON T5.instance_id = T1.id AND T5.instance_table = 'wor_activity_definition'
LEFT JOIN adm_charge_item_def_detail T4 ON T4.definition_id = T5.id AND T4.condition_code = '4'--4:限制
<where>
T1.delete_flag = '0'
AND T2.instance_table = 'wor_activity_definition'
<if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
<choose>
<when test="ew.customSqlSegment.contains('tenant_id')">
${ew.customSqlSegment.replaceFirst('tenant_id', 'T1.tenant_id').replaceFirst('WHERE', 'AND')}
</when>
<otherwise>
${ew.customSqlSegment.replaceFirst('WHERE', 'AND')}
</otherwise>
</choose>
</if>
</where>
ORDER BY T1.bus_no DESC
) AS T3
${ew.customSqlSegment}
</select>

View File

@@ -0,0 +1,96 @@
import Layout from '@/layout'
import router from './router'
import { ElMessage } from 'element-plus'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { getToken } from '@/utils/auth'
import { isHttp } from '@/utils/validate'
import { isRelogin } from '@/utils/request'
import useUserStore from '@/store/modules/user'
import useSettingsStore from '@/store/modules/settings'
import usePermissionStore from '@/store/modules/permission'
NProgress.configure({ showSpinner: false });
const whiteList = ['/login', '/register'];
router.beforeEach((to, from, next) => {
NProgress.start()
if (getToken()) {
to.meta.title && useSettingsStore().setTitle(to.meta.title)
/* has token*/
if (to.path === '/login') {
next({ path: '/' })
NProgress.done()
} else if (whiteList.indexOf(to.path) !== -1) {
next()
} else {
if (useUserStore().roles.length === 0) {
isRelogin.show = true
// 判断当前用户是否已拉取完user_info信息
useUserStore().getInfo().then(() => {
isRelogin.show = false
usePermissionStore().generateRoutes().then(accessRoutes => {
// 根据roles权限生成可访问的路由表
accessRoutes.forEach(route => {
if (!isHttp(route.path)) {
// 检查是否已经存在同名路由
if (!router.hasRoute(route.name)) {
router.addRoute(route) // 动态添加可访问路由表
}
}
})
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
})
}).catch(err => {
useUserStore().logOut().then(() => {
ElMessage.error(err)
next({ path: '/' })
})
})
} else {
next()
}
}
} else {
// 没有token
if (whiteList.indexOf(to.path) !== -1) {
// 在免登录白名单,直接进入
next()
} else {
next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
NProgress.done()
}
}
})
router.afterEach(() => {
NProgress.done()
})
const appointmentRouter = {
path: '/appointment',
component: Layout,
redirect: '/appointment/manage',
name: 'Appointment',
meta: {
title: '预约管理',
icon: 'calendar'
},
children: [
{
path: 'manage',
component: () => import('@/views/appointment/manage'),
name: 'AppointmentManage', // 修改名称,避免与父级重复
meta: { title: '预约管理', icon: 'list' }
},
{
path: 'setting',
component: () => import('@/views/appointment/setting'),
name: 'AppointmentSetting',
meta: { title: '预约设置', icon: 'setting' }
}
]
}
export default appointmentRouter

View File

@@ -1,11 +0,0 @@
package com.openhis.administration.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.openhis.administration.domain.Dept;
import com.openhis.administration.mapper.DeptMapper;
import com.openhis.administration.service.IDeptService;
import org.springframework.stereotype.Service;
@Service
public class DeptImpl extends ServiceImpl<DeptMapper, Dept> implements IDeptService {
}

View File

@@ -0,0 +1,58 @@
package com.openhis.appointmentmanage.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.HisBaseEntity;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 诊室维护Entity实体
*
* @author system
* @date 2025-12-09
*/
@Data
@TableName("clinic_room")
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
public class ClinicRoom extends HisBaseEntity {
/** ID */
@TableId(type = IdType.ASSIGN_ID)
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
/** 卫生机构名称 */
private String orgName;
/** 诊室名称 */
private String roomName;
/** 科室名称 */
private String department;
/** 诊室楼号 */
private String building;
/** 诊室楼层 */
private String floor;
/** 诊室房间号 */
private String roomNo;
/** 停用状态 */
private Boolean isDisabled;
/** 备注 */
private String remarks;
/** 作废标志 */
private Boolean voided;
}

View File

@@ -1,14 +1,13 @@
package com.openhis.administration.domain;
package com.openhis.appointmentmanage.domain;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
import java.util.List;
/**
* 科室Entity实体
* 科室Entity
*
* @date 2025-12-08
*/
@@ -40,6 +39,4 @@ public class Dept {
/** 更新时间 */
private LocalDateTime updateTime;
/** 关联的排班列表(一对多关系) */
private List<DoctorSchedule> schedules;
}

View File

@@ -0,0 +1,74 @@
package com.openhis.appointmentmanage.domain;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
import java.time.LocalTime;
/**
* 医生排班Entity
*
* @date 2025-12-12
*/
@Data
@TableName(value = "adm_doctor_schedule")
@Accessors(chain = true)
public class DoctorSchedule {
/** id */
private Integer id;
/** 星期 */
private String weekday;
/** 时段 */
private String timePeriod;
/** 医生 */
private String doctor;
/** 诊室 */
private String clinic;
/** 开始时间 */
private LocalTime startTime;
/** 结束时间 */
private LocalTime endTime;
/** 限号数量 */
private Integer limitNumber;
/** 号源记录 */
private String callSignRecord;
/** 挂号项目 */
private String registerItem;
/** 挂号费 */
private Integer registerFee;
/** 诊查项目 */
private String diagnosisItem;
/** 诊疗费 */
private Integer diagnosisFee;
/** 线上挂号 */
private Boolean isOnline;
/** 是否停诊 */
private Boolean isStopped;
/** 停诊原因 */
private String stopReason;
/** 关联科室id */
private Integer deptId;
/** 创建时间 */
private LocalDateTime createTime;
/** 更新时间 */
private LocalDateTime updateTime;
}

View File

@@ -0,0 +1,105 @@
package com.openhis.appointmentmanage.domain;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
/**
* 号源池Entity
*
* @date 2025-12-12
*/
@Data
@TableName(value = "adm_schedule_pool")
@Accessors(chain = true)
public class SchedulePool {
/** id */
private Integer id;
/** 业务编号 */
private String poolCode;
/** 医院ID */
private Integer hospitalId;
/** 科室ID */
private Integer deptId;
/** 医生ID */
private Integer doctorId;
/** 医生姓名 */
private String doctorName;
/** 诊室 */
private String clinicRoom;
/** 出诊日期 */
private LocalDate scheduleDate;
/** 班别 */
private String shift;
/** 开始时间 */
private LocalTime startTime;
/** 结束时间 */
private LocalTime endTime;
/** 总号量 */
private Integer totalQuota;
/** 已约 */
private Integer bookedNum;
/** 铁号数 */
private Integer lockedNum;
/** 剩余号数 */
private Integer availableNum;
/** 号别 */
private String regType;
/** 原价 (元) */
private Double fee;
/** 医保限价 (元) */
private Double insurancePrice;
/** 支持渠道 */
private String supportChannel;
/** 号源状态 */
private Integer status;
/** 停诊原因 */
private String stopReason;
/** 放号时间 */
private LocalDateTime releaseTime;
/** 截止预约时间 */
private LocalDateTime deadlineTime;
/** 乐观锁版本 */
private Integer version;
/** 操作人ID */
private Integer opUserId;
/** 备注 */
private String remark;
/** 排班ID */
private Integer scheduleId;
/** 创建时间 */
private LocalDateTime createTime;
/** 更新时间 */
private LocalDateTime updateTime;
}

View File

@@ -0,0 +1,41 @@
package com.openhis.appointmentmanage.domain;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
import java.time.LocalTime;
/**
* 号源池明细Entity
*
* @date 2025-12-12
*/
@Data
@TableName(value = "adm_schedule_slot")
@Accessors(chain = true)
public class ScheduleSlot {
/** 明细主键 */
private Integer id;
/** 号源池ID */
private Integer poolId;
/** 序号 */
private Integer seqNo;
/** 序号状态: 0-可用,1-已预约,2-已取消,3-已过期等 */
private Integer status;
/** 预约订单ID */
private Integer orderId;
/** 预计叫号时间 */
private LocalTime expectTime;
/** 创建时间 */
private LocalDateTime createTime;
/** 更新时间 */
private LocalDateTime updateTime;
}

View File

@@ -0,0 +1,13 @@
package com.openhis.appointmentmanage.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.openhis.appointmentmanage.domain.ClinicRoom;
/**
* 诊室维护Mapper接口
*
* @author system
* @date 2025-12-09
*/
public interface ClinicRoomMapper extends BaseMapper<ClinicRoom> {
}

View File

@@ -1,7 +1,7 @@
package com.openhis.administration.mapper;
package com.openhis.appointmentmanage.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.openhis.administration.domain.Dept;
import com.openhis.appointmentmanage.domain.Dept;
import org.springframework.stereotype.Repository;
@Repository

View File

@@ -0,0 +1,9 @@
package com.openhis.appointmentmanage.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.openhis.appointmentmanage.domain.DoctorSchedule;
import org.springframework.stereotype.Repository;
@Repository
public interface DoctorScheduleMapper extends BaseMapper<DoctorSchedule> {
}

View File

@@ -0,0 +1,9 @@
package com.openhis.appointmentmanage.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.openhis.appointmentmanage.domain.SchedulePool;
import org.springframework.stereotype.Repository;
@Repository
public interface SchedulePoolMapper extends BaseMapper<SchedulePool> {
}

View File

@@ -0,0 +1,9 @@
package com.openhis.appointmentmanage.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.openhis.appointmentmanage.domain.ScheduleSlot;
import org.springframework.stereotype.Repository;
@Repository
public interface ScheduleSlotMapper extends BaseMapper<ScheduleSlot> {
}

View File

@@ -0,0 +1,54 @@
package com.openhis.appointmentmanage.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.openhis.appointmentmanage.domain.ClinicRoom;
/**
* 诊室维护Service接口
*
* @author system
* @date 2025-12-09
*/
public interface IClinicRoomService extends IService<ClinicRoom> {
/**
* 分页查询诊室列表
*
* @param page 分页参数
* @param clinicRoom 查询条件
* @return 分页结果
*/
Page<ClinicRoom> selectClinicRoomPage(Page<ClinicRoom> page, ClinicRoom clinicRoom);
/**
* 查询诊室详情
*
* @param id 诊室ID
* @return 诊室信息
*/
ClinicRoom selectClinicRoomById(Long id);
/**
* 新增诊室
*
* @param clinicRoom 诊室信息
* @return 结果
*/
int insertClinicRoom(ClinicRoom clinicRoom);
/**
* 更新诊室
*
* @param clinicRoom 诊室信息
* @return 结果
*/
int updateClinicRoom(ClinicRoom clinicRoom);
/**
* 删除诊室
*
* @param id 诊室ID
* @return 结果
*/
int deleteClinicRoomById(Long id);
}

View File

@@ -1,7 +1,7 @@
package com.openhis.administration.service;
package com.openhis.appointmentmanage.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.openhis.administration.domain.Dept;
import com.openhis.appointmentmanage.domain.Dept;
public interface IDeptService extends IService<Dept> {
}

View File

@@ -0,0 +1,7 @@
package com.openhis.appointmentmanage.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.openhis.appointmentmanage.domain.DoctorSchedule;
public interface IDoctorScheduleService extends IService<DoctorSchedule> {
}

View File

@@ -0,0 +1,7 @@
package com.openhis.appointmentmanage.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.openhis.appointmentmanage.domain.SchedulePool;
public interface ISchedulePoolService extends IService<SchedulePool> {
}

View File

@@ -0,0 +1,7 @@
package com.openhis.appointmentmanage.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.openhis.appointmentmanage.domain.ScheduleSlot;
public interface IScheduleSlotService extends IService<ScheduleSlot> {
}

View File

@@ -0,0 +1,47 @@
package com.openhis.appointmentmanage.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.openhis.appointmentmanage.domain.ClinicRoom;
import com.openhis.appointmentmanage.mapper.ClinicRoomMapper;
import com.openhis.appointmentmanage.service.IClinicRoomService;
import org.springframework.stereotype.Service;
/**
* 诊室维护Service实现类
*
* @author system
* @date 2025-12-09
*/
@Service
public class ClinicRoomServiceImpl extends ServiceImpl<ClinicRoomMapper, ClinicRoom> implements IClinicRoomService {
@Override
public Page<ClinicRoom> selectClinicRoomPage(Page<ClinicRoom> page, ClinicRoom clinicRoom) {
return baseMapper.selectPage(page, new LambdaQueryWrapper<ClinicRoom>()
.like(clinicRoom.getOrgName() != null, ClinicRoom::getOrgName, clinicRoom.getOrgName())
.like(clinicRoom.getRoomName() != null, ClinicRoom::getRoomName, clinicRoom.getRoomName())
.orderByDesc(ClinicRoom::getCreateTime));
}
@Override
public ClinicRoom selectClinicRoomById(Long id) {
return baseMapper.selectById(id);
}
@Override
public int insertClinicRoom(ClinicRoom clinicRoom) {
return baseMapper.insert(clinicRoom);
}
@Override
public int updateClinicRoom(ClinicRoom clinicRoom) {
return baseMapper.updateById(clinicRoom);
}
@Override
public int deleteClinicRoomById(Long id) {
return baseMapper.deleteById(id);
}
}

View File

@@ -0,0 +1,11 @@
package com.openhis.appointmentmanage.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.openhis.appointmentmanage.domain.Dept;
import com.openhis.appointmentmanage.mapper.DeptMapper;
import com.openhis.appointmentmanage.service.IDeptService;
import org.springframework.stereotype.Service;
@Service
public class DeptImpl extends ServiceImpl<DeptMapper, Dept> implements IDeptService {
}

View File

@@ -0,0 +1,11 @@
package com.openhis.appointmentmanage.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.openhis.appointmentmanage.domain.DoctorSchedule;
import com.openhis.appointmentmanage.mapper.DoctorScheduleMapper;
import com.openhis.appointmentmanage.service.IDoctorScheduleService;
import org.springframework.stereotype.Service;
@Service
public class DoctorScheduleServiceImpl extends ServiceImpl<DoctorScheduleMapper, DoctorSchedule> implements IDoctorScheduleService {
}

View File

@@ -0,0 +1,11 @@
package com.openhis.appointmentmanage.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.openhis.appointmentmanage.domain.SchedulePool;
import com.openhis.appointmentmanage.mapper.SchedulePoolMapper;
import com.openhis.appointmentmanage.service.ISchedulePoolService;
import org.springframework.stereotype.Service;
@Service
public class SchedulePoolServiceImpl extends ServiceImpl<SchedulePoolMapper, SchedulePool> implements ISchedulePoolService {
}

View File

@@ -0,0 +1,11 @@
package com.openhis.appointmentmanage.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.openhis.appointmentmanage.domain.ScheduleSlot;
import com.openhis.appointmentmanage.mapper.ScheduleSlotMapper;
import com.openhis.appointmentmanage.service.IScheduleSlotService;
import org.springframework.stereotype.Service;
@Service
public class ScheduleSlotServiceImpl extends ServiceImpl<ScheduleSlotMapper, ScheduleSlot> implements IScheduleSlotService {
}

View File

@@ -332,7 +332,7 @@
</dependencyManagement>
<modules>
<module>openhis-miniapp</module>
<!-- <module>openhis-miniapp</module> -->
<module>openhis-application</module>
<module>openhis-domain</module>
<module>openhis-common</module>

View File

@@ -10,7 +10,7 @@
/>
<!-- <link rel="icon" href="src/assets/images/ccu.png" /> -->
<link rel="icon" href="src/assets/images/ccu.png" />
<link rel="stylesheet" type="text/css" media="print" href="/public/print-lock.css">
<link rel="stylesheet" type="text/css" media="print" href="/print-lock.css">
<title>医院信息管理系统</title>
<!--[if lt IE 11
]><script>

File diff suppressed because it is too large Load Diff

View File

@@ -19,43 +19,43 @@
"url": "giturl"
},
"dependencies": {
"@element-plus/icons-vue": "2.3.1",
"@element-plus/icons-vue": "^2.3.2",
"@vueup/vue-quill": "1.2.0",
"@vueuse/core": "10.6.1",
"axios": "0.27.2",
"@vueuse/core": "^11.0.0",
"axios": "^1.7.0",
"chart.js": "^4.5.1",
"d3": "^7.9.0",
"decimal.js": "^10.5.0",
"echarts": "^5.4.3",
"element-china-area-data": "^6.1.0",
"element-plus": "2.9.11",
"file-saver": "2.0.5",
"fuse.js": "6.6.2",
"element-plus": "^2.12.0",
"file-saver": "^2.0.5",
"fuse.js": "^7.0.0",
"html2pdf.js": "^0.10.3",
"js-cookie": "3.0.5",
"jsencrypt": "3.3.2",
"js-cookie": "^3.0.5",
"jsencrypt": "^3.3.2",
"lodash": "^4.17.21",
"moment": "^2.30.1",
"nprogress": "0.2.0",
"pinia": "2.1.7",
"nprogress": "^0.2.0",
"pinia": "^2.2.0",
"pinyin": "^4.0.0-alpha.2",
"province-city-china": "^8.5.8",
"segmentit": "^2.0.3",
"v-region": "^3.3.0",
"vue": "^3.5.13",
"vue-area-linkage": "^5.1.0",
"vue-cropper": "1.1.1",
"vue-cropper": "^1.1.1",
"vue-plugin-hiprint": "^0.0.60",
"vue-router": "4.2.5"
"vue-router": "^4.3.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "4.5.0",
"@vue/compiler-sfc": "3.3.9",
"sass": "1.69.5",
"unplugin-auto-import": "0.17.1",
"unplugin-vue-setup-extend-plus": "1.0.0",
"@vitejs/plugin-vue": "^5.0.0",
"@vue/compiler-sfc": "^3.5.25",
"sass": "^1.77.8",
"unplugin-auto-import": "^0.19.0",
"unplugin-vue-setup-extend-plus": "^1.0.0",
"vite": "^5.0.4",
"vite-plugin-compression": "0.5.1",
"vite-plugin-svg-icons": "2.0.1"
"vite-plugin-compression": "^0.5.1",
"vite-plugin-svg-icons": "^2.0.1"
}
}

View File

@@ -0,0 +1,66 @@
import request from '@/utils/request'
// 查询诊室列表(分页)
export function getClinicRoomList(query) {
return request({
url: '/appoinment/clinic-room/page',
method: 'get',
params: query
})
}
// 查询诊室详情
export function getClinicRoomDetail(id) {
return request({
url: '/appoinment/clinic-room/' + id,
method: 'get'
})
}
// 新增诊室
export function addClinicRoom(data) {
return request({
url: '/appoinment/clinic-room',
method: 'post',
data: data
})
}
// 编辑诊室
export function updateClinicRoom(data) {
return request({
url: '/appoinment/clinic-room',
method: 'put',
data: data
})
}
// 删除诊室
export function deleteClinicRoom(id) {
return request({
url: '/appoinment/clinic-room/' + id,
method: 'delete'
})
}
// 获取科室列表(用于下拉选择)
export function getDepartmentList() {
return request({
url: '/app-common/department-list',
method: 'get'
})
}
// 获取租户列表(用于下拉选择)
export function getTenantList() {
return request({
url: '/system/tenant/page',
method: 'get',
params: {
pageNum: 1,
pageSize: 1000
}
})
}

View File

@@ -50,8 +50,10 @@ export function logout() {
// 获取验证码
export function getUserBindTenantList(username) {
// 确保username存在避免构建出错误的URL
const safeUsername = username || '';
return request({
url: '/system/tenant/user-bind/'+username,
url: '/system/tenant/user-bind/' + safeUsername,
headers: {
isToken: false
},

View File

@@ -18,10 +18,11 @@ export function getConfig(configId) {
}
// 根据参数键名查询参数值
export function getConfigKey(configKey) {
export function getConfigKey(configKey, options = {}) {
return request({
url: '/system/config/configKey/' + configKey,
method: 'get'
method: 'get',
...options
})
}

View File

@@ -1,28 +1,16 @@
<template>
<div class="editor-container">
<div>
<el-upload
:action="uploadUrl"
:before-upload="handleBeforeUpload"
:on-success="handleUploadSuccess"
:on-error="handleUploadError"
name="file"
:show-file-list="false"
:headers="headers"
class="editor-img-uploader"
v-if="type == 'url'"
>
<el-upload :action="uploadUrl" :before-upload="handleBeforeUpload" :on-success="handleUploadSuccess"
:on-error="handleUploadError" name="file" :show-file-list="false" :headers="headers" class="editor-img-uploader"
v-if="type == 'url'">
<i ref="uploadRef" class="editor-img-uploader"></i>
</el-upload>
</div>
<div class="editor">
<quill-editor
ref="quillEditorRef"
v-model:content="content"
contentType="html"
@textChange="(e) => $emit('update:modelValue', content)"
:options="options"
:style="styles"
/>
<quill-editor ref="quillEditorRef" :content="content" @update:content="content = $event" contentType="html"
@textChange="(e) => $emit('update:modelValue', content)" :options="options" :style="styles" />
</div>
</div>
</template>
@@ -30,10 +18,11 @@
import { QuillEditor } from "@vueup/vue-quill";
import "@vueup/vue-quill/dist/vue-quill.snow.css";
import { getToken } from "@/utils/auth";
const { proxy } = getCurrentInstance();
import { ref, computed, watch, onMounted } from 'vue';
import modal from '@/plugins/modal';
const quillEditorRef = ref();
const uploadRef = ref();
const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload"); // 上传的图片服务器地址
const headers = ref({
Authorization: "Bearer " + getToken()
@@ -115,32 +104,34 @@ watch(() => props.modelValue, (v) => {
// 如果设置了上传地址则自定义图片上传事件
onMounted(() => {
if (props.type == 'url') {
let quill = quillEditorRef.value.getQuill();
let quill = quillEditorRef.value?.getQuill();
if (quill) {
let toolbar = quill.getModule("toolbar");
toolbar.addHandler("image", (value) => {
if (value) {
proxy.$refs.uploadRef.click();
if (value && uploadRef.value) {
uploadRef.value.click();
} else {
quill.format("image", false);
}
});
}
}
});
// 上传前校检格式和大小
function handleBeforeUpload(file) {
const type = ["image/jpeg", "image/jpg", "image/png", "image/svg"];
const type = ["image/jpeg", "image/jpg", "image/png", "image/svg+xml"];
const isJPG = type.includes(file.type);
//检验文件格式
if (!isJPG) {
proxy.$modal.msgError(`图片格式错误!`);
modal.msgError(`图片格式错误!`);
return false;
}
// 校检文件大小
if (props.fileSize) {
const isLt = file.size / 1024 / 1024 < props.fileSize;
if (!isLt) {
proxy.$modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`);
modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`);
return false;
}
}
@@ -152,21 +143,24 @@ function handleUploadSuccess(res, file) {
// 如果上传成功
if (res.code == 200) {
// 获取富文本实例
let quill = toRaw(quillEditorRef.value).getQuill();
let quill = quillEditorRef.value?.getQuill();
if (quill) {
// 获取光标位置
let length = quill.selection.savedRange.index;
let range = quill.selection?.savedRange || quill.getSelection();
let length = range?.index || 0;
// 插入图片res.url为服务器返回的图片链接地址
quill.insertEmbed(length, "image", import.meta.env.VITE_APP_BASE_API + res.fileName);
// 调整光标到最后
quill.setSelection(length + 1);
}
} else {
proxy.$modal.msgError("图片插入失败");
modal.msgError("图片插入失败");
}
}
// 上传失败处理
function handleUploadError() {
proxy.$modal.msgError("图片插入失败");
modal.msgError("图片插入失败");
}
</script>
@@ -174,76 +168,96 @@ function handleUploadError() {
.editor-img-uploader {
display: none;
}
.editor, .ql-toolbar {
.editor,
.ql-toolbar {
white-space: pre-wrap !important;
line-height: normal !important;
}
.quill-img {
display: none;
}
.ql-snow .ql-tooltip[data-mode="link"]::before {
content: "请输入链接地址:";
}
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
border-right: 0px;
content: "保存";
padding-right: 0px;
}
.ql-snow .ql-tooltip[data-mode="video"]::before {
content: "请输入视频地址:";
}
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
content: "14px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
content: "10px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
content: "18px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
content: "32px";
}
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
content: "文本";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
content: "标题1";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
content: "标题2";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
content: "标题3";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
content: "标题4";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
content: "标题5";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
content: "标题6";
}
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
content: "标准字体";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
content: "衬线字体";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
content: "等宽字体";

View File

@@ -39,7 +39,9 @@
</template>
<script setup>
import { ref, computed, watch } from 'vue';
import { getToken } from "@/utils/auth";
import modal from '@/plugins/modal';
const props = defineProps({
modelValue: [String, Object, Array],
@@ -65,7 +67,7 @@ const props = defineProps({
}
});
const { proxy } = getCurrentInstance();
const fileUpload = ref(null);
const emit = defineEmits();
const number = ref(0);
const uploadList = ref([]);
@@ -104,7 +106,7 @@ function handleBeforeUpload(file) {
const fileExt = fileName[fileName.length - 1];
const isTypeOk = props.fileType.indexOf(fileExt) >= 0;
if (!isTypeOk) {
proxy.$modal.msgError(`文件格式不正确, 请上传${props.fileType.join("/")}格式文件!`);
modal.msgError(`文件格式不正确, 请上传${props.fileType.join("/")}格式文件!`);
return false;
}
}
@@ -112,23 +114,23 @@ function handleBeforeUpload(file) {
if (props.fileSize) {
const isLt = file.size / 1024 / 1024 < props.fileSize;
if (!isLt) {
proxy.$modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`);
modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`);
return false;
}
}
proxy.$modal.loading("正在上传文件,请稍候...");
modal.loading("正在上传文件,请稍候...");
number.value++;
return true;
}
// 文件个数超出
function handleExceed() {
proxy.$modal.msgError(`上传文件数量不能超过 ${props.limit} 个!`);
modal.msgError(`上传文件数量不能超过 ${props.limit} 个!`);
}
// 上传失败
function handleUploadError(err) {
proxy.$modal.msgError("上传文件失败");
modal.msgError("上传文件失败");
}
// 上传成功回调
@@ -138,9 +140,9 @@ function handleUploadSuccess(res, file) {
uploadedSuccessfully();
} else {
number.value--;
proxy.$modal.closeLoading();
proxy.$modal.msgError(res.msg);
proxy.$refs.fileUpload.handleRemove(file);
modal.closeLoading();
modal.msgError(res.msg);
fileUpload.value.handleRemove(file);
uploadedSuccessfully();
}
}
@@ -158,7 +160,7 @@ function uploadedSuccessfully() {
uploadList.value = [];
number.value = 0;
emit("update:modelValue", listToString(fileList.value));
proxy.$modal.closeLoading();
modal.closeLoading();
}
}

View File

@@ -47,6 +47,8 @@
<script setup>
import { getToken } from "@/utils/auth";
import { ref, computed, watch, getCurrentInstance } from 'vue';
import modal from '@/plugins/modal';
const props = defineProps({
modelValue: [String, Object, Array],
@@ -72,7 +74,6 @@ const props = defineProps({
},
});
const { proxy } = getCurrentInstance();
const emit = defineEmits();
const number = ref(0);
const uploadList = ref([]);
@@ -82,6 +83,7 @@ const baseUrl = import.meta.env.VITE_APP_BASE_API;
const uploadImgUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload"); // 上传的图片服务器地址
const headers = ref({ Authorization: "Bearer " + getToken() });
const fileList = ref([]);
const imageUpload = ref(null);
const showTip = computed(
() => props.isShowTip && (props.fileType || props.fileSize)
);
@@ -124,7 +126,7 @@ function handleBeforeUpload(file) {
isImg = file.type.indexOf("image") > -1;
}
if (!isImg) {
proxy.$modal.msgError(
modal.msgError(
`文件格式不正确, 请上传${props.fileType.join("/")}图片格式文件!`
);
return false;
@@ -132,17 +134,17 @@ function handleBeforeUpload(file) {
if (props.fileSize) {
const isLt = file.size / 1024 / 1024 < props.fileSize;
if (!isLt) {
proxy.$modal.msgError(`上传头像图片大小不能超过 ${props.fileSize} MB!`);
modal.msgError(`上传头像图片大小不能超过 ${props.fileSize} MB!`);
return false;
}
}
proxy.$modal.loading("正在上传图片,请稍候...");
modal.loading("正在上传图片,请稍候...");
number.value++;
}
// 文件个数超出
function handleExceed() {
proxy.$modal.msgError(`上传文件数量不能超过 ${props.limit} 个!`);
modal.msgError(`上传文件数量不能超过 ${props.limit} 个!`);
}
// 上传成功回调
@@ -152,9 +154,9 @@ function handleUploadSuccess(res, file) {
uploadedSuccessfully();
} else {
number.value--;
proxy.$modal.closeLoading();
proxy.$modal.msgError(res.msg);
proxy.$refs.imageUpload.handleRemove(file);
modal.closeLoading();
modal.msgError(res.msg);
imageUpload.value.handleRemove(file);
uploadedSuccessfully();
}
}
@@ -176,14 +178,14 @@ function uploadedSuccessfully() {
uploadList.value = [];
number.value = 0;
emit("update:modelValue", listToString(fileList.value));
proxy.$modal.closeLoading();
modal.closeLoading();
}
}
// 上传失败
function handleUploadError() {
proxy.$modal.msgError("上传图片失败");
proxy.$modal.closeLoading();
modal.msgError("上传图片失败");
modal.closeLoading();
}
// 预览

View File

@@ -29,8 +29,11 @@
</template>
<script setup>
import { ref, computed, watch, onMounted, nextTick } from 'vue';
import { getCurrentInstance } from 'vue';
const { proxy } = getCurrentInstance();
const selectTree = ref(null);
const treeSelect = ref(null);
const props = defineProps({
/* 配置项 */
@@ -83,10 +86,10 @@ function initHandle() {
nextTick(() => {
const selectedValue = valueId.value;
if(selectedValue !== null && typeof (selectedValue) !== 'undefined') {
const node = proxy.$refs.selectTree.getNode(selectedValue)
const node = selectTree.value.getNode(selectedValue)
if (node) {
valueTitle.value = node.data[props.objMap.label]
proxy.$refs.selectTree.setCurrentKey(selectedValue) // 设置默认选中
selectTree.value.setCurrentKey(selectedValue) // 设置默认选中
defaultExpandedKey.value = [selectedValue] // 设置默认展开
}
} else {
@@ -98,11 +101,11 @@ function handleNodeClick(node) {
valueTitle.value = node[props.objMap.label]
valueId.value = node[props.objMap.value];
defaultExpandedKey.value = [];
proxy.$refs.treeSelect.blur()
treeSelect.value.blur()
selectFilterData('')
}
function selectFilterData(val) {
proxy.$refs.selectTree.filter(val)
selectTree.value.filter(val)
}
function filterNode(value, data) {
if (!value) return true

View File

@@ -85,6 +85,14 @@ function resolvePath(routePath, routeQuery) {
if (isExternal(props.basePath)) {
return props.basePath
}
// 特殊处理门诊医生站路径,确保路径正确
if (routePath === '/doctorstation' || routePath === 'doctorstation') {
if (routeQuery) {
let query = JSON.parse(routeQuery);
return { path: '/doctorstation', query: query }
}
return '/doctorstation'
}
if (routeQuery) {
let query = JSON.parse(routeQuery);
return { path: getNormalPath(props.basePath + '/' + routePath), query: query }

View File

@@ -1,11 +1,30 @@
import { createApp } from 'vue'
// 修复 util._extend 已弃用警告(仅在 Node.js 环境中需要)
if (typeof process !== 'undefined' && process.versions && process.versions.node) {
try {
import('util').then(util => {
if (!util._extend) {
util._extend = function(destination, source) {
for (var key in source) {
if (source.hasOwnProperty(key)) {
destination[key] = source[key];
}
}
return destination;
};
}
});
} catch (e) {
console.error('util._extend 补丁加载失败:', e);
}
}
import Cookies from 'js-cookie'
import ElementPlus from 'element-plus'
import zhCn from 'element-plus/es/locale/lang/zh-cn'
import 'element-plus/dist/index.css'
import locale from 'element-plus/es/locale/lang/zh-cn'
import '@/assets/styles/index.scss' // global css
@@ -84,8 +103,14 @@ app.component('ImageUpload', ImageUpload)
app.component('ImagePreview', ImagePreview)
app.component('RightToolbar', RightToolbar)
app.component('Editor', Editor)
app.use(registerComponents)
// 使用element-plus 并且设置全局的大小
app.use(ElementPlus, {
locale: zhCn,
// 支持 large、default、small
size: Cookies.get('size') || 'default'
})
app.use(ElMessage)
app.use(registerComponents)
app.use(router)
app.use(store)
app.use(plugins)
@@ -94,11 +119,5 @@ app.component('svg-icon', SvgIcon)
directive(app)
// 全局禁止点击遮罩层关闭弹窗
ElDialog.props.closeOnClickModal.default = false;
// 使用element-plus 并且设置全局的大小
app.use(ElementPlus, {
locale: zhCn,
// 支持 large、default、small
size: Cookies.get('size') || 'default'
})
app.mount('#app')

View File

@@ -33,8 +33,11 @@ router.beforeEach((to, from, next) => {
// 根据roles权限生成可访问的路由表
accessRoutes.forEach(route => {
if (!isHttp(route.path)) {
// 检查是否已经存在同名路由
if (!router.hasRoute(route.name)) {
router.addRoute(route) // 动态添加可访问路由表
}
}
})
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
})

View File

@@ -1,32 +1,47 @@
import { createWebHistory, createRouter } from 'vue-router';
import { createWebHistory, createRouter } from 'vue-router'
/* Layout */
import Layout from '@/layout';
import Layout from '@/layout'
/**
* Note: 路由配置项
* Note: 路由配置项说明
*
* hidden: true // 当设置 true 的时候该路由不会侧边栏出现 如401login等页面者如一些编辑页面/edit/1
* alwaysShow: true // 当你一个路由下的 children 声明的路由大于1个时自动会变成嵌套模式--如组件页面
* // 只有一个时,会将那个子路由当做根路由显示在侧边栏--如引导页面
* // 若想不管路由下面的 children 声明的个数都显示你的根路由
* // 你可以设置 alwaysShow: true这样它就会忽略之前定义的规则一直显示根路由
* redirect: noRedirect // 当设置 noRedirect 的时候该路由在面包屑导航中不可被点击
* name:'router-name' // 设定路由的名字,一定要填写不然使用<keep-alive>时会出现各种问题
* hidden: true // 当设置 true 时,该路由不会侧边栏出现如401login等页面或一些编辑页面/edit/1
* alwaysShow: true // 当路由下的 children 声明的路由大于1个时自动变为嵌套模式如组件页面
* // 只有一个时,会将子路由作为根路由显示在侧边栏如引导页面
* // 若想不管 children 个数都显示根路由,可设置 alwaysShow: true忽略之前定义的规则
* redirect: noRedirect // 当设置 noRedirect 时,该路由在面包屑导航中不可点击
* name:'router-name' // 设定路由的名字,必须填写,否则使用<keep-alive>时会出现问题
* query: '{"id": 1, "name": "ry"}' // 访问路由的默认传递参数
* roles: ['admin', 'common'] // 访问路由的角色权限
* permissions: ['a:a:a', 'b:b:b'] // 访问路由的菜单权限
* meta : {
noCache: true // 如果设置为true则不会被 <keep-alive> 缓存(默认 false)
* meta: {
noCache: true // 如果设置为true则不会被 <keep-alive> 缓存默认 false
title: 'title' // 设置该路由在侧边栏和面包屑中展示的名字
icon: 'svg-name' // 设置该路由的图标对应路径src/assets/icons/svg
breadcrumb: false // 如果设置为false则不会在breadcrumb面包屑中显示
activeMenu: '/system/user' // 当路由设置了该属性,则会高亮对应的侧边栏
activeMenu: '/system/user' // 当路由设置了该属性,则会高亮对应的侧边栏
}
*/
// 公共路由
// 公共路由 - 所有用户均可访问的路由
export const constantRoutes = [
{ path: '/appoinmentmanage', component: Layout, redirect: '/appoinmentmanage', name: 'AppoinmentManage', hidden: true, meta: { title: '预约管理', icon: 'component' }, children: [ { path: '', component: () => import('@/views/appoinmentmanage/index.vue'), name: 'AppoinmentManageIndex', meta: { title: '预约管理' } } ] },
// 门诊医生站路由
{
path: '/doctorstation',
component: Layout,
redirect: '/doctorstation',
name: 'DoctorStation',
meta: { title: '门诊医生站', icon: 'doctorstation' },
children: [
{
path: '',
component: () => import('@/views/doctorstation/index.vue'),
name: 'DoctorStationIndex',
meta: { title: '门诊医生站', icon: 'doctorstation' }
}
]
},
// 重定向路由
{
path: '/redirect',
component: Layout,
@@ -34,30 +49,29 @@ export const constantRoutes = [
children: [
{
path: '/redirect/:path(.*)',
component: () => import('@/views/redirect/index.vue'),
},
],
component: () => import('@/views/redirect/index.vue')
}
]
},
// 登录路由
{
path: '/login',
component: () => import('@/views/login'),
hidden: true,
hidden: true
},
// 注册路由
{
path: '/register',
component: () => import('@/views/register'),
hidden: true,
},
{
path: '/:pathMatch(.*)*',
component: () => import('@/views/error/404'),
hidden: true,
hidden: true
},
// 401权限不足路由
{
path: '/401',
component: () => import('@/views/error/401'),
hidden: true,
hidden: true
},
// 首页路由
{
path: '',
component: Layout,
@@ -67,11 +81,11 @@ export const constantRoutes = [
path: '/index',
component: () => import('@/views/index'),
name: 'Index',
meta: { title: '首页', icon: 'dashboard', affix: true },
meta: { title: '首页', icon: 'dashboard', affix: true }
}
]
},
],
},
// 个人中心路由
{
path: '/user',
component: Layout,
@@ -82,16 +96,11 @@ export const constantRoutes = [
path: 'profile',
component: () => import('@/views/system/user/profile/index'),
name: 'Profile',
meta: { title: '个人中心', icon: 'user' },
},
],
},
];
meta: { title: '个人中心', icon: 'user' }
}
]
},
// 添加套餐管理相关路由到公共路由确保始终可用
// 套餐管理相关路由 - 添加到公共路由确保始终可用
{
path: '/maintainSystem/Inspection/PackageManagement',
component: Layout,
@@ -104,11 +113,26 @@ export const constantRoutes = [
meta: { title: '套餐管理' }
}
]
},
// 预约管理直接访问路由 - 兼容外部系统访问
{
path: '/reservationRecord2/appoinmentmanage',
component: Layout,
hidden: true,
children: [
{
path: '',
component: () => import('@/views/appoinmentmanage/clinicRoom/index.vue'),
name: 'DirectClinicRoom',
meta: { title: '门诊出诊医生诊室设置' }
}
]
}
]
// 动态路由基于用户权限动态加载
export const dynamicRoutes = [
// 动态路由 - 基于用户权限动态加载的路由
export const dynamicRoutes = [
// 基础管理路由
{
path: '/basicmanage',
component: Layout,
@@ -124,7 +148,7 @@ export const constantRoutes = [
}
]
},
// 兼容系统业务管理路径
// 兼容系统业务管理路径的发票管理路由
{
path: '/system/ywgz',
component: Layout,
@@ -139,6 +163,7 @@ export const constantRoutes = [
}
]
},
// 维护系统路由
{
path: '/maintainSystem',
component: Layout,
@@ -148,22 +173,23 @@ export const constantRoutes = [
children: [
{
path: '',
redirect: 'chargeConfig'
redirect: 'chargeConfig',
name: 'MaintainSystemIndex' // 添加名称以解决警告
},
{
path: 'chargeConfig',
path: 'chargeConfig', // 收费配置路由
component: () => import('@/views/maintainSystem/chargeConfig/index.vue'),
name: 'ChargeConfig',
meta: { title: '挂号收费系统参数维护', icon: 'config', permissions: ['maintainSystem:chargeConfig:list'] }
},
{
path: 'Inspection',
path: 'Inspection', // 检验管理路由
component: () => import('@/views/maintainSystem/Inspection/index.vue'),
name: 'Inspection',
meta: { title: '检验管理', icon: 'inspection' },
children: [
{
path: 'PackageManagement',
path: 'PackageManagement', // 套餐管理路由
component: () => import('@/views/maintainSystem/Inspection/PackageManagement.vue'),
name: 'PackageManagement',
meta: { title: '套餐管理' }
@@ -172,6 +198,7 @@ export const constantRoutes = [
}
]
},
// 系统管理路由
{
path: '/system',
component: Layout,
@@ -180,61 +207,62 @@ export const constantRoutes = [
meta: { title: '系统管理', icon: 'system' },
children: [
{
path: 'user',
path: 'user', // 用户管理路由
component: () => import('@/views/system/user/index.vue'),
name: 'User',
meta: { title: '用户管理', icon: 'user', permissions: ['system:user:list'] }
},
{
path: 'role',
path: 'role', // 角色管理路由
component: () => import('@/views/system/role/index.vue'),
name: 'Role',
meta: { title: '角色管理', icon: 'role', permissions: ['system:role:list'] }
},
{
path: 'menu',
path: 'menu', // 菜单管理路由
component: () => import('@/views/system/menu/index.vue'),
name: 'Menu',
meta: { title: '菜单管理', icon: 'menu', permissions: ['system:menu:list'] }
},
{
path: 'dept',
path: 'dept', // 部门管理路由
component: () => import('@/views/system/dept/index.vue'),
name: 'Dept',
meta: { title: '部门管理', icon: 'dept', permissions: ['system:dept:list'] }
},
{
path: 'post',
path: 'post', // 岗位管理路由
component: () => import('@/views/system/post/index.vue'),
name: 'Post',
meta: { title: '岗位管理', icon: 'post', permissions: ['system:post:list'] }
},
{
path: 'dict',
path: 'dict', // 字典管理路由
component: () => import('@/views/system/dict/index.vue'),
name: 'Dict',
meta: { title: '字典管理', icon: 'dict', permissions: ['system:dict:list'] }
},
{
path: 'config',
path: 'config', // 参数配置路由
component: () => import('@/views/system/config/index.vue'),
name: 'Config',
meta: { title: '参数配置', icon: 'config', permissions: ['system:config:list'] }
},
{
path: 'notice',
path: 'notice', // 通知公告路由
component: () => import('@/views/system/notice/index.vue'),
name: 'Notice',
meta: { title: '通知公告', icon: 'notice', permissions: ['system:notice:list'] }
},
{
path: 'tenant',
path: 'tenant', // 租户管理路由
component: () => import('@/views/system/tenant/index.vue'),
name: 'Tenant',
meta: { title: '租户管理', icon: 'tenant', permissions: ['system:tenant:list'] }
}
]
},
// 租户用户设置路由
{
path: '/system/tenant-user',
component: Layout,
@@ -245,13 +273,11 @@ export const constantRoutes = [
path: 'set/:tenantId(\\d+)',
component: () => import('@/views/system/tenant/setUser'),
name: 'SetUser',
meta: { title: '所属用户', activeMenu: '/system/basicmanage/tenant' },
},
],
meta: { title: '所属用户', activeMenu: '/system/tenant' }
}
]
},
// 租户合同管理路由
{
path: '/system/tenant-contract',
component: Layout,
@@ -262,13 +288,11 @@ export const constantRoutes = [
path: 'set/:tenantId(\\d+)',
component: () => import('@/views/system/tenant/setContract'),
name: 'SetContract',
meta: { title: '合同管理', activeMenu: '/system/basicmanage/tenant' },
},
],
meta: { title: '合同管理', activeMenu: '/system/tenant' }
}
]
},
// 用户角色分配路由
{
path: '/system/user-auth',
component: Layout,
@@ -279,10 +303,11 @@ export const constantRoutes = [
path: 'role/:userId(\\d+)',
component: () => import('@/views/system/user/authRole'),
name: 'AuthRole',
meta: { title: '分配角色', activeMenu: '/system/user' },
},
],
meta: { title: '分配角色', activeMenu: '/system/user' }
}
]
},
// 角色用户分配路由
{
path: '/system/role-auth',
component: Layout,
@@ -293,10 +318,11 @@ export const constantRoutes = [
path: 'user/:roleId(\\d+)',
component: () => import('@/views/system/role/authUser'),
name: 'AuthUser',
meta: { title: '分配用户', activeMenu: '/system/role' },
},
],
meta: { title: '分配用户', activeMenu: '/system/role' }
}
]
},
// 字典数据路由
{
path: '/system/dict-data',
component: Layout,
@@ -307,10 +333,11 @@ export const constantRoutes = [
path: 'index/:dictId(\\d+)',
component: () => import('@/views/system/dict/data'),
name: 'Data',
meta: { title: '字典数据', activeMenu: '/system/dict' },
},
],
meta: { title: '字典数据', activeMenu: '/system/dict' }
}
]
},
// 系统监控路由
{
path: '/monitor',
component: Layout,
@@ -319,25 +346,26 @@ export const constantRoutes = [
meta: { title: '系统监控', icon: 'monitor' },
children: [
{
path: 'operlog',
path: 'operlog', // 操作日志路由
component: () => import('@/views/monitor/operlog/index.vue'),
name: 'Operlog',
meta: { title: '操作日志', icon: 'operlog', permissions: ['monitor:operlog:list'] }
},
{
path: 'logininfor',
path: 'logininfor', // 登录日志路由
component: () => import('@/views/monitor/logininfor/index.vue'),
name: 'Logininfor',
meta: { title: '登录日志', icon: 'logininfor', permissions: ['monitor:logininfor:list'] }
},
{
path: 'job',
path: 'job', // 定时任务路由
component: () => import('@/views/monitor/job/index.vue'),
name: 'Job',
meta: { title: '定时任务', icon: 'job', permissions: ['monitor:job:list'] }
}
]
},
// 系统工具路由
{
path: '/tool',
component: Layout,
@@ -346,13 +374,14 @@ export const constantRoutes = [
meta: { title: '系统工具', icon: 'tool' },
children: [
{
path: 'gen',
path: 'gen', // 代码生成路由
component: () => import('@/views/tool/gen/index.vue'),
name: 'Gen',
meta: { title: '代码生成', icon: 'gen', permissions: ['tool:gen:list'] }
}
]
},
// 定时任务日志路由
{
path: '/monitor/job-log',
component: Layout,
@@ -363,10 +392,11 @@ export const constantRoutes = [
path: 'index/:jobId(\\d+)',
component: () => import('@/views/monitor/job/log'),
name: 'JobLog',
meta: { title: '调度日志', activeMenu: '/monitor/job' },
},
],
meta: { title: '调度日志', activeMenu: '/monitor/job' }
}
]
},
// 代码生成编辑路由
{
path: '/tool/gen-edit',
component: Layout,
@@ -377,11 +407,6 @@ export const constantRoutes = [
path: 'index/:tableId(\\d+)',
component: () => import('@/views/tool/gen/editTable'),
name: 'GenEdit',
meta: { title: '修改生成配置', activeMenu: '/tool/gen' },
},
],
},
];
meta: { title: '修改生成配置', activeMenu: '/tool/gen' }
}
]
@@ -391,23 +416,26 @@ export const constantRoutes = [
// 合并常量路由和动态路由,确保所有路由都能被访问
const allRoutes = [...constantRoutes, ...dynamicRoutes];
// 添加404路由到所有路由的最后
// 添加404路由到所有路由的最后,确保捕获所有未匹配的路由
allRoutes.push({
path: "/:pathMatch(.*)*",
component: () => import('@/views/error/404'),
hidden: true
});
// 创建Vue Router实例
const router = createRouter({
history: createWebHistory(),
routes: allRoutes,
history: createWebHistory(), // 使用HTML5历史模式
routes: allRoutes, // 使用合并后的所有路由
scrollBehavior(to, from, savedPosition) {
// 页面滚动行为:如果有保存的位置则恢复,否则滚动到顶部
if (savedPosition) {
return savedPosition;
return savedPosition
} else {
return { top: 0 };
return { top: 0 }
}
},
});
// 导出路由实例
export default router;

View File

@@ -1,6 +1,8 @@
<template>
<!-- 跌倒/坠床评估护理记录单主容器 -->
<div>
<div class="business">
<!-- 已有记录展示表格 -->
<el-table
:data="tableDataSource"
border
@@ -8,10 +10,15 @@
fit
:header-cell-style="{ background: '#f2f2f2', color: 'black' }"
>
<!-- 记录时间列 -->
<el-table-column prop="content.recordTime" label="记录时间" />
<!-- 评估分数列 -->
<el-table-column prop="content.totalScore" label="评估分数" />
<!-- 护理措施列 -->
<el-table-column prop="content.patientCareSessionsTableList" label="护理措施" />
<!-- 责任护士列 -->
<el-table-column prop="content.nurseSignature" label="责任护士" />
<!-- 操作列编辑和删除按钮 -->
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
@@ -36,9 +43,12 @@
</el-table-column>
</el-table>
<!-- 跌倒/坠床评估护理记录单表单区域 -->
<div name="跌倒/坠床评估护理记录单" class="changeMajor" style="width: 99.9%">
<div>
<!-- 表单主体 -->
<el-form ref="formRef" :model="form" style="width: 99.9%">
<!-- 标题行 -->
<el-form-item style="text-align: center">
<div
style="
@@ -54,10 +64,12 @@
</div>
</el-form-item>
<!-- 日期时间选择器 -->
<el-form-item label="日期:" class="changeMajorFromItem" style="width: 100%">
<el-row :span="20">
<el-col :span="8" style="padding-left: 0px !important">
<el-form-item>
<!-- 日期时间选择器 -->
<el-date-picker
v-model="form.ZKDATE"
type="datetime"
@@ -67,6 +79,7 @@
style="width: 800px"
:disabled="admissionDataForm !== undefined"
/>
<!-- 时间选择器被注释掉 -->
<!-- <span style="margin-left: 5px">时间</span>
<el-time-picker
v-model="form.ZKTIME"
@@ -77,6 +90,7 @@
/> -->
</el-form-item>
</el-col>
<!-- 新增/保存按钮 -->
<el-col :span="5">
<el-button
v-if="!updateFlag"
@@ -100,6 +114,7 @@
</el-row>
</el-form-item>
<!-- 危险因素评估表格 -->
<el-form-item style="padding-top: 10px; margin: 0px !important">
<el-table
:data="dangerData"
@@ -107,6 +122,7 @@
:span-method="handleSpan"
style="text-align: center"
>
<!-- 动态生成表格列 -->
<el-table-column
v-for="column in dangerColumns"
:key="column.key"
@@ -115,6 +131,7 @@
:label="column.title"
align="center"
/>
<!-- 选择列复选框 -->
<el-table-column prop="id" label="选择" width="80" align="center">
<template #default="{ row }">
<el-checkbox v-model="row.checked" @change="handleDangerChange(row)" />
@@ -123,6 +140,7 @@
</el-table>
</el-form-item>
<!-- 总分显示 -->
<el-form-item
style="text-align: center; margin-bottom: 0px; padding: 0px"
class="changeMajorFromItem"
@@ -135,6 +153,7 @@
</el-row>
</el-form-item>
<!-- 护理措施表格 -->
<el-form-item style="padding-top: 10px">
<el-table
:data="nursingData"
@@ -142,6 +161,7 @@
:span-method="arraySpanMethod"
style="width: 100%"
>
<!-- 动态生成表格列 -->
<el-table-column
v-for="column in nursingColumns"
:key="column.key"
@@ -150,6 +170,7 @@
:label="column.title"
align="center"
/>
<!-- 选择列复选框 -->
<el-table-column prop="id" label="选择" width="80" align="center">
<template #default="{ row }">
<el-checkbox v-model="row.checked" @change="handleNursingChange(row)" />
@@ -158,6 +179,7 @@
</el-table>
</el-form-item>
<!-- 护士签字输入框 -->
<el-form-item
style="text-align: center; margin-bottom: 0px; padding: 0px"
class="changeMajorFromItem"
@@ -177,6 +199,7 @@
</el-row>
</el-form-item>
<!-- 备注信息 -->
<el-form-item>
<el-row :span="20">
<el-col :span="5">
@@ -197,22 +220,24 @@
</template>
<script setup>
// 组件选项定义
defineOptions({
name: 'FallBedFallAssessment',
name: '跌倒/坠床评估护理记录单',
});
// 导入所需模块
import { ref, reactive, computed, onMounted } from 'vue';
import { ElMessage } from 'element-plus';
// import { webapp_ws_ajax_run, urlAddRandomNo } from '@/utils/grwebapp';
// import { useRoute, useRouter } from 'vue-router';
// 响应式数据
// 使用路由相关功能
const route = useRoute();
const router = useRouter();
// 定义引用变量
const queryRef = ref();
const formRef = ref();
// 基本数据变量
const wardCode = ref('');
const patientId = ref('');
const visitId = ref('');
@@ -226,17 +251,18 @@ const totalScore = ref(0);
const lastSubmit = ref('');
const admissionDataForm = ref(route.params.admissionData);
// 表单数据模型
const form = reactive({
ZKDATE: '',
ZKTIME: '',
recordTime: '',
totalScore: 0,
bedFallRiskAssessmentList: [],
nurseSignature: '',
patientCareSessionsCheckedList: [],
ZKDATE: '', // 日期
ZKTIME: '', // 时间
recordTime: '', // 记录时间
totalScore: 0, // 总分
bedFallRiskAssessmentList: [], // 跌倒风险评估列表
nurseSignature: '', // 护士签名
patientCareSessionsCheckedList: [], // 护理措施选中列表
});
// 危险因素表格列
// 危险因素表格列配置
const dangerColumns = [
{
key: 'content',
@@ -301,7 +327,7 @@ const dangerData = ref([
{ id: '27', evalContent: '麻醉止痛剂', score: 2, checked: false },
]);
// 护理措施表格列
// 护理措施表格列配置
const nursingColumns = [
{
key: 'content',
@@ -338,21 +364,21 @@ const instructions = [
'3.评分≥5高度风险每周至少评估一次需采取适宜的预防措施同时填写《预防患者跌倒/坠床知情告知书》',
];
// 计算属性
// 计算属性:计算选中的危险因素总分
const calculate = computed(() => {
return dangerData.value
.filter((option) => option.checked)
.reduce((total, option) => total + option.score, 0);
});
// 计算属性:判断表单是否为空
const isFormEmpty = computed(() => {
return (
form.ZKDATE === '' && form.ZKTIME === '' && form.recordTime === '' && form.nurseSignature === ''
);
});
// 方法 - 不再需要handleData方法通过表单输入和按钮加载数据
// 危险因素选择变化处理函数
const handleDangerChange = (row) => {
totalScore.value = calculate.value;
form.bedFallRiskAssessmentList = dangerData.value
@@ -360,12 +386,14 @@ const handleDangerChange = (row) => {
.map((item) => item.id);
};
// 护理措施选择变化处理函数
const handleNursingChange = (row) => {
form.patientCareSessionsCheckedList = nursingData.value
.filter((item) => item.checked)
.map((item) => item.id);
};
// 初始化函数:加载模拟数据
const init = async () => {
// 使用模拟数据不再调用后端API
try {
@@ -427,6 +455,7 @@ const init = async () => {
}
};
// 危险因素表格合并单元格处理函数
const handleSpan = ({ row, column, rowIndex, columnIndex }) => {
if (columnIndex === 0) {
if (rowIndex === 0) {
@@ -473,6 +502,7 @@ const handleSpan = ({ row, column, rowIndex, columnIndex }) => {
return [1, 1];
};
// 护理措施表格合并单元格处理函数
const arraySpanMethod = ({ row, column, rowIndex, columnIndex }) => {
// 护理措施
if (columnIndex === 0) {
@@ -489,8 +519,9 @@ const arraySpanMethod = ({ row, column, rowIndex, columnIndex }) => {
return [1, 1];
};
// 提交表单处理函数
const onSubmit = async () => {
// 检查上次提交时间
// 检查上次提交时间,防止重复提交
if (lastSubmit.value && new Date() - lastSubmit.value < 2000) {
ElMessage.error('禁止重复提交!');
return;
@@ -562,6 +593,7 @@ const onSubmit = async () => {
}
};
// 编辑记录处理函数
const handleUpdate = (row) => {
const loginUser = JSON.parse(window.localStorage.getItem('loginUser'));
@@ -591,6 +623,7 @@ const handleUpdate = (row) => {
}
};
// 重置表单函数
const reset = () => {
Object.assign(form, {
ZKDATE: '',
@@ -623,6 +656,7 @@ const reset = () => {
}
};
// 删除记录处理函数
const handleDelete = (row) => {
const loginUser = JSON.parse(window.localStorage.getItem('loginUser'));
@@ -646,6 +680,7 @@ const handleDelete = (row) => {
}
};
// 打印预览函数(暂未实现)
const dc_ajax_preview = () => {
var args = {
report: urlAddRandomNo('./grf/NurseRecord_Pressure_208.grf'),
@@ -656,6 +691,7 @@ const dc_ajax_preview = () => {
webapp_ws_ajax_run(args);
};
// 数据转换函数,用于报表打印
const transformData = () => {
const jsonDate = [...tableDataSource.value];
@@ -802,7 +838,7 @@ const transformData = () => {
return transformedData;
};
// 生命周期钩子
// 组件挂载后执行的生命周期函数
onMounted(() => {
try {
// 安全获取用户信息
@@ -831,6 +867,7 @@ onMounted(() => {
</script>
<style scoped>
/* 页面样式定义 */
.business {
background: white;
border-radius: 5px;
@@ -894,4 +931,10 @@ onMounted(() => {
margin-bottom: 0px !important;
}
}
/* 备注信息列表样式 */
.instructions-list {
list-style-type: none;
padding-left: 0;
}
</style>

View File

@@ -1,17 +1,42 @@
// 动态引入 template 目录下的所有 .vue 文件
/**
* 模板组件注册模块
* 动态引入 template 目录下的所有 .vue 文件,并将它们注册为全局组件
*/
// 动态引入 template 目录下的所有 .vue 文件(包括中文命名的文件)
// 使用 { eager: true } 表示立即加载所有匹配的文件
const templates = import.meta.glob('./*.vue', { eager: true });
// 存储所有加载的组件
const components = [];
// 遍历所有引入的文件
for (const path in templates) {
try {
// 获取组件的默认导出
const component = templates[path].default;
// 检查组件是否有 name 属性,如果没有则跳过
if (component && component.name) {
components.push(component);
} else {
console.warn(`组件 ${path} 缺少 name 属性,将不会被注册`);
}
} catch (error) {
console.error(`加载组件 ${path} 时出错:`, error);
}
}
/**
* 注册所有组件到 Vue 应用实例
* @param {Object} app - Vue 应用实例
*/
const registerComponents = (app) => {
components.forEach((component) => {
// 使用组件的 name 属性作为组件名称进行注册
app.component(component.name, component);
})
}
export { components, registerComponents };
});
};
// 导出组件数组和注册函数
export { components, registerComponents };

View File

@@ -1,15 +1,19 @@
<template>
<!-- 门诊病历表单主容器 -->
<div class="medical-form">
<!-- 患者基本信息展示区域 -->
<div class="patient-name">
患者姓名{{ patient?.patientName || '未知' }} &nbsp;&nbsp; 病历号{{
patient?.busNo || '未知'
}}
</div>
<!-- 医院名称和标题 -->
<h2 style="text-align: center">{{ userStore.hospitalName }}</h2>
<h2 style="text-align: center">门诊病历</h2>
<!-- 滚动内容区域 -->
<div class="form-scroll-container">
<!-- Element Plus表单组件 -->
<el-form
ref="formRef"
:model="formData"
@@ -18,34 +22,40 @@
label-align="left"
class="medical-full-form"
>
<!-- 基础信息区域标题 -->
<h4 class="section-title">基础信息</h4>
<!-- 1. 基础信息单行自适应排列 -->
<el-form-item class="form-section">
<div class="single-row-layout">
<!-- 身高输入项 -->
<el-form-item label="身高" prop="height" class="row-item">
<div class="input-with-unit">
<el-input v-model="formData.height" type="text" placeholder="请输入" />
<span class="unit">cm</span>
</div>
</el-form-item>
<!-- 体重输入项 -->
<el-form-item label="体重" prop="weight" class="row-item">
<div class="input-with-unit">
<el-input v-model="formData.weight" type="text" placeholder="请输入" />
<span class="unit">kg</span>
</div>
</el-form-item>
<!-- 体温输入项 -->
<el-form-item label="体温" prop="temperature" class="row-item">
<div class="input-with-unit">
<el-input v-model="formData.temperature" type="text" placeholder="请输入" />
<span class="unit"></span>
</div>
</el-form-item>
<!-- 脉搏输入项 -->
<el-form-item label="脉搏" prop="pulse" class="row-item">
<div class="input-with-unit">
<el-input v-model="formData.pulse" type="text" placeholder="请输入" />
<span class="unit">/</span>
</div>
</el-form-item>
<!-- 发病日期选择项 -->
<el-form-item label="发病日期" prop="onsetDate" class="row-item">
<el-date-picker
v-model="formData.onsetDate"
@@ -58,10 +68,13 @@
</el-form-item>
</div>
</el-form-item>
<!-- 病史信息区域标题 -->
<h4 class="section-title">病史信息</h4>
<!-- 2. 病史信息单行自适应排列新增调整 -->
<el-form-item class="form-section">
<div class="single-row-layout">
<!-- 现病史输入项 -->
<el-form-item label="现病史" prop="presentIllness" class="row-item history-item">
<el-input
v-model="formData.presentIllness"
@@ -70,9 +83,11 @@
autosize
/>
</el-form-item>
<!-- 既往史输入项 -->
<el-form-item label="既往史" prop="pastIllness" class="row-item history-item">
<el-input v-model="formData.pastIllness" type="textarea" placeholder="无" autosize />
</el-form-item>
<!-- 个人史输入项 -->
<el-form-item label="个人史" prop="personalHistory" class="row-item history-item">
<el-input
v-model="formData.personalHistory"
@@ -81,6 +96,7 @@
autosize
/>
</el-form-item>
<!-- 过敏史输入项 -->
<el-form-item label="过敏史" prop="allergyHistory" class="row-item history-item">
<el-input
v-model="formData.allergyHistory"
@@ -89,6 +105,7 @@
autosize
/>
</el-form-item>
<!-- 家族史输入项 -->
<el-form-item label="家族史" prop="familyHistory" class="row-item history-item">
<el-input
v-model="formData.familyHistory"
@@ -99,6 +116,8 @@
</el-form-item>
</div>
</el-form-item>
<!-- 主诉查体(治疗)处置辅助检查区域标题 -->
<h4 class="section-title">主诉查体(治疗)处置辅助检查</h4>
<!-- 3. 主诉必填 -->
<el-form-item label="主诉" prop="complaint" class="required form-item-single">
@@ -111,6 +130,7 @@
/>
</el-form-item>
<!-- 4. 查体处理辅助检查 -->
<!-- 查体(治疗)输入项 -->
<el-form-item label="查体(治疗)" prop="physicalExam" class="form-item-single">
<el-input
v-model="formData.physicalExam"
@@ -121,6 +141,7 @@
/>
</el-form-item>
<!-- 处置输入项 -->
<el-form-item label="处置" prop="treatment" class="form-item-single">
<el-input
v-model="formData.treatment"
@@ -131,6 +152,7 @@
/>
</el-form-item>
<!-- 辅助检查输入项 -->
<el-form-item label="辅助检查" prop="auxiliaryExam" class="form-item-single">
<el-input
v-model="formData.auxiliaryExam"
@@ -146,12 +168,14 @@
</template>
<script setup>
// 导入Vue相关功能和组件
import { reactive, ref, onBeforeMount, onMounted, watch } from 'vue';
import useUserStore from '../store/modules/user';
import { ElInput, ElMessage, ElForm, ElFormItem } from 'element-plus';
import { patientInfo } from '../views/doctorstation/components/store/patient';
import { pa } from 'element-plus/es/locales.mjs';
// 定义组件选项
defineOptions({
name: 'OutpatientMedicalRecord',
components: { ElInput, ElMessage, ElForm, ElFormItem },
@@ -164,33 +188,42 @@ defineOptions({
// required: true,
// },
// });
// 定义组件接收的属性(目前为空)
const props = defineProps({});
// 定义组件触发的事件
const emits = defineEmits(['submitOk']);
// 数据初始化
// 获取用户store实例用于获取医院名称等全局信息
const userStore = useUserStore();
// 患者信息引用,存储当前就诊患者的基本信息
const patient = ref(null);
// 表单引用,用于访问表单实例进行验证等操作
const formRef = ref(null);
// 表单数据(全部字符类型)
// 存储门诊病历表单的所有字段数据
const formData = reactive({
height: '', // 身高
weight: '', // 体重
temperature: '', // 体温
pulse: '', // 脉搏
height: '', // 身高(cm)
weight: '', // 体重(kg)
temperature: '', // 体温(℃)
pulse: '', // 脉搏(次/分)
onsetDate: '', // 发病日期
complaint: '', // 主诉(必填)
complaint: '', // 主诉(必填
presentIllness: '', // 现病史
pastIllness: '', // 既往史
personalHistory: '', // 个人史
allergyHistory: '', // 过敏史
physicalExam: '', // 查体
treatment: '', // 处理
auxiliaryExam: '', // 辅助检查
physicalExam: '', // 查体结果
treatment: '', // 处理方案
auxiliaryExam: '', // 辅助检查结果
familyHistory: '', // 家族史
});
// 表单校验规则
// 定义表单字段的验证规则,目前仅主诉为必填项
const rules = reactive({
complaint: [
{
@@ -202,15 +235,21 @@ const rules = reactive({
});
// 提交函数
// 用于触发表单验证并提交数据到父组件
const submit = () => {
// 表单验证
formRef.value.validate((isValid) => {
if (isValid) {
// 触发submitOk事件传递表单数据
emits('submitOk', formData);
// 显示成功消息
ElMessage.success('提交成功');
}
});
};
// 日期格式化工具
// 日期格式化工具函数
// 将Date对象格式化为 YYYY-MM-DD HH:mm 格式的字符串
const formatDateTime = (date) => {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
@@ -219,17 +258,23 @@ const formatDateTime = (date) => {
const minute = String(date.getMinutes()).padStart(2, '0');
return `${year}-${month}-${day} ${hour}:${minute}`;
};
// 表单数据赋值
// 表单数据赋值函数
// 用于外部组件向表单填充已有数据
const setFormData = (data) => {
if (data) {
// 将传入的数据合并到表单数据中
Object.assign(formData, data);
}
};
// 生命周期
// 生命周期钩子 - 组件挂载前
onBeforeMount(() => {});
// 生命周期钩子 - 组件挂载后
onMounted(() => {
console.log('当前患者信息:', patientInfo);
// 从store获取患者信息
patient.value = patientInfo.value;
// 初始化发病日期为当前时间
if (!formData.onsetDate) {
@@ -238,6 +283,7 @@ onMounted(() => {
});
// 监听患者信息变化,实现联动显示
// 当patientInfo发生变化时更新本地patient引用
watch(
() => patientInfo.value,
(newPatientInfo) => {
@@ -246,7 +292,8 @@ watch(
{ deep: true }
);
// 暴露接口
// 暴露接口供父组件调用
// 将formData、submit方法和setFormData方法暴露给父组件使用
defineExpose({ formData, submit, setFormData });
</script>

View File

@@ -1,21 +1,50 @@
// 导入 API 函数,用于从服务器获取带有选项列表的数据
import { getListWithOptionList } from '@/views/basicmanage/caseTemplatesStatistics/api';
// 导入 Vue 3 的组合式 APIonMounted组件挂载后执行和 ref响应式数据
import { onMounted, ref } from 'vue';
// 创建响应式数据:统计选项列表,初始为空数组
const statisticsOptionList = ref([]);
/**
* 初始化统计选项列表数据
* 异步函数,通过 API 获取数据并更新到响应式变量中
*/
const initStatic = async () => {
try {
// 调用 API 获取数据
const res = await getListWithOptionList();
// 将获取到的数据赋值给响应式变量
statisticsOptionList.value = res.data;
} catch (error) {
// 错误处理:打印错误信息到控制台
console.log(error);
}
};
/**
* Vue 3 组合式函数:用于获取和管理统计选项列表
* @returns {Object} 返回包含响应式数据和方法的对象
*/
export default function useOptionsList() {
// 组件挂载后自动初始化数据
onMounted(() => {
initStatic();
});
/**
* 根据代码获取对应的选项列表
* @param {string} code - 统计类型代码
* @returns {Array} 返回匹配的选项列表,如果没有匹配则返回空数组
*/
const getStatisticsOptionList = (code) => {
// 在统计选项列表中查找匹配代码的项,然后返回其 optionList 属性,如果没有找到则返回空数组
return statisticsOptionList.value.find((item) => item.code === code)?.optionList || [];
};
// 返回响应式数据和方法供组件使用
return {
statisticsOptionList,
getStatisticsOptionList,
statisticsOptionList, // 完整的统计选项列表
getStatisticsOptionList, // 根据代码获取选项列表的方法
};
}

View File

@@ -0,0 +1,44 @@
<template>
<div class="template-content">
<div class="template-header">
<h3>股骨头坏死(模板11111111)</h3>
</div>
<div class="template-body">
<p>主诉左侧髋部疼痛X个月加重1周</p>
<p>现病史患者X个月前无明显诱因出现左侧髋部疼痛活动后加重休息后减轻未予重视1周前疼痛加重行走困难遂来我院就诊</p>
<p>既往史否认高血压糖尿病冠心病等慢性病史否认手术外伤史否认药物过敏史</p>
<p>体格检查左侧髋关节压痛(+)活动受限左下肢肌力下降</p>
<p>辅助检查DR示左侧股骨头坏死</p>
<p>诊断左侧股骨头坏死</p>
<p>治疗方案1. 避免负重2. 药物治疗3. 必要时手术治疗</p>
</div>
</div>
</template>
<script setup>
defineOptions({
name: '股骨头坏死(模板11111111)'
})
// 可以在这里添加组件逻辑
</script>
<style scoped>
.template-content {
background-color: white;
border: 1px solid #ddd;
border-radius: 4px;
padding: 15px;
min-height: 300px;
}
.template-header {
border-bottom: 1px solid #eee;
padding-bottom: 10px;
margin-bottom: 15px;
}
.template-body p {
margin-bottom: 10px;
line-height: 1.5;
}
</style>

View File

@@ -0,0 +1,478 @@
<template>
<div class="app-container" v-loading="loading">
<!-- 筛选区 -->
<el-form :model="queryParams" ref="queryRef" :inline="true" class="filter-form">
<el-form-item label="诊室名称" prop="roomName">
<el-input
v-model="queryParams.roomName"
placeholder="请输入诊室名称"
clearable
style="width: 200px"
maxlength="50"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">查询</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
<el-button type="primary" icon="Plus" @click="handleAdd">新增</el-button>
</el-form-item>
</el-form>
<!-- 表格区 -->
<el-table
v-loading="loading"
:data="clinicRoomList"
border
style="width: 100%"
class="clinic-room-table"
>
<el-table-column prop="id" label="ID" width="180" align="center" />
<el-table-column prop="roomName" label="诊室名称" width="160" align="center" show-overflow-tooltip />
<el-table-column prop="department" label="科室名称" width="160" align="center" show-overflow-tooltip />
<el-table-column prop="building" label="诊室楼号" width="120" align="center" show-overflow-tooltip />
<el-table-column prop="floor" label="楼层" width="90" align="center" />
<el-table-column prop="roomNo" label="房间号" width="120" align="center" />
<el-table-column prop="isDisabled" label="停用" width="90" align="center">
<template #default="scope">
<el-tag :type="scope.row.isDisabled ? 'danger' : 'success'">
{{ scope.row.isDisabled ? '是' : '否' }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="remarks" label="备注" min-width="100" align="center" show-overflow-tooltip />
<el-table-column prop="void" label="作废" width="90" align="center">
<template #default="scope">
<el-tag :type="scope.row.void ? 'danger' : 'success'">
{{ scope.row.void ? '是' : '否' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="250" align="center" fixed="right">
<template #default="scope">
<el-button
type="primary"
link
icon="EditPen"
@click="handleEdit(scope.row)"
v-hasPermi="['appoinment:clinicRoom:edit']"
>编辑</el-button>
<el-button
type="info"
link
icon="View"
@click="handleView(scope.row)"
v-hasPermi="['appoinment:clinicRoom:query']"
>查看</el-button>
<el-button
type="danger"
link
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['appoinment:clinicRoom:remove']"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页区 -->
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
<!-- 新增/编辑/查看弹窗 -->
<el-dialog
:title="dialogTitle"
v-model="dialogVisible"
width="500px"
append-to-body
:close-on-click-modal="false"
>
<el-form
ref="formRef"
:model="form"
:rules="rules"
label-width="100px"
:disabled="dialogType === 'view'"
>
<el-form-item label="科室名称" prop="department">
<el-select
v-model="form.department"
placeholder="请选择科室"
style="width: 100%"
filterable
:disabled="dialogType === 'view'"
>
<el-option
v-for="item in departmentOptions"
:key="item.deptId || item.id"
:label="item.deptName || item.name"
:value="item.deptName || item.name"
/>
</el-select>
</el-form-item>
<el-form-item label="诊室名称" prop="roomName">
<el-input
v-model="form.roomName"
placeholder="请输入诊室名称"
maxlength="50"
show-word-limit
/>
</el-form-item>
<el-form-item label="诊室楼号" prop="building">
<el-input
v-model="form.building"
placeholder="请输入诊室楼号"
maxlength="50"
/>
</el-form-item>
<el-form-item label="诊室楼层" prop="floor">
<el-input
v-model="form.floor"
placeholder="请输入诊室楼层"
maxlength="10"
/>
</el-form-item>
<el-form-item label="诊室房间号" prop="roomNo">
<el-input
v-model="form.roomNo"
placeholder="请输入诊室房间号"
maxlength="50"
/>
</el-form-item>
<el-form-item label="停用状态" prop="isDisabled">
<el-radio-group v-model="form.isDisabled">
<el-radio :label="false">启用</el-radio>
<el-radio :label="true">停用</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remarks">
<el-input
v-model="form.remarks"
type="textarea"
:rows="3"
placeholder="请输入备注"
maxlength="500"
show-word-limit
/>
</el-form-item>
<el-form-item label="作废" prop="void">
<el-radio-group v-model="form.void">
<el-radio :label="false"></el-radio>
<el-radio :label="true"></el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button v-if="dialogType !== 'view'" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="ClinicRoom">
import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
getClinicRoomList,
getClinicRoomDetail,
addClinicRoom,
updateClinicRoom,
deleteClinicRoom,
getDepartmentList
} from '@/api/appoinmentmanage/clinicRoom'
const { proxy } = getCurrentInstance()
// 加载状态
const loading = ref(false)
// 表格数据
const clinicRoomList = ref([])
// 总数
const total = ref(0)
// 查询参数
const queryParams = reactive({
pageNum: 1,
pageSize: 10,
roomName: null
})
// 科室选项
const departmentOptions = ref([])
// 弹窗相关
const dialogVisible = ref(false)
const dialogType = ref('') // add/edit/view
const dialogTitle = ref('')
const formRef = ref()
// 表单数据
const form = reactive({
id: null,
roomName: '',
department: '',
building: '',
floor: '',
roomNo: '',
isDisabled: false,
remarks: '',
void: false
})
// 表单验证规则
const rules = {
roomName: [
{ required: true, message: '诊室名称不能为空', trigger: 'blur' },
{ max: 50, message: '诊室名称长度不能超过50个字符', trigger: 'blur' }
],
department: [
{ required: true, message: '科室名称不能为空', trigger: 'change' }
]
}
// 获取诊室列表
function getList() {
loading.value = true
getClinicRoomList(queryParams)
.then(response => {
if (response.code === 200) {
clinicRoomList.value = response.data?.records || response.data || []
total.value = response.data?.total || clinicRoomList.value.length || 0
} else {
ElMessage.error(response.msg || '获取诊室列表失败')
}
})
.catch(error => {
console.error('获取诊室列表失败:', error)
ElMessage.error('获取诊室列表失败')
})
.finally(() => {
loading.value = false
})
}
// 查询按钮操作
function handleQuery() {
queryParams.pageNum = 1
getList()
}
// 重置按钮操作
function resetQuery() {
proxy.resetForm('queryRef')
queryParams.roomName = null
handleQuery()
}
// 新增按钮操作
function handleAdd() {
resetForm()
dialogType.value = 'add'
dialogTitle.value = '新增诊室'
dialogVisible.value = true
}
// 编辑按钮操作
function handleEdit(row) {
resetForm()
const id = row.id
getClinicRoomDetail(id)
.then(response => {
if (response.code === 200) {
Object.assign(form, response.data || row)
dialogType.value = 'edit'
dialogTitle.value = '编辑诊室'
dialogVisible.value = true
} else {
ElMessage.error(response.msg || '获取诊室详情失败')
}
})
.catch(error => {
console.error('获取诊室详情失败:', error)
ElMessage.error('获取诊室详情失败')
})
}
// 查看按钮操作
function handleView(row) {
resetForm()
const id = row.id
getClinicRoomDetail(id)
.then(response => {
if (response.code === 200) {
Object.assign(form, response.data || row)
dialogType.value = 'view'
dialogTitle.value = '查看诊室详情'
dialogVisible.value = true
} else {
ElMessage.error(response.msg || '获取诊室详情失败')
}
})
.catch(error => {
console.error('获取诊室详情失败:', error)
ElMessage.error('获取诊室详情失败')
})
}
// 删除按钮操作
function handleDelete(row) {
const id = row.id || row.ids
ElMessageBox.confirm('是否确认删除诊室ID为"' + id + '"的数据项?')
.then(() => {
return deleteClinicRoom(id)
})
.then(response => {
if (response.code === 200) {
ElMessage.success('删除成功')
getList()
} else {
ElMessage.error(response.msg || '删除失败')
}
})
.catch(() => {})
}
// 提交表单
function submitForm() {
formRef.value.validate(valid => {
if (valid) {
if (dialogType.value === 'edit') {
updateClinicRoom(form)
.then(response => {
if (response.code === 200) {
ElMessage.success('修改成功')
dialogVisible.value = false
getList()
} else {
ElMessage.error(response.msg || '修改失败')
}
})
.catch(error => {
console.error('修改失败:', error)
ElMessage.error('修改失败')
})
} else {
addClinicRoom(form)
.then(response => {
if (response.code === 200) {
ElMessage.success('新增成功')
dialogVisible.value = false
getList()
} else {
ElMessage.error(response.msg || '新增失败')
}
})
.catch(error => {
console.error('新增失败:', error)
ElMessage.error('新增失败')
})
}
}
})
}
// 取消按钮
function cancel() {
dialogVisible.value = false
resetForm()
}
// 重置表单
function resetForm() {
form.id = null
form.roomName = ''
form.department = ''
form.building = ''
form.floor = ''
form.roomNo = ''
form.isDisabled = false
form.remarks = ''
form.void = false
proxy.resetForm('formRef')
}
// 获取科室列表
function getDepartmentOptions() {
getDepartmentList()
.then(response => {
if (response.code === 200) {
// 处理不同的响应格式
if (Array.isArray(response.data)) {
departmentOptions.value = response.data
} else if (response.data?.data && Array.isArray(response.data.data)) {
departmentOptions.value = response.data.data
} else if (response.data?.records && Array.isArray(response.data.records)) {
departmentOptions.value = response.data.records
} else {
departmentOptions.value = []
}
} else {
console.warn('获取科室列表失败:', response.msg)
}
})
.catch(error => {
console.error('获取科室列表失败:', error)
})
}
// 页面加载时初始化
onMounted(() => {
getDepartmentOptions()
getList()
})
</script>
<style scoped lang="scss">
.app-container {
padding: 20px;
background-color: #f5f7fa;
}
.filter-form {
background-color: #fff;
padding: 20px;
border-radius: 4px;
margin-bottom: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
.clinic-room-table {
background-color: #fff;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
:deep(.el-table) {
.el-table__header-wrapper th {
background-color: #fafafa;
font-weight: 500;
}
}
:deep(.el-button--link) {
padding: 0;
margin: 0 5px;
}
// 响应式布局
@media (max-width: 768px) {
.filter-form {
:deep(.el-form-item) {
display: block;
margin-bottom: 16px;
}
:deep(.el-form-item__content) {
width: 100%;
}
}
.clinic-room-table {
overflow-x: auto;
}
}
</style>

View File

@@ -0,0 +1,611 @@
<template>
<div class="doctorschedule-container">
<div class="doctorschedule-header">
<h2 class="doctorschedule-title">医生排班</h2>
</div>
<div class="doctorschedule-content">
<!-- 筛选条件 -->
<div class="filter-condition">
<span class="filter-label">卫生机构</span>
<el-select v-model="filterParams.orgName" class="filter-select">
<el-option label="演示医院" value="演示医院"></el-option>
</el-select>
<span class="filter-label">科室名称</span>
<el-select v-model="filterParams.deptName" class="filter-select">
<el-option label="测试内科" value="测试内科"></el-option>
</el-select>
<span class="filter-label">开始日期</span>
<el-date-picker
v-model="filterParams.startDate"
type="date"
placeholder="选择日期"
class="filter-date-picker"
/>
<span class="filter-label">排班类型</span>
<div class="radio-group">
<el-radio v-model="filterParams.appointmentType" label="普通">普通</el-radio>
<el-radio v-model="filterParams.appointmentType" label="专家">专家</el-radio>
</div>
</div>
<!-- 排班表格 -->
<div class="schedule-table-container">
<!-- 按日期分组显示排班 -->
<div v-for="(dateGroup, index) in groupedSchedule" :key="index" class="daily-schedule">
<div class="daily-header">
<span class="date-text">{{ dateGroup.date }}</span>
<span class="weekday-text">{{ dateGroup.weekday }}</span>
</div>
<el-table :data="dateGroup.items" border style="width: 100%" class="schedule-table">
<el-table-column prop="timeSlot" label="时段" width="100"></el-table-column>
<el-table-column prop="doctorName" label="医生" width="120">
<template #default="scope">
<el-select
v-model="scope.row.doctorName"
placeholder="请选"
class="inline-select"
:disabled="!isEditMode"
>
<el-option label="张医生" value="张医生"></el-option>
<el-option label="李医生" value="李医生"></el-option>
<el-option label="王医生" value="王医生"></el-option>
<el-option label="赵医生" value="赵医生"></el-option>
</el-select>
</template>
</el-table-column>
<el-table-column prop="room" label="诊室" width="100">
<template #default="scope">
<el-select
v-model="scope.row.room"
placeholder="请选"
class="inline-select"
:disabled="!isEditMode"
>
<el-option label="诊室1" value="诊室1"></el-option>
<el-option label="诊室2" value="诊室2"></el-option>
<el-option label="诊室3" value="诊室3"></el-option>
<el-option label="诊室4" value="诊室4"></el-option>
</el-select>
</template>
</el-table-column>
<el-table-column prop="startTime" label="开始时间" width="120">
<template #default="scope">
<el-time-picker
v-model="scope.row.startTime"
type="time"
format="HH:mm"
value-format="HH:mm"
placeholder="选择开始时间"
:disabled="!isEditMode"
class="time-picker"
/>
</template>
</el-table-column>
<el-table-column prop="endTime" label="结束时间" width="120">
<template #default="scope">
<el-time-picker
v-model="scope.row.endTime"
type="time"
format="HH:mm"
value-format="HH:mm"
placeholder="选择结束时间"
:disabled="!isEditMode"
class="time-picker"
/>
</template>
</el-table-column>
<el-table-column prop="maxNumber" label="限号数量" width="80">
<template #default="scope">
<el-input
v-model="scope.row.maxNumber"
type="number"
:disabled="!isEditMode"
/>
</template>
</el-table-column>
<el-table-column prop="record" label="号源记录" width="80">
<template #default="scope">
<el-icon
@click="handleViewRecord(scope.row)"
class="record-icon"
title="查看号源记录"
>
<View />
</el-icon>
</template>
</el-table-column>
<el-table-column prop="appointmentItem" label="挂号项目" width="120">
<template #default="scope">
<el-select
v-model="scope.row.appointmentItem"
placeholder="请选"
class="inline-select"
:disabled="!isEditMode"
>
<el-option label="挂号费 50" value="挂号费 50"></el-option>
<el-option label="一般诊疗费 10" value="一般诊疗费 10"></el-option>
<el-option label="主任医师 27" value="主任医师 27"></el-option>
<el-option label="副主任 15" value="副主任 15"></el-option>
</el-select>
</template>
</el-table-column>
<el-table-column prop="registrationFee" label="挂号费(元)" width="100"></el-table-column>
<el-table-column prop="clinicItem" label="诊查项目" width="150">
<template #default="scope">
<el-select
v-model="scope.row.clinicItem"
placeholder="请选择诊查项目"
class="inline-select"
:disabled="!isEditMode"
>
<el-option label="常规诊查" value="常规诊查"></el-option>
<el-option label="专科诊查" value="专科诊查"></el-option>
<el-option label="特殊诊查" value="特殊诊查"></el-option>
<el-option label="专家诊查" value="专家诊查"></el-option>
</el-select>
</template>
</el-table-column>
<el-table-column prop="treatmentFee" label="诊疗费(元)" width="100"></el-table-column>
<el-table-column prop="online" label="线上" width="60">
<template #default="scope">
<el-checkbox v-model="scope.row.online" :disabled="!isEditMode"></el-checkbox>
</template>
</el-table-column>
<el-table-column prop="stopClinic" label="停诊" width="60">
<template #default="scope">
<el-checkbox v-model="scope.row.stopClinic" :disabled="!isEditMode"></el-checkbox>
</template>
</el-table-column>
<el-table-column prop="stopReason" label="停诊原因" width="150">
<template #default="scope">
<el-input
v-model="scope.row.stopReason"
:placeholder="scope.row.stopClinic ? '请输入停诊原因' : ''"
class="inline-input"
:disabled="!isEditMode || !scope.row.stopClinic"
></el-input>
</template>
</el-table-column>
<el-table-column label="操作" width="150" fixed="right">
<template #default="scope">
<el-button
type="primary"
size="small"
@click="handleAddSchedule(scope.row)"
:disabled="!isEditMode"
>
添加
</el-button>
<el-button
type="danger"
size="small"
@click="handleDeleteSchedule(scope.row)"
:disabled="!isEditMode"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
<!-- 底部操作按钮 -->
<div class="bottom-buttons">
<el-button type="primary" @click="handleSave" :disabled="!isEditMode">确定</el-button>
<el-button @click="handleCancel">取消</el-button>
</div>
</div>
<!-- 号源记录对话框 -->
<el-dialog
v-model="recordDialogVisible"
title="号源记录"
width="30%"
:close-on-click-modal="true"
>
<div class="appointment-records">
<div class="record-item" v-for="record in appointmentRecords" :key="record.index">
<span class="record-time">{{ record.time }}</span>
</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="recordDialogVisible = false">确定</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="DoctorSchedule">
import { ref, onMounted, computed, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage, ElMessageBox, ElDialog } from 'element-plus'
import { View } from '@element-plus/icons-vue'
// 路由和导航
const route = useRoute()
const router = useRouter()
// 筛选参数
const filterParams = ref({
orgName: '演示医院',
deptName: '测试内科',
startDate: new Date('2025-12-01'),
appointmentType: '普通'
})
// 编辑模式控制
const isEditMode = computed(() => {
return route.query.mode === 'edit'
})
// 排班列表数据
const scheduleList = ref([])
// 按日期分组的排班数据
const groupedSchedule = computed(() => {
// 按日期分组
const groups = {}
scheduleList.value.forEach(item => {
if (!groups[item.date]) {
groups[item.date] = {
date: item.date,
weekday: item.weekday,
items: []
}
}
groups[item.date].items.push(item)
})
// 转换为数组
return Object.values(groups)
})
// 生成一周排班数据
const generateWeekSchedule = (startDate) => {
const days = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
const timeSlots = [
{ label: '上午', startTime: '08:00', endTime: '12:00' },
{ label: '下午', startTime: '14:30', endTime: '18:00' }
]
const schedule = []
// 生成一周7天的数据
for (let i = 0; i < 7; i++) {
const currentDate = new Date(startDate)
currentDate.setDate(startDate.getDate() + i)
const dateStr = currentDate.toISOString().split('T')[0]
const weekday = days[currentDate.getDay()]
// 每个时间段生成一条记录
timeSlots.forEach(slot => {
schedule.push({
id: `${dateStr}-${slot.label}`,
date: dateStr,
weekday: weekday,
timeSlot: slot.label,
startTime: slot.startTime,
endTime: slot.endTime,
doctorName: '',
room: '',
maxNumber: '',
appointmentItem: '',
registrationFee: '',
clinicItem: '',
treatmentFee: '',
online: true,
stopClinic: false,
stopReason: ''
})
})
}
return schedule
}
// 初始化数据
const initData = () => {
// 从路由参数获取科室ID
const deptId = route.params.deptId
console.log('科室ID:', deptId)
// 生成排班数据
scheduleList.value = generateWeekSchedule(filterParams.value.startDate)
}
// 添加排班
const handleAddSchedule = (row) => {
ElMessage.info('添加排班功能待实现')
}
// 删除排班
const handleDeleteSchedule = (row) => {
ElMessage.info('删除排班功能待实现')
}
// 号源记录对话框相关
const recordDialogVisible = ref(false)
const currentRow = ref(null)
const appointmentRecords = ref([])
// 计算号源记录
const calculateAppointmentRecords = (row) => {
const { startTime, endTime, maxNumber } = row
// 将时间转换为分钟数
const [startHour, startMinute] = startTime.split(':').map(Number)
const [endHour, endMinute] = endTime.split(':').map(Number)
const startTotalMinutes = startHour * 60 + startMinute
const endTotalMinutes = endHour * 60 + endMinute
// 计算总时长和间隔
const totalDuration = endTotalMinutes - startTotalMinutes
const interval = Math.floor(totalDuration / maxNumber)
// 生成号源记录
const records = []
for (let i = 0; i < maxNumber; i++) {
const minutes = startTotalMinutes + i * interval
const hour = Math.floor(minutes / 60).toString().padStart(2, '0')
const minute = (minutes % 60).toString().padStart(2, '0')
records.push({
index: i + 1,
time: `${hour}:${minute}`
})
}
return records
}
// 查看号源记录
const handleViewRecord = (row) => {
// 验证开始时间、结束时间和限号数量
if (!row.startTime || !row.endTime || !row.maxNumber) {
ElMessageBox.confirm('请先设置开始时间、结束时间和限号数量', '', {
confirmButtonText: '确定',
type: 'warning',
showCancelButton: false
})
return
}
// 计算号源记录
currentRow.value = row
appointmentRecords.value = calculateAppointmentRecords(row)
recordDialogVisible.value = true
}
// 保存排班
const handleSave = () => {
ElMessage.success('排班保存成功')
// 返回上一页
router.back()
}
// 取消操作
const handleCancel = () => {
// 返回上一页
router.back()
}
// 页面加载时初始化数据
onMounted(() => {
initData()
})
// 监听路由参数变化,重新初始化数据
watch(
() => [route.params.deptId, route.query.mode],
() => {
initData()
},
{ deep: true }
)
</script>
<style scoped lang="scss">
.doctorschedule-container {
width: 100%;
height: 100%;
padding: 20px;
background-color: #f5f7fa;
}
.doctorschedule-header {
margin-bottom: 20px;
}
.doctorschedule-title {
font-size: 20px;
font-weight: 600;
color: #333;
margin: 0;
}
.doctorschedule-content {
background-color: #fff;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
.filter-condition {
display: flex;
align-items: center;
margin-bottom: 20px;
gap: 16px;
}
.filter-label {
font-weight: 500;
white-space: nowrap;
}
.filter-select {
width: 150px;
}
.filter-date-picker {
width: 200px;
}
.radio-group {
display: flex;
align-items: center;
gap: 10px;
}
.schedule-table-container {
margin-bottom: 20px;
width: 100%;
overflow-x: auto;
}
.daily-schedule {
margin-bottom: 20px;
border: 1px solid #ebeef5;
border-radius: 4px;
overflow: hidden;
width: 100%;
}
.daily-header {
background-color: #f5f7fa;
padding: 10px 15px;
border-bottom: 1px solid #ebeef5;
display: flex;
align-items: center;
gap: 15px;
font-size: 16px;
font-weight: 600;
}
.date-text {
color: #333;
}
.weekday-text {
color: #606266;
font-weight: normal;
}
.schedule-table {
width: 100% !important;
min-width: 100% !important;
:deep(.el-table__header-wrapper) {
width: 100% !important;
border-top: none;
}
:deep(.el-table__body-wrapper) {
width: 100% !important;
}
:deep(.el-table__header-wrapper th.el-table__cell),
:deep(.el-table__body-wrapper td.el-table__cell) {
text-align: center;
padding: 8px 0;
}
/* 确保表格容器填满 */
:deep(.el-table__inner-wrapper) {
width: 100% !important;
}
/* 确保表格本身填满 */
:deep(.el-table__body) {
width: 100% !important;
}
/* 确保表格列正确分配宽度 */
:deep(.el-table__header) {
width: 100% !important;
}
:deep(.el-table__header tr),
:deep(.el-table__body tr) {
width: 100% !important;
}
/* 确保表格容器的最小宽度与内容匹配 */
:deep(.el-table) {
width: 100% !important;
min-width: 100% !important;
}
}
.inline-select {
width: 100%;
}
.inline-input {
width: 100%;
}
.time-picker {
width: 100%;
}
.record-icon {
font-size: 18px;
color: #409eff;
cursor: pointer;
transition: color 0.2s;
}
.record-icon:hover {
color: #66b1ff;
}
.bottom-buttons {
display: flex;
justify-content: flex-end;
gap: 16px;
}
/* 号源记录对话框样式 */
.appointment-records {
max-height: 300px;
overflow-y: auto;
padding: 10px 0;
}
.record-item {
padding: 8px 0;
border-bottom: 1px solid #f0f0f0;
}
.record-item:last-child {
border-bottom: none;
}
.record-time {
font-size: 16px;
color: #333;
}
.dialog-footer {
text-align: center;
}
/* 隐藏数字输入框的增减按钮 */
:deep(.el-input__inner[type="number"]) {
-moz-appearance: textfield;
}
:deep(.el-input__inner[type="number"])::-webkit-outer-spin-button,
:deep(.el-input__inner[type="number"])::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
</style>

View File

@@ -1,7 +1,7 @@
<template>
<div class="appoinmentmanage-container">
<div class="appoinmentmanage-header">
<h2 class="appoinmentmanage-title">预约管理</h2>
<h2 class="appoinmentmanage-title">科室名称管理</h2>
</div>
<div class="appoinmentmanage-content">
@@ -124,6 +124,7 @@
<script setup name="AppoinmentManage">
import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage, ElDialog, ElSelect, ElOption, ElInput, ElForm, ElFormItem } from 'element-plus'
import { EditPen, View, DocumentRemove } from '@element-plus/icons-vue'
import { listDept, searchDept } from '@/api/appoinmentmanage/dept'
@@ -254,14 +255,25 @@ const handleAppointmentSettingCancel = () => {
appointmentSettingDialog.value = false
}
// 路由和导航
const router = useRouter()
// 编辑
const handleEdit = (row) => {
ElMessage.info(`编辑科室: ${row.deptName}`)
// 导航到医生排班页面传递科室ID和编辑模式
router.push({
path: `/appoinmentmanage/doctorschedule/${row.id}`,
query: { mode: 'edit' }
})
}
// 查看
const handleView = (row) => {
ElMessage.info(`查看科室: ${row.deptName}`)
// 导航到医生排班页面传递科室ID和查看模式
router.push({
path: `/appoinmentmanage/doctorschedule/${row.id}`,
query: { mode: 'view' }
})
}
// 分页大小变化

View File

@@ -103,7 +103,7 @@
:data="deviceList"
@selection-change="handleSelectionChange"
width="90%"
>
/>
<el-table v-loading="loading" :data="deviceList" @selection-change="handleSelectionChange" width="90%" border resizable-column>
<el-table-column type="selection" width="50" align="center" />
<el-table-column

View File

@@ -46,21 +46,6 @@
/>
</el-select>
</el-form-item>
<el-form-item label="诊断类型" prop="typeCode">
<el-select
v-model="queryParams.typeCode"
placeholder="请选择"
style="width: 240px"
clearable
>
<el-option
v-for="dict in condition_type_code"
:key="dict.value"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
<!-- <el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
@@ -101,84 +86,6 @@
</el-col> -->
</el-row>
<el-table v-loading="loading" :data="diseaseList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<el-table-column label="编码" align="center" key="conditionCode" prop="conditionCode" />
<el-table-column
label="名称"
align="center"
key="name"
prop="name"
:show-overflow-tooltip="true"
/>
<el-table-column
label="疾病分类"
align="center"
key="sourceEnum_enumText"
prop="sourceEnum_enumText"
:show-overflow-tooltip="true"
/>
<!-- <el-table-column
label="拼音助记码"
align="center"
key="pyStr"
prop="pyStr"
:show-overflow-tooltip="true"
/> -->
<el-table-column
label="类型"
align="center"
key="typeCode_dictText"
prop="typeCode_dictText"
:show-overflow-tooltip="true"
/>
<el-table-column
label="医保编码 "
align="center"
key="ybNo"
prop="ybNo"
:show-overflow-tooltip="true"
/>
<!-- <el-table-column
label="医保标记"
align="center"
key="ybMatchFlag"
prop="ybMatchFlag_enumText"
/>
<el-table-column
label="医保对码标志"
align="center"
key="ybMatchFlag"
prop="ybMatchFlag_enumText"
/> -->
<el-table-column
label="状态"
align="center"
key="statusEnum_enumText"
prop="statusEnum_enumText"
width="160"
/>
<el-table-column
label="描述"
align="center"
key="description"
prop="description"
width="160"
/>
<el-table-column
label="操作"
align="center"
width="150"
class-name="small-padding fixed-width"
>
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
>编辑</el-button
>
</template>
</el-table-column>
</el-table>
<pagination
<!-- 添加外层滚动容器确保表格可以水平滚动 -->
<div class="table-scroll-container">
<!-- 移除style="width: 100%"让Element UI表格根据内容自动调整 -->
@@ -304,7 +211,7 @@
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="诊断类型" prop="typeCode">
<el-form-item label="类型" prop="typeCode">
<el-select v-model="form.typeCode" placeholder="请选择" clearable>
<el-option
v-for="dict in condition_type_code"

View File

@@ -350,7 +350,6 @@
</template>
<script setup name="PatientAddDialog">
import { watch } from 'vue';
import { watch, defineProps } from "vue";
import pcas from 'china-division/dist/pcas-code.json';
import { addPatient, patientlLists, getOutpatientRegistrationList } from './outpatientregistration';

View File

@@ -765,8 +765,6 @@ const patientInfoList = ref(undefined);
// 费用性质
const contractList = ref(undefined);
// const locationOptions = ref(undefined); // 地点树选项
const doctorList = ref(undefined); // 医生选项
const healthcareList = ref([]); // 挂号项目选项
const doctorList = ref(undefined); // 医生选项(过滤后的)
const allDoctorList = ref(undefined); // 所有医生选项(用于过滤)
const healthcareList = ref(undefined); // 挂号项目选项

View File

@@ -212,25 +212,25 @@ watch(
);
getList();
function getList() {
queryParams.value.organizationId = props.patientInfo.orgId;
getAdviceBaseInfo(queryParams.value).then((res) => {
if (res.data.records.length > 0) {
adviceBaseList.value = res.data.records.filter((item) => {
if (item.adviceType == 1 || item.adviceType == 2) {
return handleQuantity(item) != 0;
} else {
return true;
}
});
total.value = res.data.total;
nextTick(() => {
currentIndex.value = 0;
// adviceBaseRef.value.setCurrentRow(adviceBaseList.value[0]);
});
}
});
}
// function getList() {
// queryParams.value.organizationId = props.patientInfo.orgId;
// getAdviceBaseInfo(queryParams.value).then((res) => {
// if (res.data.records.length > 0) {
// adviceBaseList.value = res.data.records.filter((item) => {
// if (item.adviceType == 1 || item.adviceType == 2) {
// return handleQuantity(item) != 0;
// } else {
// return true;
// }
// });
// total.value = res.data.total;
// nextTick(() => {
// currentIndex.value = 0;
// // adviceBaseRef.value.setCurrentRow(adviceBaseList.value[0]);
// });
// }
// });
// }
// 从priceList列表中获取价格
function getPriceFromInventory(row) {
if (row.priceList && row.priceList.length > 0) {

View File

@@ -219,6 +219,7 @@ const templateName = ref('');
// 事件
const emits = defineEmits(['save']);
const { proxy } = getCurrentInstance();
console.log('EMR组件初始化proxy:', proxy);
// 监听表单变化
watch(
@@ -325,16 +326,107 @@ function cancel() {
// 暴露方法给父组件
defineExpose({
getDetail(encounterId) {
getEmrDetail(encounterId).then((res) => {
if (res.data) {
try {
form.value = JSON.parse(res.data.contextJson) || {};
} catch (e) {
console.log('开始获取病历详情encounterId:', encounterId);
// 立即初始化form.value为空对象确保页面有内容显示
form.value = {};
// 检查API函数是否存在
if (typeof getEmrDetail !== 'function') {
console.error('getEmrDetail函数未定义');
if (proxy) {
proxy.$modal.msgError('获取病历详情失败API函数未定义');
}
emits('save', true);
return;
}
// 添加超时处理,防止请求一直挂起
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => {
reject(new Error('获取病历详情请求超时'));
}, 10000); // 10秒超时
});
// 使用Promise.race处理正常请求和超时
Promise.race([getEmrDetail(encounterId), timeoutPromise])
.then((res) => {
console.log('获取病历详情成功,返回完整数据:', JSON.stringify(res, null, 2));
// 检查响应是否有效
if (!res) {
console.error('API返回结果为空');
if (proxy) {
proxy.$modal.msgError('获取病历详情失败API返回结果为空');
}
return;
}
console.log('res存在类型:', typeof res);
console.log('res的属性:', Object.keys(res));
// 检查响应码
if (res.code !== 200) {
console.error('API返回错误代码:', res.code);
if (proxy) {
proxy.$modal.msgError('获取病历详情失败:' + (res.msg || '未知错误'));
}
return;
}
// 检查数据是否存在
if (!res.data) {
console.log('res.data为空使用默认值');
return;
}
console.log('res.data存在类型:', typeof res.data);
console.log('res.data的属性:', Object.keys(res.data));
// 处理contextJson
try {
if (res.data.contextJson) {
console.log('contextJson存在值:', res.data.contextJson);
console.log('contextJson类型:', typeof res.data.contextJson);
// 检查contextJson类型
if (typeof res.data.contextJson === 'string') {
// 尝试解析JSON字符串
const parsedData = JSON.parse(res.data.contextJson);
// 确保解析结果是对象
if (typeof parsedData === 'object' && parsedData !== null) {
form.value = parsedData;
console.log('解析后的病历数据:', JSON.stringify(form.value, null, 2));
} else {
form.value = {};
console.error('contextJson解析结果不是有效对象:', parsedData);
}
} else if (typeof res.data.contextJson === 'object') {
// 如果已经是对象,直接使用
form.value = res.data.contextJson;
console.log('直接使用contextJson作为对象:', JSON.stringify(form.value, null, 2));
} else {
form.value = {};
console.error('contextJson类型无效:', typeof res.data.contextJson);
}
} else {
console.log('contextJson为空使用默认值');
}
} catch (e) {
form.value = {};
console.error('病历数据解析失败:', e);
console.error('解析失败的contextJson值:', res.data.contextJson);
if (proxy) {
proxy.$modal.msgError('病历数据解析失败');
}
}
emits('save', true);
})
.catch((error) => {
// 处理API调用失败或超时的情况
console.error('获取病历详情失败:', error);
if (proxy) {
proxy.$modal.msgError('获取病历详情失败:' + (error.message || '未知错误'));
}
});
},

View File

@@ -20,16 +20,16 @@
<el-icon
class="delete-icon"
title="删除处方单"
@click="handleDeletePrescriptionClick(index)"
:class="{ 'disabled-icon': isPrescriptionDeletable(index) !== true }"
@click="handleDeletePrescriptionClick(pIndex)"
:class="{ 'disabled-icon': isPrescriptionDeletable(pIndex) !== true }"
style="font-size: 20px !important; margin-left: 10px; color: #f56c6c"
>
<minus />
</el-icon>
</div>
<div class="summary">
<span class="summary-item">药品数: {{ getPrescriptionMedicineCount(index) }}</span>
<span class="summary-item">总价: ¥ {{ getPrescriptionTotalPrice(index) }}</span>
<span class="summary-item">药品数: {{ getPrescriptionMedicineCount(pIndex) }}</span>
<span class="summary-item">总价: ¥ {{ getPrescriptionTotalPrice(pIndex) }}</span>
</div>
</div>
<div>
@@ -202,7 +202,6 @@
<el-form-item
label="数量"
prop="minUnitQuantity"
prop="minUnitQuantity"
class="required-field"
data-prop="minUnitQuantity"
>
@@ -463,7 +462,6 @@ const unitCodeList = ref([]);
const adviceTableRef = ref([]);
const organization = ref([]);
const conditionDefinitionId = ref('');
const encounterDiagnosisId = ref('');
const diagnosisName = ref('');
const diagnosisInfo = ref({});
const rateCode = ref('');
@@ -572,7 +570,10 @@ function getList() {
}
function getListInfo(addNewRow) {
// 确保isAdding变量存在
if (typeof isAdding !== 'undefined') {
isAdding.value = false;
}
// 确保有患者信息
if (!props.patientInfo || !props.patientInfo.encounterId) {
@@ -582,13 +583,17 @@ function getListInfo(addNewRow) {
getTcmAdviceList({ encounterId: props.patientInfo.encounterId }).then((res) => {
if (res && res.data && Array.isArray(res.data)) {
prescriptionList.value = res.data.map((item) => {
// 清空当前处方列表
tcmPrescriptionList.value = [];
// 处理返回的数据
res.data.forEach((item) => {
try {
// 解析contentJson获取完整的医嘱数据
const contentData = item.contentJson ? JSON.parse(item.contentJson) : {};
// 合并基础信息和contentJson中的详细信息
return {
// 创建一个新的处方对象
const newPrescription = {
...item,
...contentData,
// 确保关键显示字段存在
@@ -598,11 +603,14 @@ function getListInfo(addNewRow) {
diagnosisName: contentData.diagnosisName || item.diagnosisName || '',
positionName: contentData.positionName || item.positionName || '',
doseUnitCode_dictText: contentData.doseUnitCode_dictText || item.doseUnitCode_dictText || '',
chineseHerbsDoseQuantity: contentData.chineseHerbsDoseQuantity || item.chineseHerbsDoseQuantity || ''
chineseHerbsDoseQuantity: contentData.chineseHerbsDoseQuantity || item.chineseHerbsDoseQuantity || '',
prescriptionList: [contentData]
};
// 添加到处方列表
tcmPrescriptionList.value.push(newPrescription);
} catch (error) {
console.error('解析医嘱数据失败:', error, '数据项:', item);
return item; // 出错时返回原始数据
}
});
@@ -614,11 +622,11 @@ function getListInfo(addNewRow) {
}
} else {
console.error('获取医嘱列表失败或数据格式错误:', res);
prescriptionList.value = [];
tcmPrescriptionList.value = [];
}
}).catch(error => {
console.error('获取医嘱列表异常:', error);
prescriptionList.value = [];
tcmPrescriptionList.value = [];
});
tcmDiagnosisList.value = getFromDiagnosis(props.patientInfo.encounterId);
@@ -771,7 +779,8 @@ function handleDeletePrescriptionClick(prescriptionIndex) {
}
// 检查是否有已签发的药品
const hasChargedItems = prescriptionList.value.some(item => item.statusEnum === 2);
const prescription = tcmPrescriptionList.value[prescriptionIndex];
const hasChargedItems = prescription.prescriptionList.some(item => item.statusEnum === 2);
if (hasChargedItems) {
proxy.$modal.msgWarning('该处方单已收费,不能删除');
return;
@@ -795,16 +804,18 @@ function isPrescriptionDeletable(prescriptionIndex) {
}
// 检查是否有已签发的药品
const hasChargedItems = prescriptionList.value.some(item => item.statusEnum === 2);
const hasChargedItems = tcmPrescriptionList.value.some(item =>
item.prescriptionList && item.prescriptionList.some(med => med.statusEnum === 2)
);
return !hasChargedItems;
}
// 计算处方总价
function getPrescriptionTotalPrice(prescriptionIndex) {
const prescription = prescriptionList.value[prescriptionIndex];
const prescription = tcmPrescriptionList.value[prescriptionIndex];
let totalPrice = 0;
if (prescription && prescription.prescriptionDetailsList) {
prescription.prescriptionDetailsList.forEach(item => {
if (prescription && prescription.prescriptionList) {
prescription.prescriptionList.forEach(item => {
// 使用decimal.js确保精度计算
const quantity = new Decimal(item.minUnitQuantity || 0);
const unitPrice = new Decimal(item.unitPrice || 0);
@@ -816,9 +827,11 @@ function getPrescriptionTotalPrice(prescriptionIndex) {
// 获取处方中的药品数量
function getPrescriptionMedicineCount(prescriptionIndex) {
// 这里需要根据实际的业务逻辑来计算
// 假设每个处方对应一组药品,这里简化处理
return prescriptionList.value.filter(item => item.statusEnum !== 2).length;
const prescription = tcmPrescriptionList.value[prescriptionIndex];
if (prescription && prescription.prescriptionList) {
return prescription.prescriptionList.length;
}
return 0;
}
/**
@@ -961,7 +974,9 @@ function handleDelete(pIndex) {
prescription.expandOrder = [];
prescription.isAdding = false;
adviceQueryParams.value.adviceType = undefined;
groupMarkers.value = getGroupMarkers(prescriptionList.value); // 删除行会出现组号混乱的情况,所以这里重新更新标记
// 删除行会出现组号混乱的情况,所以这里重新更新标记
const allPrescriptions = tcmPrescriptionList.value.flatMap(p => p.prescriptionList);
groupMarkers.value = getGroupMarkers(allPrescriptions);
}
@@ -1117,10 +1132,21 @@ function handleSaveSign(row, index) {
function handleSaveBatch() {
let saveList = prescriptionList.value
.filter((item) => {
return item.statusEnum == 1;
})
// 收集所有需要保存的处方项目
let saveList = [];
// 遍历所有处方
for (const prescription of tcmPrescriptionList.value) {
if (prescription.prescriptionList) {
// 检查处方是否有必填的付数
if (!prescription.chineseHerbsDoseQuantity || prescription.chineseHerbsDoseQuantity == 0) {
proxy.$modal.msgWarning('请输入付数');
return;
}
// 收集该处方下需要保存的项目
const itemsToSave = prescription.prescriptionList
.filter((item) => item.statusEnum == 1)
.map((item, index) => {
return {
...item,
@@ -1132,29 +1158,36 @@ function handleSaveBatch() {
patientId: props.patientInfo.patientId,
requestId: item.requestId,
groupId: item.groupId ? item.groupId : timestamp.toString(),
chineseHerbsDoseQuantity: prescription.chineseHerbsDoseQuantity,
dbOpType: item.requestId ? '2' : '1',
};
});
// 将项目添加到保存列表
saveList = saveList.concat(itemsToSave);
}
}
// 检查是否有可保存的项目
if (saveList.length == 0) {
proxy.$modal.msgWarning('当前没有可保存医嘱');
return;
}
if (
prescription.chineseHerbsDoseQuantity == undefined ||
prescription.chineseHerbsDoseQuantity == 0
) {
proxy.$modal.msgWarning('请输入付数');
return;
}
// 保存处方
saveTcmAdvice({ adviceSaveList: saveList }).then((res) => {
if (res.code === 200) {
proxy.$modal.msgSuccess('保存成功');
getListInfo(true);
// 重置所有处方的nextId
tcmPrescriptionList.value.forEach(prescription => {
if (prescription.nextId) {
prescription.nextId = 1;
}
});
}
});
}
// 获取诊断列表

View File

@@ -3,43 +3,24 @@
<div style="width: 15%; height: 100%; border: 1px solid #eee; border-right: 0">
<div style="padding: 10px; border: 1px solid #eee; height: 50px; border-right: 0">
<span>现诊患者</span>
<el-badge
:value="waitCount > 0 ? waitCount : ''"
:max="10"
style="float: right; color: #409eff; cursor: pointer; margin-right: 10px"
>
<el-badge :value="waitCount > 0 ? waitCount : ''" :max="10"
style="float: right; color: #409eff; cursor: pointer; margin-right: 10px">
<span @click="openDrawer"> 患者队列 </span>
</el-badge>
</div>
<div style="width: 100%; padding: 10px">
<el-input
v-model="queryParams.searchKey"
placeholder="请输入患者名"
clearable
style="width: 100%; margin-bottom: 10px"
@keyup.enter="getPatientList"
>
<el-input v-model="queryParams.searchKey" placeholder="请输入患者名" clearable
style="width: 100%; margin-bottom: 10px" @keyup.enter="getPatientList">
<template #append>
<el-button icon="Search" @click="getPatientList" />
</template>
</el-input>
<el-date-picker
v-model="registerTime"
@change="handleTimeChange"
type="date"
style="width: 100%; margin-bottom: 10px"
:clearable="false"
placeholder="挂号时间"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
/>
<el-date-picker v-model="registerTime" @change="handleTimeChange" type="daterange"
style="width: 100%; margin-bottom: 10px" :clearable="false" placeholder="挂号时间" format="YYYY-MM-DD"
value-format="YYYY-MM-DD" />
<el-scrollbar height="700px">
<div
v-for="(item, index) in patientList"
:class="item.active ? 'patient-card actived' : 'patient-card'"
:key="item.id"
@click="handleCardClick(item, index)"
>
<div v-for="(item, index) in patientList" :class="item.active ? 'patient-card actived' : 'patient-card'"
:key="item.id" @click="handleCardClick(item, index)">
<div class="main-info-container">
<!-- <el-avatar
:size="30"
@@ -78,8 +59,8 @@
</div>
<div class="disabled-wrapper" style="width: 85%; border: 1px solid #eee; position: relative">
<div style="padding: 10px; border: 1px solid #eee; height: 50px; border-left: 0">
<el-descriptions :column="5" class="patient-info-descriptions">
<el-descriptions-item label="患者信息:" width="420">
<el-descriptions :column="4">
<el-descriptions-item label="患者信息:" width="150">
{{
Object.keys(patientInfo).length !== 0
? patientInfo.patientName +
@@ -88,53 +69,19 @@
' / ' +
patientInfo.genderEnum_enumText +
' / ' +
patientInfo.contractName +
'/' +
patientInfo.phone
patientInfo.contractName
: '-'
}}
</el-descriptions-item>
<el-descriptions-item label="挂号时间:" width="300">
<el-descriptions-item label="挂号时间:" width="150">
{{ Object.keys(patientInfo).length !== 0 ? formatDate(patientInfo.registerTime) : '-' }}
</el-descriptions-item>
<el-descriptions-item label="医生:" width="250">
{{ userStore.nickName }}
</el-descriptions-item>
<el-descriptions-item label="" width="300">
<el-button type="primary" plain @click.stop="handleFinish(patientInfo.encounterId)">
完诊
</el-button>
<el-button type="primary" plain @click.stop="handleLeave(patientInfo.encounterId)">
暂离
</el-button>
<el-button type="primary" plain @click.stop="handleRefund(patientInfo.encounterId)">
退费
</el-button>
<el-button
type="primary"
plain
@click.stop="getEnPrescription(patientInfo.encounterId)"
>
处方单
</el-button>
<el-button
type="primary"
plain
@click.stop="
() => {
openDialog = true;
}
"
>
办理住院
</el-button>
</el-descriptions-item>
<el-descriptions-item label="医生:" width="150">{{
userStore.name
}}</el-descriptions-item>
<el-descriptions-item label="" width="350">
<!-- 初诊 / 复诊 按钮 -->
<el-radio v-model="visitType" label="FIRST" :disabled="visitTypeDisabled">初诊</el-radio>
<el-radio v-model="visitType" label="FIRST" :disabled="visitTypeDisabled">初诊</el-radio>
<el-radio v-model="visitType" label="FOLLOW_UP" :disabled="visitTypeDisabled">复诊</el-radio>
<!-- 原有按钮 -->
@@ -147,84 +94,44 @@
<el-button type="primary" plain @click.stop="handleRefund(patientInfo.encounterId)">
退费
</el-button>
<el-button
type="primary"
plain
@click.stop="getEnPrescription(patientInfo.encounterId)"
>
<el-button type="primary" plain @click.stop="getEnPrescription(patientInfo.encounterId)">
处方单
</el-button>
<el-button
type="primary"
plain
@click.stop="openDialog = true"
>
<el-button type="primary" plain @click.stop="openDialog = true">
办理住院
</el-button>
<el-button
type="primary"
plain
@click.stop="handleCancelEncounter"
>
<el-button type="primary" plain @click.stop="handleCancelEncounter">
取消接诊
</el-button>
</el-descriptions-item>
</el-descriptions-item>
</el-descriptions>
</div>
<div style="padding: 10px">
<el-tabs
type="card"
style="width: 100%; height: 100%"
v-loading="loading"
v-model="activeTab"
@tab-change="handleClick(activeTab)"
>
<el-tab-pane label="门诊病历" name="hospitalizationEmr">
<hospitalizationEmr
:patientInfo="patientInfo"
:activeTab="activeTab"
@emrSaved="handleEmrSaved"
/>
</el-tab-pane>
<el-tabs type="card" style="width: 100%; height: 100%" v-loading="loading" v-model="activeTab"
@tab-change="handleClick(activeTab)">
<el-tab-pane label="病历" name="emr">
<Emr
:patientInfo="patientInfo"
ref="emrRef"
@save="
<Emr :patientInfo="patientInfo" ref="emrRef" @save="
(value) => {
saveStatus = value;
}
"
:visitType="visitType"
:firstVisitDate="firstVisitDate"
/>
" :visitType="visitType" :firstVisitDate="firstVisitDate" />
</el-tab-pane>
<el-tab-pane label="诊断" name="diagnosis">
<Diagnosis
:patientInfo="patientInfo"
ref="diagnosisRef"
@diagnosisSave="
<Diagnosis :patientInfo="patientInfo" ref="diagnosisRef" @diagnosisSave="
(value) => {
saveStatus = value;
}
"
/>
" />
</el-tab-pane>
<el-tab-pane label="医嘱" name="prescription">
<prescriptionlist
:patientInfo="patientInfo"
ref="prescriptionRef"
:activeTab="activeTab"
:outpatientEmrSaved="outpatientEmrSaved"
/>
<prescriptionlist :patientInfo="patientInfo" ref="prescriptionRef" :activeTab="activeTab" />
</el-tab-pane>
<el-tab-pane label="中医" name="tcm">
<tcmAdvice :patientInfo="patientInfo" ref="tcmRef" />
</el-tab-pane>
<!-- <el-tab-pane label="电子处方" name="eprescription">
<el-tab-pane label="电子处方" name="eprescription">
<eprescriptionlist :patientInfo="patientInfo" ref="eprescriptionRef" />
</el-tab-pane>
-->
</el-tabs>
<div class="overlay" v-if="disabled"></div>
</div>
@@ -232,27 +139,15 @@
<el-drawer v-model="drawer" title="患者队列" direction="ltr" @open="handleOpen">
<PatientList ref="patientDrawerRef" @toCurrent="handleReceive" />
</el-drawer>
<RefundListDialog
:open="openRefundListDialog"
:encounterId="currentEncounterId"
@close="openRefundListDialog = false"
@refresh="() => prescriptionRef.getListInfo()"
/>
<HospitalizationDialog
:open="openDialog"
:patientInfo="patientInfo"
:encounterId="currentEncounterId"
@close="openDialog = false"
/>
<PrescriptionInfo
:open="openPrescriptionDialog"
:precriptionInfo="prescriptionInfo"
@close="openPrescriptionDialog = false"
/>
<RefundListDialog :open="openRefundListDialog" :encounterId="currentEncounterId"
@close="openRefundListDialog = false" />
<HospitalizationDialog :open="openDialog" :patientInfo="patientInfo" :encounterId="currentEncounterId"
@close="openDialog = false" />
<PrescriptionInfo :open="openPrescriptionDialog" :precriptionInfo="prescriptionInfo"
@close="openPrescriptionDialog = false" />
</div>
</template>
<script setup>
import hospitalizationEmr from './components/hospitalizationEmr/index.vue';
import Emr from './components/emr/emr.vue';
import {
getList,
@@ -267,14 +162,13 @@ import RefundListDialog from './components/prescription/refundListDialog.vue';
import PatientList from './components/patientList.vue';
import Diagnosis from './components/diagnosis/diagnosis.vue';
import PrescriptionInfo from './components/prescription/prescriptionInfo.vue';
// import eprescriptionlist from './components/eprescriptionlist.vue';
import eprescriptionlist from './components/eprescriptionlist.vue';
import HospitalizationDialog from './components/hospitalizationDialog.vue';
import tcmAdvice from './components/tcm/tcmAdvice.vue';
import { formatDate, formatDateStr } from '@/utils/index';
import useUserStore from '@/store/modules/user';
import { nextTick } from 'vue';
import { onBeforeRouteLeave } from 'vue-router';
import { updatePatientInfo } from './components/store/patient.js';
// // 监听路由离开事件
// onBeforeRouteLeave((to, from, next) => {
@@ -303,18 +197,15 @@ const openRefundListDialog = ref(false);
const openDialog = ref(false);
const openPrescriptionDialog = ref(false);
const saveStatus = ref(false);
const outpatientEmrSaved = ref(false); // 门诊病历保存状态
const currentEncounterId = ref('');
const emits = defineEmits(['click']);
// const activeTab = ref('emr');
const activeTab = ref('hospitalizationEmr');
const activeTab = ref('emr');
const patientList = ref([]);
const patientInfo = ref({});
const visitTypeDisabled = ref(false);
const prescriptionInfo = ref([]);
const registerTime = ref(formatDate(new Date()));
const registerTime = ref([formatDate(new Date()), formatDate(new Date())]);
const patientDrawerRef = ref();
const prescriptionRef = ref();
const tcmRef = ref();
@@ -328,41 +219,12 @@ const firstVisitDate = ref('');
const disabled = computed(() => {
return Object.keys(patientInfo.value).length === 0;
});
const shortcuts = [
{
text: '今天',
value: new Date(),
},
{
text: '昨天',
value: () => {
const date = new Date();
date.setDate(date.getDate() - 1);
return date;
},
},
{
text: '三天内',
value: () => {
const date = new Date();
date.setDate(date.getDate() - 3);
return date;
},
},
{
text: '一周内',
value: () => {
const date = new Date();
date.setDate(date.getDate() - 7);
return date;
},
},
];
// const eprescriptionRef = ref();
const eprescriptionRef = ref();
onMounted(() => {
getWaitPatient();
});
getPatientList();
// 获取现诊患者列表
function getPatientList() {
@@ -380,7 +242,7 @@ function setVisitType(type) {
visitType.value = type;
}
function checkPatientHistory(patient) {
// 重置状态
// 重置状态
visitTypeDisabled.value = false;
firstVisitDate.value = '';
@@ -451,9 +313,9 @@ function handleClick(tab) {
case 'tcm':
tcmRef.value.getDiagnosisInfo();
break;
// case 'eprescription':
// eprescriptionRef.value.getList();
// break;
case 'eprescription':
eprescriptionRef.value.getList();
break;
}
// if (tab != 'emr') {
// if (!saveStatus.value) {
@@ -471,11 +333,6 @@ function handleClick(tab) {
// 查看本次就诊处方单从医嘱Tab页获取已开立的处方单信息
function getEnPrescription(encounterId) {
getEnPrescriptionInfo({ encounterId: encounterId }).then((res) => {
console.log('处方单 res', res);
prescriptionInfo.value = res.data.records;
openPrescriptionDialog.value = true;
});
// 检查是否有选中的患者
if (!patientInfo.value || !patientInfo.value.encounterId) {
proxy.$modal.msgWarning('请先选择患者');
@@ -553,9 +410,6 @@ function handleCardClick(item, index) {
patient.active = patient.encounterId === item.encounterId;
});
patientInfo.value = item;
// 将患者信息保存到store中供hospitalizationEmr组件使用
updatePatientInfo(item);
activeTab.value = 'hospitalizationEmr';
// 优先使用数据库中保存的初复诊值
if (item.visitType) {
@@ -572,11 +426,17 @@ function handleCardClick(item, index) {
}
activeTab.value = 'emr';
nextTick(() => {
prescriptionRef.value.getListInfo();
tcmRef.value.getListInfo();
diagnosisRef.value.getList();
// eprescriptionRef.value.getList();
// 确保所有组件引用都已初始化
if (prescriptionRef.value) prescriptionRef.value.getListInfo();
if (tcmRef.value) tcmRef.value.getListInfo();
if (diagnosisRef.value) diagnosisRef.value.getList();
if (eprescriptionRef.value) eprescriptionRef.value.getList();
if (emrRef.value) {
emrRef.value.getDetail(item.encounterId);
} else {
console.error('emr组件未正确初始化');
proxy.$modal.msgError('病历组件加载失败,请刷新页面重试');
}
setTimeout(() => {
loading.value = false;
}, 200);
@@ -606,8 +466,8 @@ function handleFinish(encounterId) {
}
function handleTimeChange(value) {
queryParams.value.registerTimeSTime = value + ' 00:00:00';
queryParams.value.registerTimeETime = value + ' 23:59:59';
queryParams.value.registerTimeSTime = value[0] + ' 00:00:00';
queryParams.value.registerTimeETime = value[1] + ' 23:59:59';
getPatientList();
}
@@ -620,17 +480,12 @@ function handleReceive(row) {
getWaitPatient();
}
// 处理门诊病历保存成功事件
function handleEmrSaved(isSaved) {
outpatientEmrSaved.value = isSaved;
}
function openDrawer() {
drawer.value = true;
}
function handleCancelEncounter(){
proxy.$modal.confirm('您确定要取消病人本次的就诊记录吗?','提示信息',{
function handleCancelEncounter() {
proxy.$modal.confirm('您确定要取消病人本次的就诊记录吗?', '提示信息', {
confirmButtonText: '是(Y)',
cancelButtonText: '否(N)',
type: 'warning'
@@ -643,7 +498,7 @@ function handleCancelEncounter(){
getPatientList();
}
}).catch((error) => {
proxy.$modal.confirm('该病人本次就诊已经有业务产生,不能取消接诊!','提示信息',{
proxy.$modal.confirm('该病人本次就诊已经有业务产生,不能取消接诊!', '提示信息', {
confirmButtonText: '是(Y)',
type: 'warning'
});
@@ -655,16 +510,6 @@ function handleCancelEncounter(){
</script>
<style lang="scss" scoped>
// 患者信息
.patient-info-descriptions {
:deep(.el-descriptions__label) {
font-size: 16px !important;
}
:deep(.el-descriptions__content) {
font-size: 16px !important;
}
}
.patient-card {
width: 100%;
overflow: hidden;
@@ -817,6 +662,7 @@ function handleCancelEncounter(){
}
}
}
:deep(.el-tabs__header) {
padding: 0;
position: relative;
@@ -826,19 +672,23 @@ function handleCancelEncounter(){
:deep(.el-drawer__header) {
margin-bottom: 15px !important;
}
:deep(.el-drawer__body) {
padding: 10px !important;
}
.el-badge {
--el-badge-padding: 6px;
}
.disabled-wrapper .overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 999; /* 确保覆盖在内容上方 */
z-index: 999;
/* 确保覆盖在内容上方 */
cursor: not-allowed;
}
</style>

View File

@@ -85,7 +85,6 @@
</div>
</template>
<script setup lang='ts'>
import { is } from 'core-js/core/object'
import { getCurrentInstance, onBeforeMount, onMounted, reactive,ref } from 'vue'
// const { proxy } = getCurrentInstance();
const emits = defineEmits([])

View File

@@ -219,11 +219,11 @@ function getExpirationWarningCount() {
let chartInstance = null;
onActivated(() => {
getExpirationWarningCount();
// getExpirationWarningCount();
})
onMounted(() => {
getExpirationWarningCount();
// getExpirationWarningCount();
const ctx = document.getElementById('statsChart');
if (!ctx) return;

View File

@@ -3,7 +3,8 @@
* @Date: 2025-09-05 22:32:17
* @Description: 申请单 检验检查输血手术
-->
<template>
<template>
<div>
<div class="applicationForm-bottom-btn">
<el-button-group>
<el-button
@@ -52,13 +53,14 @@
</div>
</template>
</el-dialog>
</template>
</div>
</template>
<script setup>
import { getCurrentInstance, onBeforeMount, onMounted, reactive, ref, computed } from 'vue';
import BloodTransfusion from './bloodTransfusion';
import { patientInfo } from '../../../store/patient.js';
import Surgery from './surgery.vue';
import laboratoryTests from './laboratoryTests.vue';
import LaboratoryTests from './laboratoryTests.vue';
import MedicalExaminations from './medicalExaminations.vue';
const { proxy } = getCurrentInstance();
const emits = defineEmits([]);

View File

@@ -234,7 +234,8 @@ onMounted(() => {
}
// 获取医疗机构列表
getUserBindTenantList().then((res) => {
if (loginForm.value.username) {
getUserBindTenantList(loginForm.value.username).then((res) => {
tenantOptions.value = res.data.map(item => ({
label: item.tenantName,
value: item.id
@@ -245,6 +246,7 @@ onMounted(() => {
currentTenantName.value = tenantOptions.value[0].label;
}
});
}
});
function handleLogin() {
@@ -476,7 +478,10 @@ function handleUserName(value) {
//getCode();
getCookie();
getTenantList(loginForm.value.username);
// 只有当 username 存在时才获取租户列表
if (loginForm.value.username) {
getTenantList(loginForm.value.username);
}
</script>
<style>

View File

@@ -49,13 +49,17 @@
</div>
<div class="filter-item">
<label>科室</label>
<select>
<option value="">请选择科室</option>
<option value="内科">内科</option>
<option value="儿科">儿科</option>
<option value="外科">外科</option>
<option value="妇科">妇科</option>
</select>
<el-tree-select
placeholder="请选择科室"
:data="departments"
:props="{
value: 'name',
label: 'name',
children: 'children'
}"
value-key="name"
style="width: 100%;"
/>
</div>
<div class="filter-item">
<label>用户</label>
@@ -140,9 +144,10 @@
</template>
<script setup>
import { ref, computed } from 'vue';
import { useRouter } from 'vue-router';
import { ref, reactive, computed, onMounted } from 'vue';
import { useRouter, useRoute } from 'vue-router';
import { Edit, View, Delete } from '@element-plus/icons-vue';
import { getLocationTree } from '@/views/charge/outpatientregistration/components/outpatientregistration';
// 创建路由实例
const router = useRouter();
@@ -150,6 +155,46 @@ const router = useRouter();
// 侧边栏状态
const sidebarActive = ref(false);
// 科室数据
const departments = ref([]);
// 获取科室数据 - 与门诊挂号页面保持一致
function getDepartmentList() {
console.log('调用getLocationTree API...');
getLocationTree().then((response) => {
console.log('getLocationTree API完整返回:', response);
console.log('getLocationTree API数据结构:', JSON.stringify(response.data, null, 2));
// 检查数据结构并转换为适合el-tree-select的格式
if (Array.isArray(response.data)) {
// 直接使用数组数据
departments.value = response.data;
} else if (response.data && response.data.records) {
// 处理分页格式数据
departments.value = response.data.records;
} else if (response.data && response.data.rows) {
// 处理另一种分页格式数据
departments.value = response.data.rows;
} else {
console.error('API返回数据格式不符合预期:', response.data);
departments.value = [];
}
console.log('最终科室数据:', JSON.stringify(departments.value, null, 2));
}).catch((error) => {
console.error('获取科室数据失败:', error);
departments.value = [];
});
}
// 获取科室数据 - 与门诊挂号页面保持一致,在组件初始化时直接调用
getDepartmentList();
// 初始化数据
onMounted(() => {
// 其他初始化逻辑
});
// 表格数据
const tableData = ref([
{id: 2348, hospital: '演示医院', date: '2025-11-17', name: '血脂333', type: '检验套餐', level: '全院套餐', dept: '', user: '', amount: 40.00, fee: 0.00, total: 40.00, combined: '否', display: '是', enabled: '是', operator: '徐斌'},

File diff suppressed because it is too large Load Diff

View File

@@ -16,97 +16,147 @@
</el-tab-pane>
<el-tab-pane label="挂号处理" name="tab3">
<el-form ref="formRef" :model="formData" label-width="120px" class="config-form">
<el-form ref="formRef" :model="formData" label-width="150px" class="config-form compact-form">
<!-- 第一行 -->
<div class="form-row">
<el-form-item label="病历本费用(元)" prop="medicalRecordFee" style="margin-right: 20px;">
<el-input v-model="formData.medicalRecordFee" style="width: 180px" />
<el-form-item label="病历本费用(元)" prop="medicalRecordFee">
<el-input-number v-model="formData.medicalRecordFee" style="width: 150px" :controls-position="'right'" :step="1" :min="0" />
</el-form-item>
<el-form-item style="margin-left: 20px;">
<el-checkbox v-model="formData.medicalRecordFlag">病历费入账标志</el-checkbox>
<el-form-item label="" prop="medicalRecordFlag" checkbox-label>
<template #label>
<div class="checkbox-label-container">
<el-checkbox v-model="formData.medicalRecordFlag" style="margin-right: 8px;" />
<span>病历费入账标志</span>
</div>
</template>
</el-form-item>
</div>
<!-- 第二行 -->
<div class="form-row">
<el-form-item label="就诊卡费(元)" prop="patientCardFee" style="margin-right: 20px;">
<el-input v-model="formData.patientCardFee" style="width: 180px" />
<el-form-item label="就诊卡费(元)" prop="patientCardFee">
<el-input-number v-model="formData.patientCardFee" style="width: 150px" :controls-position="'right'" :step="1" :min="0" />
</el-form-item>
<el-form-item style="margin-left: 20px;">
<el-checkbox v-model="formData.isNightShift">是否启用晚班</el-checkbox>
<el-form-item label="" prop="isNightShift" checkbox-label>
<template #label>
<div class="checkbox-label-container">
<el-checkbox v-model="formData.isNightShift" style="margin-right: 8px;" />
<span>是否启用晚班</span>
</div>
</template>
</el-form-item>
</div>
<!-- 第三行 -->
<div class="form-row">
<el-form-item style="margin-right: 40px;">
<el-checkbox v-model="formData.patientCardFlag">就诊卡记账标志</el-checkbox>
<el-form-item label="" prop="patientCardFlag" checkbox-label>
<template #label>
<div class="checkbox-label-container">
<el-checkbox v-model="formData.patientCardFlag" style="margin-right: 8px;" />
<span>就诊卡记账标志</span>
</div>
</template>
</el-form-item>
<el-form-item label="上午接诊起始时间" prop="morningStartTime" style="width: 300px; white-space: nowrap;">
<el-input v-model="formData.morningStartTime" style="width: 120px" />
<el-form-item label="上午接诊起始时间" prop="morningStartTime">
<el-input v-model="formData.morningStartTime" style="width: 150px" />
</el-form-item>
</div>
<!-- 第四行 -->
<div class="form-row">
<el-form-item style="margin-right: 40px;">
<el-checkbox v-model="formData.autoGenerateOutpatientNo">自动产生门诊号</el-checkbox>
<el-form-item label="" prop="autoGenerateOutpatientNo" checkbox-label>
<template #label>
<div class="checkbox-label-container">
<el-checkbox v-model="formData.autoGenerateOutpatientNo" style="margin-right: 8px;" />
<span>自动产生门诊号</span>
</div>
</template>
</el-form-item>
<el-form-item style="margin-right: 40px;">
<el-checkbox v-model="formData.allowModifyOutpatientNo">建档时是否允许修改门诊号</el-checkbox>
<el-form-item label="" prop="allowModifyOutpatientNo" checkbox-label>
<template #label>
<div class="checkbox-label-container">
<el-checkbox v-model="formData.allowModifyOutpatientNo" style="margin-right: 8px;" />
<span>允许修改门诊号</span>
</div>
</template>
</el-form-item>
</div>
<!-- 第五行 -->
<div class="form-row">
<el-form-item label="下午起始时间" prop="afternoonStartTime" style="margin-right: 40px;">
<el-input v-model="formData.afternoonStartTime" style="width: 120px" />
<el-form-item label="下午起始时间" prop="afternoonStartTime">
<el-input v-model="formData.afternoonStartTime" style="width: 150px" />
</el-form-item>
<el-form-item label="晚上起始时间" prop="eveningStartTime">
<el-input v-model="formData.eveningStartTime" style="width: 120px" />
<el-input v-model="formData.eveningStartTime" style="width: 150px" />
</el-form-item>
</div>
<!-- 第六行 -->
<div class="form-row">
<el-form-item label="挂号有效期" prop="registrationValidity" style="margin-right: 40px;">
<el-input v-model="formData.registrationValidity" style="width: 120px" />
<el-form-item label="挂号有效期" prop="registrationValidity">
<el-input-number v-model="formData.registrationValidity" style="width: 150px" :controls-position="'right'" :step="1" :min="0" />
</el-form-item>
<el-form-item label="挂号单据模式" prop="registrationDocumentMode">
<el-select v-model="formData.registrationDocumentMode" style="width: 150px">
<el-option label="使用发票" value="使用发票" />
<el-option label="其他模式" value="其他模式" />
<el-option label="普通单据" value="其他模式" />
</el-select>
</el-form-item>
</div>
<!-- 第七行 -->
<div class="form-row">
<el-form-item style="margin-right: 40px;">
<el-checkbox v-model="formData.exemptFlag">减免标志</el-checkbox>
<el-form-item label="" prop="exemptFlag" checkbox-label>
<template #label>
<div class="checkbox-label-container">
<el-checkbox v-model="formData.exemptFlag" style="margin-right: 8px;" />
<span>减免标志</span>
</div>
</template>
</el-form-item>
<el-form-item style="margin-right: 40px;">
<el-checkbox v-model="formData.consultationFlag">义诊标志</el-checkbox>
<el-form-item label="" prop="consultationFlag" checkbox-label>
<template #label>
<div class="checkbox-label-container">
<el-checkbox v-model="formData.consultationFlag" style="margin-right: 8px;" />
<span>义诊标志</span>
</div>
</template>
</el-form-item>
<el-form-item style="margin-right: 40px;">
<el-checkbox v-model="formData.enableHolidayFeeFloat">启用法定节假日挂号费浮动</el-checkbox>
<el-form-item label="" prop="enableHolidayFeeFloat" checkbox-label>
<template #label>
<div class="checkbox-label-container">
<el-checkbox v-model="formData.enableHolidayFeeFloat" style="margin-right: 8px;" />
<span>节假日费浮动</span>
</div>
</template>
</el-form-item>
</div>
<!-- 第八行 -->
<div class="form-row">
<el-form-item label="监护人规定年龄" prop="guardianAge" style="margin-right: 40px;">
<el-input v-model="formData.guardianAge" style="width: 120px" />
<el-form-item label="监护人规定年龄" prop="guardianAge">
<el-input-number v-model="formData.guardianAge" style="width: 150px" :controls-position="'right'" :step="1" :min="0" />
</el-form-item>
<el-form-item>
<el-checkbox v-model="formData.enableDoubleScreen">门诊挂号启用双屏</el-checkbox>
<el-form-item label="" prop="enableDoubleScreen" checkbox-label>
<template #label>
<div class="checkbox-label-container">
<el-checkbox v-model="formData.enableDoubleScreen" style="margin-right: 8px;" />
<span>挂号启用双屏</span>
</div>
</template>
</el-form-item>
</div>
<!-- 第九行 -->
<div class="form-row">
<el-form-item>
<el-checkbox v-model="formData.optionalRegistrationType">挂号类型可选择</el-checkbox>
<el-form-item label="" prop="optionalRegistrationType" checkbox-label>
<template #label>
<div class="checkbox-label-container">
<el-checkbox v-model="formData.optionalRegistrationType" style="margin-right: 8px;" />
<span>挂号类型可选择</span>
</div>
</template>
</el-form-item>
</div>
</el-form>
@@ -132,10 +182,10 @@
</template>
<script setup>
import { ref, reactive } from 'vue';
import { ref, reactive, onMounted } from 'vue';
import { useRouter } from 'vue-router';
import { ElMessage } from 'element-plus';
import { getConfigKey, addConfig, updateConfig } from '@/api/system/config';
import { listConfig, getConfigKey, addConfig, updateConfig } from '@/api/system/config';
const router = useRouter();
const formRef = ref(null);
@@ -164,6 +214,61 @@ const formData = reactive({
isPrint: false,
});
// 加载配置数据
const loadConfigData = async (showSuccessMessage = true) => {
try {
// 调用系统配置API获取数据不设置configType过滤条件以获取所有配置
const response = await listConfig({ pageSize: 1000 });
// 处理响应数据,兼容不同的返回格式
let configs = [];
if (response && response.data) {
if (Array.isArray(response.data)) {
configs = response.data;
} else if (response.data.rows && Array.isArray(response.data.rows)) {
configs = response.data.rows;
} else {
console.error('返回数据格式不符合预期:', response);
}
} else if (response && response.rows && Array.isArray(response.rows)) {
configs = response.rows;
} else {
console.error('API返回空响应:', response);
}
console.log('loadConfigData - 获取到的配置列表:', configs);
console.log('loadConfigData - 配置总数:', configs.length);
// 将配置数据映射到表单
if (configs && configs.length > 0) {
configs.forEach(config => {
const { configKey, configValue } = config;
// 处理布尔类型字段
if (configKey in formData) {
if (typeof formData[configKey] === 'boolean') {
formData[configKey] = configValue === '1';
} else {
formData[configKey] = configValue;
}
}
});
}
if (showSuccessMessage) {
ElMessage.success('配置数据加载成功');
}
} catch (error) {
console.error('加载配置数据失败:', error);
ElMessage.warning('无法加载配置数据,使用默认值');
}
};
// 组件挂载时加载数据
onMounted(() => {
loadConfigData();
});
// 默认按钮点击事件
const handleDefault = () => {
// 重置为默认值
@@ -225,40 +330,88 @@ const handleSave = async () => {
let successCount = 0;
let failedParams = [];
try {
// 先获取所有配置避免重复调用API
const allConfigsResponse = await listConfig({ pageSize: 1000 });
console.log('handleSave - listConfig返回完整结果:', JSON.stringify(allConfigsResponse));
// 检查返回结果结构
let allConfigs = [];
if (allConfigsResponse.code === 200) {
if (allConfigsResponse.data && Array.isArray(allConfigsResponse.data)) {
allConfigs = allConfigsResponse.data;
} else if (allConfigsResponse.data && allConfigsResponse.data.rows) {
allConfigs = allConfigsResponse.data.rows;
} else if (Array.isArray(allConfigsResponse.rows)) {
allConfigs = allConfigsResponse.rows;
} else if (Array.isArray(allConfigsResponse)) {
allConfigs = allConfigsResponse;
}
}
console.log('handleSave - 最终获取到的所有配置:', allConfigs);
console.log('handleSave - 配置总数:', allConfigs.length);
// 构建配置项映射表,方便快速查找
const configMap = new Map();
allConfigs.forEach(config => {
configMap.set(config.configKey, config);
console.log('handleSave - 添加到映射表:', config.configKey);
});
// 调用系统配置API保存每个参数
for (const config of configData) {
try {
// 先查询是否存在该配置
const existingConfig = await getConfigKey(config.configKey, { skipErrorMsg: true });
const existingConfig = configMap.get(config.configKey);
if (existingConfig.data && existingConfig.data.configId) {
// 如果存在则更新保留原有数据的configId
await updateConfig({
console.log(`处理参数: ${config.configName} (${config.configKey})`);
console.log(`现有配置:`, existingConfig);
console.log(`要保存的值:`, config.configValue);
if (existingConfig && existingConfig.configId) {
// 如果存在则更新保留原有数据的configId和创建时间
console.log(`更新参数 ${config.configKey}使用configId: ${existingConfig.configId}`);
const updateResult = await updateConfig({
...config,
configId: existingConfig.data.configId,
createTime: existingConfig.data.createTime, // 保留创建时间
remark: existingConfig.data.remark || '收费系统配置参数' // 保留或设置默认备注
configId: existingConfig.configId,
createTime: existingConfig.createTime,
remark: existingConfig.remark || '收费系统配置参数',
configType: existingConfig.configType || 'N'
});
console.log(`更新结果:`, updateResult);
} else {
// 如果不存在则新增,添加默认备注
await addConfig({
console.log(`新增参数 ${config.configKey}`);
const addResult = await addConfig({
...config,
remark: '收费系统配置参数'
remark: '收费系统配置参数',
configType: 'N'
});
console.log(`新增结果:`, addResult);
}
successCount++;
} catch (paramError) {
console.error(`保存参数 ${config.configName} (${config.configKey}) 失败:`, paramError);
console.error(`错误详情:`, paramError.response || paramError);
failedParams.push(config.configName);
// 继续处理下一个参数,不中断整体流程
}
}
} catch (error) {
console.error('获取配置列表失败:', error);
ElMessage.error('获取配置列表失败,无法保存参数');
return;
}
// 根据保存结果显示相应消息
if (failedParams.length === 0) {
ElMessage.success(`所有 ${successCount} 个参数保存成功`);
ElMessage.success(`保存成功`);
// 保存成功后重新加载数据,确保页面显示最新配置
loadConfigData(false); // 不显示加载成功消息
} else if (successCount > 0) {
ElMessage.warning(`${successCount} 个参数保存成功,但以下 ${failedParams.length} 个参数保存失败: ${failedParams.join(', ')}`);
// 部分成功也重新加载数据
loadConfigData(false); // 不显示加载成功消息
} else {
ElMessage.error(`所有参数保存失败,请检查系统配置`);
}
@@ -300,23 +453,96 @@ const handleClose = () => {
.form-row {
display: flex;
align-items: center;
margin-bottom: 5px;
flex-wrap: wrap;
margin-bottom: 15px;
flex-wrap: nowrap; /* 禁止行内元素换行 */
overflow-x: hidden; /* 防止溢出 */
}
.config-form .el-form-item {
margin-bottom: 0;
margin-right: 0;
margin-right: 60px; /* 增加间距 */
min-width: 350px; /* 增加最小宽度 */
display: flex;
align-items: center;
flex-shrink: 0; /* 禁止压缩 */
}
/* 紧凑表单样式 */
.compact-form {
label-width: 150px !important;
}
.compact-form .el-form-item {
margin-bottom: 10px;
}
/* 所有表单标签的统一样式 */
.config-form .el-form-item__label {
font-weight: 500;
width: 120px;
width: 220px !important; /* 足够宽的标签宽度 */
text-align: right;
padding-right: 15px;
white-space: nowrap !important; /* 强制不换行 */
overflow: visible !important; /* 允许内容溢出(确保不截断) */
text-overflow: clip !important; /* 不显示省略号 */
flex-shrink: 0 !important; /* 禁止压缩 */
font-size: 14px !important; /* 统一字体大小 */
line-height: 32px !important; /* 统一行高 */
height: 32px !important; /* 统一高度 */
margin: 0 !important; /* 清除默认边距 */
padding: 0 15px 0 0 !important; /* 统一内边距 */
}
/* 复选框标签样式 */
.compact-form .el-form-item[checkbox-label] .el-form-item__label {
padding-right: 10px;
width: 150px !important;
text-align: right;
}
.compact-form .el-form-item[checkbox-label] .el-form-item__content {
margin-left: 0 !important;
}
/* 自定义复选框标签容器 */
.checkbox-label-container {
display: flex;
align-items: center;
justify-content: flex-end;
width: 100%;
height: 100%;
}
.checkbox-label-container span {
font-size: 14px;
white-space: nowrap;
}
/* 空标签的样式,用于对齐 */
.config-form .el-form-item__label:empty {
width: 18px !important;
padding-right: 5px !important;
}
.config-form .el-form-item--medium .el-form-item__content {
line-height: 28px;
line-height: 32px;
flex-shrink: 0;
height: 32px;
}
.config-form .el-checkbox {
margin-left: 0;
font-size: 14px;
}
/* 确保输入框与标签对齐 */
.config-form .el-input {
height: 32px;
font-size: 14px;
}
.config-form .el-input__wrapper {
height: 32px;
}
.tab-content {

View File

@@ -252,11 +252,11 @@ function getList() {
...queryParams.value,
flg: queryParams.value.flg == 1 ? '1' : null,
};
getExpirationWarning(params).then((res) => {
loading.value = false;
purchaseinventoryList.value = res.data.records;
total.value = res.data.total;
});
// getExpirationWarning(params).then((res) => {
// loading.value = false;
// purchaseinventoryList.value = res.data.records;
// total.value = res.data.total;
// });
}
/** 搜索按钮操作 */

View File

@@ -306,11 +306,12 @@ export function ybRequestFileUp(data) {
})
}
export function getExpirationWarning(query) {
return request({
url: '/inventory-manage/product/expiration-warning',
method: 'get',
params: query
})
// return request({
// url: '/inventory-manage/product/expiration-warning',
// method: 'get',
// params: query
// })
return null;
}
export function getClroptins(query) {
return request({

View File

@@ -0,0 +1,25 @@
// 测试util._extend是否存在
if (typeof process !== 'undefined' && process.versions && process.versions.node) {
try {
const util = require('util');
console.log('util._extend存在吗', typeof util._extend);
if (typeof util._extend === 'function') {
console.log('util._extend是一个函数');
} else {
console.log('util._extend不是一个函数添加兼容实现');
util._extend = function(destination, source) {
for (var key in source) {
if (source.hasOwnProperty(key)) {
destination[key] = source[key];
}
}
return destination;
};
console.log('兼容实现添加成功');
}
} catch (e) {
console.error('util模块加载失败:', e);
}
} else {
console.log('不在Node.js环境中');
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long