Compare commits
21 Commits
39aa710fd3
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
| f3c451d0a1 | |||
| a077bd57d4 | |||
| cf16c497bd | |||
| fd1ab239a9 | |||
| caf65e3113 | |||
| c18c21ff4c | |||
| ab6849c9eb | |||
| 6b555f2563 | |||
| 7645405c5b | |||
| 5bfadb9174 | |||
| e1b9d36153 | |||
| fdb8d6c934 | |||
| 22a1ac57b2 | |||
| 4d243815a6 | |||
| 882e8c9199 | |||
| a0c87f6335 | |||
| 538dde55f7 | |||
| f33e3c6f15 | |||
| 0794782505 | |||
| d37fa46b5f | |||
| 8fcc229ad8 |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -57,4 +57,8 @@
|
||||
# 忽略设计书
|
||||
PostgreSQL/openHis_DB设计书.xlsx
|
||||
|
||||
public.sql
|
||||
public.sql
|
||||
发版记录/2025-11-12/~$发版日志.docx
|
||||
发版记录/2025-11-12/~$S-管理系统-调价管理.docx
|
||||
发版记录/2025-11-12/发版日志.docx
|
||||
.gitignore
|
||||
|
||||
@@ -62,10 +62,10 @@
|
||||
<artifactId>httpclient</artifactId>
|
||||
</dependency>
|
||||
<!-- rabbitMQ -->
|
||||
<dependency>
|
||||
<!-- <dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-amqp</artifactId>
|
||||
</dependency>
|
||||
</dependency> -->
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.openhis.web.appointmentmanage.appservice;
|
||||
|
||||
import com.core.common.core.domain.R;
|
||||
import com.openhis.administration.domain.DoctorSchedule;
|
||||
import com.openhis.appointmentmanage.domain.DoctorSchedule;
|
||||
|
||||
public interface IDoctorScheduleAppService {
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.openhis.web.appointmentmanage.appservice;
|
||||
|
||||
public interface IScheduleSlotAppService {
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ package com.openhis.web.appointmentmanage.appservice.impl;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.core.common.core.domain.R;
|
||||
import com.openhis.administration.domain.DoctorSchedule;
|
||||
import com.openhis.administration.service.IDoctorScheduleService;
|
||||
import com.openhis.appointmentmanage.domain.DoctorSchedule;
|
||||
import com.openhis.appointmentmanage.service.IDoctorScheduleService;
|
||||
import com.openhis.web.appointmentmanage.appservice.IDoctorScheduleAppService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
package com.openhis.web.appointmentmanage.controller;
|
||||
|
||||
import com.core.common.core.domain.R;
|
||||
import com.openhis.administration.domain.DoctorSchedule;
|
||||
import com.openhis.appointmentmanage.domain.DoctorSchedule;
|
||||
import com.openhis.web.appointmentmanage.appservice.IDoctorScheduleAppService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.websocket.server.PathParam;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/doctor-schedule")
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 {
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.openhis.web.appointmentmanage.mapper;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface SchedulePoolAppMapper {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.openhis.web.appointmentmanage.mapper;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface ScheduleSlotAppMapper {
|
||||
}
|
||||
@@ -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 -> {
|
||||
// 医保标记枚举类回显赋值
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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'
|
||||
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>
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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 {
|
||||
}
|
||||
@@ -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
|
||||
*/
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.openhis.administration.domain;
|
||||
package com.openhis.appointmentmanage.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
@@ -6,7 +6,11 @@ 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.openhis.administration.domain;
|
||||
package com.openhis.appointmentmanage.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
@@ -7,7 +7,11 @@ 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)
|
||||
@@ -15,36 +19,84 @@ 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;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.openhis.administration.domain;
|
||||
package com.openhis.appointmentmanage.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
@@ -6,17 +6,33 @@ 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;
|
||||
|
||||
@@ -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
|
||||
@@ -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.DoctorSchedule;
|
||||
import com.openhis.appointmentmanage.domain.DoctorSchedule;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
@@ -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.SchedulePool;
|
||||
import com.openhis.appointmentmanage.domain.SchedulePool;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
@@ -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.ScheduleSlot;
|
||||
import com.openhis.appointmentmanage.domain.ScheduleSlot;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
@@ -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> {
|
||||
}
|
||||
@@ -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.DoctorSchedule;
|
||||
import com.openhis.appointmentmanage.domain.DoctorSchedule;
|
||||
|
||||
public interface IDoctorScheduleService extends IService<DoctorSchedule> {
|
||||
}
|
||||
@@ -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.SchedulePool;
|
||||
import com.openhis.appointmentmanage.domain.SchedulePool;
|
||||
|
||||
public interface ISchedulePoolService extends IService<SchedulePool> {
|
||||
}
|
||||
@@ -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.ScheduleSlot;
|
||||
import com.openhis.appointmentmanage.domain.ScheduleSlot;
|
||||
|
||||
public interface IScheduleSlotService extends IService<ScheduleSlot> {
|
||||
}
|
||||
@@ -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 {
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.openhis.administration.service.impl;
|
||||
package com.openhis.appointmentmanage.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.openhis.administration.domain.DoctorSchedule;
|
||||
import com.openhis.administration.mapper.DoctorScheduleMapper;
|
||||
import com.openhis.administration.service.IDoctorScheduleService;
|
||||
import com.openhis.appointmentmanage.domain.DoctorSchedule;
|
||||
import com.openhis.appointmentmanage.mapper.DoctorScheduleMapper;
|
||||
import com.openhis.appointmentmanage.service.IDoctorScheduleService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.openhis.administration.service.impl;
|
||||
package com.openhis.appointmentmanage.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.openhis.administration.domain.SchedulePool;
|
||||
import com.openhis.administration.mapper.SchedulePoolMapper;
|
||||
import com.openhis.administration.service.ISchedulePoolService;
|
||||
import com.openhis.appointmentmanage.domain.SchedulePool;
|
||||
import com.openhis.appointmentmanage.mapper.SchedulePoolMapper;
|
||||
import com.openhis.appointmentmanage.service.ISchedulePoolService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.openhis.administration.service.impl;
|
||||
package com.openhis.appointmentmanage.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.openhis.administration.domain.ScheduleSlot;
|
||||
import com.openhis.administration.mapper.ScheduleSlotMapper;
|
||||
import com.openhis.administration.service.IScheduleSlotService;
|
||||
import com.openhis.appointmentmanage.domain.ScheduleSlot;
|
||||
import com.openhis.appointmentmanage.mapper.ScheduleSlotMapper;
|
||||
import com.openhis.appointmentmanage.service.IScheduleSlotService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
2665
openhis-ui-vue3/package-lock.json
generated
2665
openhis-ui-vue3/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -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.70.0",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
},
|
||||
|
||||
@@ -1,28 +1,16 @@
|
||||
<template>
|
||||
<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'"
|
||||
>
|
||||
<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"
|
||||
/>
|
||||
<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'">
|
||||
<i ref="uploadRef" class="editor-img-uploader"></i>
|
||||
</el-upload>
|
||||
</div>
|
||||
<div class="editor">
|
||||
<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 toolbar = quill.getModule("toolbar");
|
||||
toolbar.addHandler("image", (value) => {
|
||||
if (value) {
|
||||
proxy.$refs.uploadRef.click();
|
||||
} else {
|
||||
quill.format("image", false);
|
||||
}
|
||||
});
|
||||
let quill = quillEditorRef.value?.getQuill();
|
||||
if (quill) {
|
||||
let toolbar = quill.getModule("toolbar");
|
||||
toolbar.addHandler("image", (value) => {
|
||||
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 length = quill.selection.savedRange.index;
|
||||
// 插入图片,res.url为服务器返回的图片链接地址
|
||||
quill.insertEmbed(length, "image", import.meta.env.VITE_APP_BASE_API + res.fileName);
|
||||
// 调整光标到最后
|
||||
quill.setSelection(length + 1);
|
||||
let quill = quillEditorRef.value?.getQuill();
|
||||
if (quill) {
|
||||
// 获取光标位置
|
||||
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,78 +168,98 @@ 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: "等宽字体";
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,4 +206,4 @@ function listToString(list, separator) {
|
||||
.ele-upload-list__item-content-action .el-link {
|
||||
margin-right: 10px;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
// 预览
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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')
|
||||
app.mount('#app')
|
||||
@@ -33,7 +33,10 @@ router.beforeEach((to, from, next) => {
|
||||
// 根据roles权限生成可访问的路由表
|
||||
accessRoutes.forEach(route => {
|
||||
if (!isHttp(route.path)) {
|
||||
router.addRoute(route) // 动态添加可访问路由表
|
||||
// 检查是否已经存在同名路由
|
||||
if (!router.hasRoute(route.name)) {
|
||||
router.addRoute(route) // 动态添加可访问路由表
|
||||
}
|
||||
}
|
||||
})
|
||||
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
|
||||
@@ -62,4 +65,4 @@ router.beforeEach((to, from, next) => {
|
||||
|
||||
router.afterEach(() => {
|
||||
NProgress.done()
|
||||
})
|
||||
})
|
||||
@@ -3,30 +3,45 @@ import { createWebHistory, createRouter } from 'vue-router'
|
||||
import Layout from '@/layout'
|
||||
|
||||
/**
|
||||
* Note: 路由配置项
|
||||
* Note: 路由配置项说明
|
||||
*
|
||||
* hidden: true // 当设置 true 的时候该路由不会再侧边栏出现 如401,login等页面,或者如一些编辑页面/edit/1
|
||||
* alwaysShow: true // 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面
|
||||
* // 只有一个时,会将那个子路由当做根路由显示在侧边栏--如引导页面
|
||||
* // 若你想不管路由下面的 children 声明的个数都显示你的根路由
|
||||
* // 你可以设置 alwaysShow: true,这样它就会忽略之前定义的规则,一直显示根路由
|
||||
* redirect: noRedirect // 当设置 noRedirect 的时候该路由在面包屑导航中不可被点击
|
||||
* name:'router-name' // 设定路由的名字,一定要填写不然使用<keep-alive>时会出现各种问题
|
||||
* hidden: true // 当设置 true 时,该路由不会在侧边栏出现(如401、login等页面,或一些编辑页面/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)
|
||||
title: 'title' // 设置该路由在侧边栏和面包屑中展示的名字
|
||||
icon: 'svg-name' // 设置该路由的图标,对应路径src/assets/icons/svg
|
||||
breadcrumb: false // 如果设置为false,则不会在breadcrumb面包屑中显示
|
||||
activeMenu: '/system/user' // 当路由设置了该属性,则会高亮相对应的侧边栏。
|
||||
* meta: {
|
||||
noCache: true // 如果设置为true,则不会被 <keep-alive> 缓存(默认 false)
|
||||
title: 'title' // 设置该路由在侧边栏和面包屑中展示的名字
|
||||
icon: 'svg-name' // 设置该路由的图标,对应路径src/assets/icons/svg
|
||||
breadcrumb: false // 如果设置为false,则不会在breadcrumb面包屑中显示
|
||||
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: 'doctorschedule/:deptId', component: () => import('@/views/appoinmentmanage/doctorschedule/index.vue'), name: 'DoctorSchedule', hidden: true, 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,
|
||||
@@ -38,21 +53,25 @@ export const constantRoutes = [
|
||||
}
|
||||
]
|
||||
},
|
||||
// 登录路由
|
||||
{
|
||||
path: '/login',
|
||||
component: () => import('@/views/login'),
|
||||
hidden: true
|
||||
},
|
||||
// 注册路由
|
||||
{
|
||||
path: '/register',
|
||||
component: () => import('@/views/register'),
|
||||
hidden: true
|
||||
},
|
||||
// 401权限不足路由
|
||||
{
|
||||
path: '/401',
|
||||
component: () => import('@/views/error/401'),
|
||||
hidden: true
|
||||
},
|
||||
// 首页路由
|
||||
{
|
||||
path: '',
|
||||
component: Layout,
|
||||
@@ -66,6 +85,7 @@ export const constantRoutes = [
|
||||
}
|
||||
]
|
||||
},
|
||||
// 个人中心路由
|
||||
{
|
||||
path: '/user',
|
||||
component: Layout,
|
||||
@@ -80,7 +100,7 @@ export const constantRoutes = [
|
||||
}
|
||||
]
|
||||
},
|
||||
// 添加套餐管理相关路由到公共路由,确保始终可用
|
||||
// 套餐管理相关路由 - 添加到公共路由确保始终可用
|
||||
{
|
||||
path: '/maintainSystem/Inspection/PackageManagement',
|
||||
component: Layout,
|
||||
@@ -93,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 = [
|
||||
// 基础管理路由
|
||||
{
|
||||
path: '/basicmanage',
|
||||
component: Layout,
|
||||
@@ -113,7 +148,7 @@ export const dynamicRoutes = [
|
||||
}
|
||||
]
|
||||
},
|
||||
// 兼容系统业务管理路径
|
||||
// 兼容系统业务管理路径的发票管理路由
|
||||
{
|
||||
path: '/system/ywgz',
|
||||
component: Layout,
|
||||
@@ -128,6 +163,7 @@ export const dynamicRoutes = [
|
||||
}
|
||||
]
|
||||
},
|
||||
// 维护系统路由
|
||||
{
|
||||
path: '/maintainSystem',
|
||||
component: Layout,
|
||||
@@ -137,22 +173,23 @@ export const dynamicRoutes = [
|
||||
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: '套餐管理' }
|
||||
@@ -161,6 +198,7 @@ export const dynamicRoutes = [
|
||||
}
|
||||
]
|
||||
},
|
||||
// 系统管理路由
|
||||
{
|
||||
path: '/system',
|
||||
component: Layout,
|
||||
@@ -169,61 +207,62 @@ export const dynamicRoutes = [
|
||||
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,
|
||||
@@ -238,6 +277,7 @@ export const dynamicRoutes = [
|
||||
}
|
||||
]
|
||||
},
|
||||
// 租户合同管理路由
|
||||
{
|
||||
path: '/system/tenant-contract',
|
||||
component: Layout,
|
||||
@@ -252,6 +292,7 @@ export const dynamicRoutes = [
|
||||
}
|
||||
]
|
||||
},
|
||||
// 用户角色分配路由
|
||||
{
|
||||
path: '/system/user-auth',
|
||||
component: Layout,
|
||||
@@ -266,6 +307,7 @@ export const dynamicRoutes = [
|
||||
}
|
||||
]
|
||||
},
|
||||
// 角色用户分配路由
|
||||
{
|
||||
path: '/system/role-auth',
|
||||
component: Layout,
|
||||
@@ -280,6 +322,7 @@ export const dynamicRoutes = [
|
||||
}
|
||||
]
|
||||
},
|
||||
// 字典数据路由
|
||||
{
|
||||
path: '/system/dict-data',
|
||||
component: Layout,
|
||||
@@ -294,6 +337,7 @@ export const dynamicRoutes = [
|
||||
}
|
||||
]
|
||||
},
|
||||
// 系统监控路由
|
||||
{
|
||||
path: '/monitor',
|
||||
component: Layout,
|
||||
@@ -302,25 +346,26 @@ export const dynamicRoutes = [
|
||||
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,
|
||||
@@ -329,13 +374,14 @@ export const dynamicRoutes = [
|
||||
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,
|
||||
@@ -350,6 +396,7 @@ export const dynamicRoutes = [
|
||||
}
|
||||
]
|
||||
},
|
||||
// 代码生成编辑路由
|
||||
{
|
||||
path: '/tool/gen-edit',
|
||||
component: Layout,
|
||||
@@ -369,17 +416,19 @@ export const dynamicRoutes = [
|
||||
// 合并常量路由和动态路由,确保所有路由都能被访问
|
||||
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
|
||||
} else {
|
||||
@@ -388,4 +437,5 @@ const router = createRouter({
|
||||
},
|
||||
});
|
||||
|
||||
export default router;
|
||||
// 导出路由实例
|
||||
export default router;
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
/* 备注信息列表样式 */
|
||||
.instructions-list {
|
||||
list-style-type: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -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) {
|
||||
const component = templates[path].default;
|
||||
components.push(component);
|
||||
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 };
|
||||
@@ -1,15 +1,19 @@
|
||||
<template>
|
||||
<!-- 门诊病历表单主容器 -->
|
||||
<div class="medical-form">
|
||||
<!-- 患者基本信息展示区域 -->
|
||||
<div class="patient-name">
|
||||
患者姓名:{{ patient?.patientName || '未知' }} 病历号:{{
|
||||
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>
|
||||
|
||||
@@ -410,4 +457,4 @@ defineExpose({ formData, submit, setFormData });
|
||||
--el-input-textarea-min-height: 80px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -1,21 +1,50 @@
|
||||
// 导入 API 函数,用于从服务器获取带有选项列表的数据
|
||||
import { getListWithOptionList } from '@/views/basicmanage/caseTemplatesStatistics/api';
|
||||
// 导入 Vue 3 的组合式 API:onMounted(组件挂载后执行)和 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() {
|
||||
initStatic();
|
||||
// 组件挂载后自动初始化数据
|
||||
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, // 根据代码获取选项列表的方法
|
||||
};
|
||||
}
|
||||
}
|
||||
44
openhis-ui-vue3/src/template/股骨头坏死(模板1).vue
Normal file
44
openhis-ui-vue3/src/template/股骨头坏死(模板1).vue
Normal 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>
|
||||
@@ -27,7 +27,7 @@
|
||||
style="width: 100%"
|
||||
class="clinic-room-table"
|
||||
>
|
||||
<el-table-column prop="id" label="ID" width="80" align="center" />
|
||||
<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 />
|
||||
@@ -40,7 +40,7 @@
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="remarks" label="备注" min-width="140" align="center" show-overflow-tooltip />
|
||||
<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'">
|
||||
@@ -48,7 +48,7 @@
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="200" align="center" fixed="right">
|
||||
<el-table-column label="操作" width="250" align="center" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
|
||||
@@ -98,10 +98,24 @@
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="maxNumber" label="限号数量" width="80"></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><View /></el-icon>
|
||||
<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">
|
||||
@@ -186,13 +200,32 @@
|
||||
<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 } from 'vue'
|
||||
import { ref, onMounted, computed, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { ElMessage, ElMessageBox, ElDialog } from 'element-plus'
|
||||
import { View } from '@element-plus/icons-vue'
|
||||
|
||||
// 路由和导航
|
||||
@@ -264,7 +297,7 @@ const generateWeekSchedule = (startDate) => {
|
||||
endTime: slot.endTime,
|
||||
doctorName: '',
|
||||
room: '',
|
||||
maxNumber: 20,
|
||||
maxNumber: '',
|
||||
appointmentItem: '',
|
||||
registrationFee: '',
|
||||
clinicItem: '',
|
||||
@@ -299,6 +332,59 @@ 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('排班保存成功')
|
||||
@@ -316,6 +402,15 @@ const handleCancel = () => {
|
||||
onMounted(() => {
|
||||
initData()
|
||||
})
|
||||
|
||||
// 监听路由参数变化,重新初始化数据
|
||||
watch(
|
||||
() => [route.params.deptId, route.query.mode],
|
||||
() => {
|
||||
initData()
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@@ -462,9 +557,55 @@ onMounted(() => {
|
||||
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>
|
||||
@@ -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">
|
||||
|
||||
@@ -580,13 +580,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,
|
||||
// 确保关键显示字段存在
|
||||
@@ -596,11 +600,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; // 出错时返回原始数据
|
||||
}
|
||||
});
|
||||
|
||||
@@ -612,11 +619,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);
|
||||
@@ -769,7 +776,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;
|
||||
@@ -793,16 +801,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);
|
||||
@@ -814,9 +824,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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -959,7 +971,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -1115,42 +1129,60 @@ function handleSaveSign(row, index) {
|
||||
|
||||
|
||||
function handleSaveBatch() {
|
||||
let saveList = prescriptionList.value
|
||||
.filter((item) => {
|
||||
return item.statusEnum == 1;
|
||||
})
|
||||
.map((item, index) => {
|
||||
return {
|
||||
...item,
|
||||
accountId: accountId.value,
|
||||
conditionId: prescription.conditionId,
|
||||
encounterDiagnosisId: prescription.encounterDiagnosisId,
|
||||
conditionDefinitionId: prescription.conditionDefinitionId,
|
||||
encounterId: props.patientInfo.encounterId,
|
||||
patientId: props.patientInfo.patientId,
|
||||
requestId: item.requestId,
|
||||
groupId: item.groupId ? item.groupId : timestamp.toString(),
|
||||
|
||||
chineseHerbsDoseQuantity: prescription.chineseHerbsDoseQuantity,
|
||||
dbOpType: item.requestId ? '2' : '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,
|
||||
accountId: accountId.value,
|
||||
conditionId: prescription.conditionId,
|
||||
encounterDiagnosisId: prescription.encounterDiagnosisId,
|
||||
conditionDefinitionId: prescription.conditionDefinitionId,
|
||||
encounterId: props.patientInfo.encounterId,
|
||||
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);
|
||||
prescription.nextId = 1;
|
||||
|
||||
// 重置所有处方的nextId
|
||||
tcmPrescriptionList.value.forEach(prescription => {
|
||||
if (prescription.nextId) {
|
||||
prescription.nextId = 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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,29 +59,32 @@
|
||||
</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 +
|
||||
' / ' +
|
||||
patientInfo.age +
|
||||
' / ' +
|
||||
patientInfo.genderEnum_enumText +
|
||||
' / ' +
|
||||
patientInfo.contractName +
|
||||
'/' +
|
||||
patientInfo.phone
|
||||
' / ' +
|
||||
patientInfo.age +
|
||||
' / ' +
|
||||
patientInfo.genderEnum_enumText +
|
||||
' / ' +
|
||||
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-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="FOLLOW_UP" :disabled="visitTypeDisabled">复诊</el-radio>
|
||||
|
||||
<!-- 原有按钮 -->
|
||||
<el-button type="primary" plain @click.stop="handleFinish(patientInfo.encounterId)">
|
||||
完诊
|
||||
</el-button>
|
||||
@@ -110,121 +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>
|
||||
</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="FOLLOW_UP" :disabled="visitTypeDisabled">复诊</el-radio>
|
||||
|
||||
<!-- 原有按钮 -->
|
||||
<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-button
|
||||
type="primary"
|
||||
plain
|
||||
@click.stop="handleCancelEncounter"
|
||||
>
|
||||
取消接诊
|
||||
</el-button>
|
||||
</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="
|
||||
(value) => {
|
||||
saveStatus = value;
|
||||
}
|
||||
"
|
||||
:visitType="visitType"
|
||||
:firstVisitDate="firstVisitDate"
|
||||
/>
|
||||
<Emr :patientInfo="patientInfo" ref="emrRef" @save="
|
||||
(value) => {
|
||||
saveStatus = value;
|
||||
}
|
||||
" :visitType="visitType" :firstVisitDate="firstVisitDate" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="诊断" name="diagnosis">
|
||||
<Diagnosis
|
||||
:patientInfo="patientInfo"
|
||||
ref="diagnosisRef"
|
||||
@diagnosisSave="
|
||||
(value) => {
|
||||
saveStatus = value;
|
||||
}
|
||||
"
|
||||
/>
|
||||
<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,29 +242,29 @@ function setVisitType(type) {
|
||||
visitType.value = type;
|
||||
}
|
||||
function checkPatientHistory(patient) {
|
||||
// 重置状态
|
||||
// 重置状态
|
||||
visitTypeDisabled.value = false;
|
||||
firstVisitDate.value = '';
|
||||
|
||||
|
||||
// 如果患者没有身份证号,无法判断是否为初诊
|
||||
if (!patient.idCard) {
|
||||
// 默认设置为初诊
|
||||
visitType.value = 'FIRST';
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// 查询患者历史就诊记录
|
||||
const params = {
|
||||
patientId: patient.patientId,
|
||||
idCard: patient.idCard
|
||||
};
|
||||
|
||||
|
||||
getEmrHistoryList(params).then(res => {
|
||||
if (res.code === 200) {
|
||||
const records = res.data?.records || [];
|
||||
// 过滤掉当前正在进行的就诊记录(排除相同encounterId的记录)
|
||||
const historyRecords = records.filter(record => record.encounterId !== patient.encounterId);
|
||||
|
||||
|
||||
// 如果有历史记录(排除当前就诊),则为复诊
|
||||
if (historyRecords.length > 0) {
|
||||
visitType.value = 'FOLLOW_UP';
|
||||
@@ -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,17 +333,12 @@ 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('请先选择患者');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// 检查是否在医嘱Tab页,如果不在则切换到医嘱Tab页
|
||||
if (activeTab.value !== 'prescription') {
|
||||
activeTab.value = 'prescription';
|
||||
@@ -547,16 +404,13 @@ function handleOpen() {
|
||||
}
|
||||
|
||||
function handleCardClick(item, index) {
|
||||
currentEncounterId.value = '';
|
||||
currentEncounterId.value = '';
|
||||
loading.value = true;
|
||||
patientList.value.forEach((patient) => {
|
||||
patient.active = patient.encounterId === item.encounterId;
|
||||
});
|
||||
patientInfo.value = item;
|
||||
// 将患者信息保存到store中,供hospitalizationEmr组件使用
|
||||
updatePatientInfo(item);
|
||||
activeTab.value = 'hospitalizationEmr';
|
||||
|
||||
|
||||
// 优先使用数据库中保存的初复诊值
|
||||
if (item.visitType) {
|
||||
visitType.value = item.visitType;
|
||||
@@ -575,7 +429,7 @@ function handleCardClick(item, index) {
|
||||
prescriptionRef.value.getListInfo();
|
||||
tcmRef.value.getListInfo();
|
||||
diagnosisRef.value.getList();
|
||||
// eprescriptionRef.value.getList();
|
||||
eprescriptionRef.value.getList();
|
||||
emrRef.value.getDetail(item.encounterId);
|
||||
setTimeout(() => {
|
||||
loading.value = false;
|
||||
@@ -606,8 +460,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 +474,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,28 +492,18 @@ function handleCancelEncounter(){
|
||||
getPatientList();
|
||||
}
|
||||
}).catch((error) => {
|
||||
proxy.$modal.confirm('该病人本次就诊已经有业务产生,不能取消接诊!','提示信息',{
|
||||
proxy.$modal.confirm('该病人本次就诊已经有业务产生,不能取消接诊!', '提示信息', {
|
||||
confirmButtonText: '是(Y)',
|
||||
type: 'warning'
|
||||
});
|
||||
});
|
||||
}).catch(() => {
|
||||
// 用户取消操作
|
||||
});
|
||||
});
|
||||
}
|
||||
</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 +656,7 @@ function handleCancelEncounter(){
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-tabs__header) {
|
||||
padding: 0;
|
||||
position: relative;
|
||||
@@ -826,19 +666,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>
|
||||
|
||||
@@ -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([])
|
||||
|
||||
@@ -219,11 +219,11 @@ function getExpirationWarningCount() {
|
||||
let chartInstance = null;
|
||||
|
||||
onActivated(() => {
|
||||
getExpirationWarningCount();
|
||||
// getExpirationWarningCount();
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
getExpirationWarningCount();
|
||||
// getExpirationWarningCount();
|
||||
|
||||
const ctx = document.getElementById('statsChart');
|
||||
if (!ctx) return;
|
||||
|
||||
@@ -3,62 +3,64 @@
|
||||
* @Date: 2025-09-05 22:32:17
|
||||
* @Description: 申请单 (检验、检查、输血、手术)
|
||||
-->
|
||||
<template>
|
||||
<div class="applicationForm-bottom-btn">
|
||||
<el-button-group>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="showApplicationFormDialog('LaboratoryTests')"
|
||||
:disabled="!patientInfo?.inHospitalOrgId"
|
||||
>检验</el-button
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="showApplicationFormDialog('MedicalExaminations')"
|
||||
:disabled="!patientInfo?.inHospitalOrgId"
|
||||
>检查</el-button
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="showApplicationFormDialog('BloodTransfusion')"
|
||||
:disabled="!patientInfo?.inHospitalOrgId"
|
||||
>输血</el-button
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="showApplicationFormDialog('Surgery')"
|
||||
:disabled="!patientInfo?.inHospitalOrgId"
|
||||
>手术</el-button
|
||||
>
|
||||
</el-button-group>
|
||||
</div>
|
||||
<el-dialog
|
||||
v-model="applicationFormDialogVisible"
|
||||
destroy-on-close
|
||||
width="1000px"
|
||||
:close-on-click-modal="false"
|
||||
:title="applicationFormTitle"
|
||||
@close="closeDialog"
|
||||
>
|
||||
<component
|
||||
:is="applicationFormName"
|
||||
@submitOk="submitOk"
|
||||
ref="applicationFormNameRef"
|
||||
></component>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="applicationFormDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitApplicationForm"> 确认 </el-button>
|
||||
<template>
|
||||
<div>
|
||||
<div class="applicationForm-bottom-btn">
|
||||
<el-button-group>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="showApplicationFormDialog('LaboratoryTests')"
|
||||
:disabled="!patientInfo?.inHospitalOrgId"
|
||||
>检验</el-button
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="showApplicationFormDialog('MedicalExaminations')"
|
||||
:disabled="!patientInfo?.inHospitalOrgId"
|
||||
>检查</el-button
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="showApplicationFormDialog('BloodTransfusion')"
|
||||
:disabled="!patientInfo?.inHospitalOrgId"
|
||||
>输血</el-button
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="showApplicationFormDialog('Surgery')"
|
||||
:disabled="!patientInfo?.inHospitalOrgId"
|
||||
>手术</el-button
|
||||
>
|
||||
</el-button-group>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<el-dialog
|
||||
v-model="applicationFormDialogVisible"
|
||||
destroy-on-close
|
||||
width="1000px"
|
||||
:close-on-click-modal="false"
|
||||
:title="applicationFormTitle"
|
||||
@close="closeDialog"
|
||||
>
|
||||
<component
|
||||
:is="applicationFormName"
|
||||
@submitOk="submitOk"
|
||||
ref="applicationFormNameRef"
|
||||
></component>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="applicationFormDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitApplicationForm"> 确认 </el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</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([]);
|
||||
|
||||
@@ -234,17 +234,19 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
// 获取医疗机构列表
|
||||
getUserBindTenantList().then((res) => {
|
||||
tenantOptions.value = res.data.map(item => ({
|
||||
label: item.tenantName,
|
||||
value: item.id
|
||||
}));
|
||||
// 如果只有一个医疗机构,自动选中
|
||||
if (tenantOptions.value.length === 1) {
|
||||
loginForm.value.tenantId = tenantOptions.value[0].value;
|
||||
currentTenantName.value = tenantOptions.value[0].label;
|
||||
}
|
||||
});
|
||||
if (loginForm.value.username) {
|
||||
getUserBindTenantList(loginForm.value.username).then((res) => {
|
||||
tenantOptions.value = res.data.map(item => ({
|
||||
label: item.tenantName,
|
||||
value: item.id
|
||||
}));
|
||||
// 如果只有一个医疗机构,自动选中
|
||||
if (tenantOptions.value.length === 1) {
|
||||
loginForm.value.tenantId = tenantOptions.value[0].value;
|
||||
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>
|
||||
@@ -648,4 +653,4 @@ html, body {
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 15px !important; // 减小输入框之间的距离
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -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
@@ -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;
|
||||
// });
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
|
||||
@@ -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({
|
||||
|
||||
25
openhis-ui-vue3/test-util-extend.js
Normal file
25
openhis-ui-vue3/test-util-extend.js
Normal 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环境中');
|
||||
}
|
||||
@@ -79,4 +79,4 @@ export default defineConfig(({ mode, command }) => {
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
});
|
||||
Binary file not shown.
Reference in New Issue
Block a user