Compare commits
24 Commits
39aa710fd3
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
| 633cf2c17f | |||
| 3188ca5752 | |||
| c79e4c2623 | |||
| f3c451d0a1 | |||
| a077bd57d4 | |||
| cf16c497bd | |||
| fd1ab239a9 | |||
| caf65e3113 | |||
| c18c21ff4c | |||
| ab6849c9eb | |||
| 6b555f2563 | |||
| 7645405c5b | |||
| 5bfadb9174 | |||
| e1b9d36153 | |||
| fdb8d6c934 | |||
| 22a1ac57b2 | |||
| 4d243815a6 | |||
| 882e8c9199 | |||
| a0c87f6335 | |||
| 538dde55f7 | |||
| f33e3c6f15 | |||
| 0794782505 | |||
| d37fa46b5f | |||
| 8fcc229ad8 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -58,3 +58,7 @@
|
||||
PostgreSQL/openHis_DB设计书.xlsx
|
||||
|
||||
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'
|
||||
<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
|
||||
2663
openhis-ui-vue3/package-lock.json
generated
2663
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.77.8",
|
||||
"unplugin-auto-import": "^0.19.0",
|
||||
"unplugin-vue-setup-extend-plus": "^1.0.0",
|
||||
"vite": "^5.0.4",
|
||||
"vite-plugin-compression": "0.5.1",
|
||||
"vite-plugin-svg-icons": "2.0.1"
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-svg-icons": "^2.0.1"
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
},
|
||||
|
||||
@@ -18,10 +18,11 @@ export function getConfig(configId) {
|
||||
}
|
||||
|
||||
// 根据参数键名查询参数值
|
||||
export function getConfigKey(configKey) {
|
||||
export function getConfigKey(configKey, options = {}) {
|
||||
return request({
|
||||
url: '/system/config/configKey/' + configKey,
|
||||
method: 'get'
|
||||
method: 'get',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,28 +1,16 @@
|
||||
<template>
|
||||
<div class="editor-container">
|
||||
<div>
|
||||
<el-upload
|
||||
:action="uploadUrl"
|
||||
:before-upload="handleBeforeUpload"
|
||||
:on-success="handleUploadSuccess"
|
||||
:on-error="handleUploadError"
|
||||
name="file"
|
||||
:show-file-list="false"
|
||||
:headers="headers"
|
||||
class="editor-img-uploader"
|
||||
v-if="type == 'url'"
|
||||
>
|
||||
<el-upload :action="uploadUrl" :before-upload="handleBeforeUpload" :on-success="handleUploadSuccess"
|
||||
:on-error="handleUploadError" name="file" :show-file-list="false" :headers="headers" class="editor-img-uploader"
|
||||
v-if="type == 'url'">
|
||||
<i ref="uploadRef" class="editor-img-uploader"></i>
|
||||
</el-upload>
|
||||
</div>
|
||||
<div class="editor">
|
||||
<quill-editor
|
||||
ref="quillEditorRef"
|
||||
v-model:content="content"
|
||||
contentType="html"
|
||||
@textChange="(e) => $emit('update:modelValue', content)"
|
||||
:options="options"
|
||||
:style="styles"
|
||||
/>
|
||||
<quill-editor ref="quillEditorRef" :content="content" @update:content="content = $event" contentType="html"
|
||||
@textChange="(e) => $emit('update:modelValue', content)" :options="options" :style="styles" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -30,10 +18,11 @@
|
||||
import { QuillEditor } from "@vueup/vue-quill";
|
||||
import "@vueup/vue-quill/dist/vue-quill.snow.css";
|
||||
import { getToken } from "@/utils/auth";
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
import { ref, computed, watch, onMounted } from 'vue';
|
||||
import modal from '@/plugins/modal';
|
||||
|
||||
const quillEditorRef = ref();
|
||||
const uploadRef = ref();
|
||||
const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload"); // 上传的图片服务器地址
|
||||
const headers = ref({
|
||||
Authorization: "Bearer " + getToken()
|
||||
@@ -115,32 +104,34 @@ watch(() => props.modelValue, (v) => {
|
||||
// 如果设置了上传地址则自定义图片上传事件
|
||||
onMounted(() => {
|
||||
if (props.type == 'url') {
|
||||
let quill = quillEditorRef.value.getQuill();
|
||||
let quill = quillEditorRef.value?.getQuill();
|
||||
if (quill) {
|
||||
let toolbar = quill.getModule("toolbar");
|
||||
toolbar.addHandler("image", (value) => {
|
||||
if (value) {
|
||||
proxy.$refs.uploadRef.click();
|
||||
if (value && uploadRef.value) {
|
||||
uploadRef.value.click();
|
||||
} else {
|
||||
quill.format("image", false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 上传前校检格式和大小
|
||||
function handleBeforeUpload(file) {
|
||||
const type = ["image/jpeg", "image/jpg", "image/png", "image/svg"];
|
||||
const type = ["image/jpeg", "image/jpg", "image/png", "image/svg+xml"];
|
||||
const isJPG = type.includes(file.type);
|
||||
//检验文件格式
|
||||
if (!isJPG) {
|
||||
proxy.$modal.msgError(`图片格式错误!`);
|
||||
modal.msgError(`图片格式错误!`);
|
||||
return false;
|
||||
}
|
||||
// 校检文件大小
|
||||
if (props.fileSize) {
|
||||
const isLt = file.size / 1024 / 1024 < props.fileSize;
|
||||
if (!isLt) {
|
||||
proxy.$modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`);
|
||||
modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -152,21 +143,24 @@ function handleUploadSuccess(res, file) {
|
||||
// 如果上传成功
|
||||
if (res.code == 200) {
|
||||
// 获取富文本实例
|
||||
let quill = toRaw(quillEditorRef.value).getQuill();
|
||||
let quill = quillEditorRef.value?.getQuill();
|
||||
if (quill) {
|
||||
// 获取光标位置
|
||||
let length = quill.selection.savedRange.index;
|
||||
let range = quill.selection?.savedRange || quill.getSelection();
|
||||
let length = range?.index || 0;
|
||||
// 插入图片,res.url为服务器返回的图片链接地址
|
||||
quill.insertEmbed(length, "image", import.meta.env.VITE_APP_BASE_API + res.fileName);
|
||||
// 调整光标到最后
|
||||
quill.setSelection(length + 1);
|
||||
}
|
||||
} else {
|
||||
proxy.$modal.msgError("图片插入失败");
|
||||
modal.msgError("图片插入失败");
|
||||
}
|
||||
}
|
||||
|
||||
// 上传失败处理
|
||||
function handleUploadError() {
|
||||
proxy.$modal.msgError("图片插入失败");
|
||||
modal.msgError("图片插入失败");
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -174,76 +168,96 @@ function handleUploadError() {
|
||||
.editor-img-uploader {
|
||||
display: none;
|
||||
}
|
||||
.editor, .ql-toolbar {
|
||||
|
||||
.editor,
|
||||
.ql-toolbar {
|
||||
white-space: pre-wrap !important;
|
||||
line-height: normal !important;
|
||||
}
|
||||
|
||||
.quill-img {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ql-snow .ql-tooltip[data-mode="link"]::before {
|
||||
content: "请输入链接地址:";
|
||||
}
|
||||
|
||||
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
|
||||
border-right: 0px;
|
||||
content: "保存";
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.ql-snow .ql-tooltip[data-mode="video"]::before {
|
||||
content: "请输入视频地址:";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
|
||||
content: "14px";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
|
||||
content: "10px";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
|
||||
content: "18px";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
|
||||
content: "32px";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
|
||||
content: "文本";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
|
||||
content: "标题1";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
|
||||
content: "标题2";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
|
||||
content: "标题3";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
|
||||
content: "标题4";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
|
||||
content: "标题5";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
|
||||
content: "标题6";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
|
||||
content: "标准字体";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
|
||||
content: "衬线字体";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
|
||||
content: "等宽字体";
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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')
|
||||
@@ -33,8 +33,11 @@ router.beforeEach((to, from, next) => {
|
||||
// 根据roles权限生成可访问的路由表
|
||||
accessRoutes.forEach(route => {
|
||||
if (!isHttp(route.path)) {
|
||||
// 检查是否已经存在同名路由
|
||||
if (!router.hasRoute(route.name)) {
|
||||
router.addRoute(route) // 动态添加可访问路由表
|
||||
}
|
||||
}
|
||||
})
|
||||
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
|
||||
})
|
||||
|
||||
@@ -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)
|
||||
noCache: true // 如果设置为true,则不会被 <keep-alive> 缓存(默认 false)
|
||||
title: 'title' // 设置该路由在侧边栏和面包屑中展示的名字
|
||||
icon: 'svg-name' // 设置该路由的图标,对应路径src/assets/icons/svg
|
||||
breadcrumb: false // 如果设置为false,则不会在breadcrumb面包屑中显示
|
||||
activeMenu: '/system/user' // 当路由设置了该属性,则会高亮相对应的侧边栏。
|
||||
activeMenu: '/system/user' // 当路由设置了该属性,则会高亮对应的侧边栏
|
||||
}
|
||||
*/
|
||||
|
||||
// 公共路由
|
||||
// 公共路由 - 所有用户均可访问的路由
|
||||
export const constantRoutes = [
|
||||
{ path: '/appoinmentmanage', component: Layout, redirect: '/appoinmentmanage', name: 'AppoinmentManage', hidden: true, meta: { title: '预约管理', icon: 'component' }, children: [{ path: '', component: () => import('@/views/appoinmentmanage/index.vue'), name: 'AppoinmentManageIndex', meta: { title: '预约管理' } }, { path: '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;
|
||||
@@ -1,6 +1,8 @@
|
||||
<template>
|
||||
<!-- 跌倒/坠床评估护理记录单主容器 -->
|
||||
<div>
|
||||
<div class="business">
|
||||
<!-- 已有记录展示表格 -->
|
||||
<el-table
|
||||
:data="tableDataSource"
|
||||
border
|
||||
@@ -8,10 +10,15 @@
|
||||
fit
|
||||
:header-cell-style="{ background: '#f2f2f2', color: 'black' }"
|
||||
>
|
||||
<!-- 记录时间列 -->
|
||||
<el-table-column prop="content.recordTime" label="记录时间" />
|
||||
<!-- 评估分数列 -->
|
||||
<el-table-column prop="content.totalScore" label="评估分数" />
|
||||
<!-- 护理措施列 -->
|
||||
<el-table-column prop="content.patientCareSessionsTableList" label="护理措施" />
|
||||
<!-- 责任护士列 -->
|
||||
<el-table-column prop="content.nurseSignature" label="责任护士" />
|
||||
<!-- 操作列:编辑和删除按钮 -->
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
@@ -36,9 +43,12 @@
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 跌倒/坠床评估护理记录单表单区域 -->
|
||||
<div name="跌倒/坠床评估护理记录单" class="changeMajor" style="width: 99.9%">
|
||||
<div>
|
||||
<!-- 表单主体 -->
|
||||
<el-form ref="formRef" :model="form" style="width: 99.9%">
|
||||
<!-- 标题行 -->
|
||||
<el-form-item style="text-align: center">
|
||||
<div
|
||||
style="
|
||||
@@ -54,10 +64,12 @@
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 日期时间选择器 -->
|
||||
<el-form-item label="日期:" class="changeMajorFromItem" style="width: 100%">
|
||||
<el-row :span="20">
|
||||
<el-col :span="8" style="padding-left: 0px !important">
|
||||
<el-form-item>
|
||||
<!-- 日期时间选择器 -->
|
||||
<el-date-picker
|
||||
v-model="form.ZKDATE"
|
||||
type="datetime"
|
||||
@@ -67,6 +79,7 @@
|
||||
style="width: 800px"
|
||||
:disabled="admissionDataForm !== undefined"
|
||||
/>
|
||||
<!-- 时间选择器被注释掉 -->
|
||||
<!-- <span style="margin-left: 5px">时间:</span>
|
||||
<el-time-picker
|
||||
v-model="form.ZKTIME"
|
||||
@@ -77,6 +90,7 @@
|
||||
/> -->
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- 新增/保存按钮 -->
|
||||
<el-col :span="5">
|
||||
<el-button
|
||||
v-if="!updateFlag"
|
||||
@@ -100,6 +114,7 @@
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 危险因素评估表格 -->
|
||||
<el-form-item style="padding-top: 10px; margin: 0px !important">
|
||||
<el-table
|
||||
:data="dangerData"
|
||||
@@ -107,6 +122,7 @@
|
||||
:span-method="handleSpan"
|
||||
style="text-align: center"
|
||||
>
|
||||
<!-- 动态生成表格列 -->
|
||||
<el-table-column
|
||||
v-for="column in dangerColumns"
|
||||
:key="column.key"
|
||||
@@ -115,6 +131,7 @@
|
||||
:label="column.title"
|
||||
align="center"
|
||||
/>
|
||||
<!-- 选择列(复选框) -->
|
||||
<el-table-column prop="id" label="选择" width="80" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-checkbox v-model="row.checked" @change="handleDangerChange(row)" />
|
||||
@@ -123,6 +140,7 @@
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 总分显示 -->
|
||||
<el-form-item
|
||||
style="text-align: center; margin-bottom: 0px; padding: 0px"
|
||||
class="changeMajorFromItem"
|
||||
@@ -135,6 +153,7 @@
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 护理措施表格 -->
|
||||
<el-form-item style="padding-top: 10px">
|
||||
<el-table
|
||||
:data="nursingData"
|
||||
@@ -142,6 +161,7 @@
|
||||
:span-method="arraySpanMethod"
|
||||
style="width: 100%"
|
||||
>
|
||||
<!-- 动态生成表格列 -->
|
||||
<el-table-column
|
||||
v-for="column in nursingColumns"
|
||||
:key="column.key"
|
||||
@@ -150,6 +170,7 @@
|
||||
:label="column.title"
|
||||
align="center"
|
||||
/>
|
||||
<!-- 选择列(复选框) -->
|
||||
<el-table-column prop="id" label="选择" width="80" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-checkbox v-model="row.checked" @change="handleNursingChange(row)" />
|
||||
@@ -158,6 +179,7 @@
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 护士签字输入框 -->
|
||||
<el-form-item
|
||||
style="text-align: center; margin-bottom: 0px; padding: 0px"
|
||||
class="changeMajorFromItem"
|
||||
@@ -177,6 +199,7 @@
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 备注信息 -->
|
||||
<el-form-item>
|
||||
<el-row :span="20">
|
||||
<el-col :span="5">
|
||||
@@ -197,22 +220,24 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
// 组件选项定义
|
||||
defineOptions({
|
||||
name: 'FallBedFallAssessment',
|
||||
name: '跌倒/坠床评估护理记录单',
|
||||
});
|
||||
|
||||
// 导入所需模块
|
||||
import { ref, reactive, computed, onMounted } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
|
||||
// import { webapp_ws_ajax_run, urlAddRandomNo } from '@/utils/grwebapp';
|
||||
// import { useRoute, useRouter } from 'vue-router';
|
||||
|
||||
// 响应式数据
|
||||
// 使用路由相关功能
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
// 定义引用变量
|
||||
const queryRef = ref();
|
||||
const formRef = ref();
|
||||
|
||||
// 基本数据变量
|
||||
const wardCode = ref('');
|
||||
const patientId = ref('');
|
||||
const visitId = ref('');
|
||||
@@ -226,17 +251,18 @@ const totalScore = ref(0);
|
||||
const lastSubmit = ref('');
|
||||
const admissionDataForm = ref(route.params.admissionData);
|
||||
|
||||
// 表单数据模型
|
||||
const form = reactive({
|
||||
ZKDATE: '',
|
||||
ZKTIME: '',
|
||||
recordTime: '',
|
||||
totalScore: 0,
|
||||
bedFallRiskAssessmentList: [],
|
||||
nurseSignature: '',
|
||||
patientCareSessionsCheckedList: [],
|
||||
ZKDATE: '', // 日期
|
||||
ZKTIME: '', // 时间
|
||||
recordTime: '', // 记录时间
|
||||
totalScore: 0, // 总分
|
||||
bedFallRiskAssessmentList: [], // 跌倒风险评估列表
|
||||
nurseSignature: '', // 护士签名
|
||||
patientCareSessionsCheckedList: [], // 护理措施选中列表
|
||||
});
|
||||
|
||||
// 危险因素表格列
|
||||
// 危险因素表格列配置
|
||||
const dangerColumns = [
|
||||
{
|
||||
key: 'content',
|
||||
@@ -301,7 +327,7 @@ const dangerData = ref([
|
||||
{ id: '27', evalContent: '麻醉止痛剂', score: 2, checked: false },
|
||||
]);
|
||||
|
||||
// 护理措施表格列
|
||||
// 护理措施表格列配置
|
||||
const nursingColumns = [
|
||||
{
|
||||
key: 'content',
|
||||
@@ -338,21 +364,21 @@ const instructions = [
|
||||
'3.评分≥5,高度风险,每周至少评估一次,需采取适宜的预防措施,同时填写《预防患者跌倒/坠床知情告知书》',
|
||||
];
|
||||
|
||||
// 计算属性
|
||||
// 计算属性:计算选中的危险因素总分
|
||||
const calculate = computed(() => {
|
||||
return dangerData.value
|
||||
.filter((option) => option.checked)
|
||||
.reduce((total, option) => total + option.score, 0);
|
||||
});
|
||||
|
||||
// 计算属性:判断表单是否为空
|
||||
const isFormEmpty = computed(() => {
|
||||
return (
|
||||
form.ZKDATE === '' && form.ZKTIME === '' && form.recordTime === '' && form.nurseSignature === ''
|
||||
);
|
||||
});
|
||||
|
||||
// 方法 - 不再需要handleData方法,通过表单输入和按钮加载数据
|
||||
|
||||
// 危险因素选择变化处理函数
|
||||
const handleDangerChange = (row) => {
|
||||
totalScore.value = calculate.value;
|
||||
form.bedFallRiskAssessmentList = dangerData.value
|
||||
@@ -360,12 +386,14 @@ const handleDangerChange = (row) => {
|
||||
.map((item) => item.id);
|
||||
};
|
||||
|
||||
// 护理措施选择变化处理函数
|
||||
const handleNursingChange = (row) => {
|
||||
form.patientCareSessionsCheckedList = nursingData.value
|
||||
.filter((item) => item.checked)
|
||||
.map((item) => item.id);
|
||||
};
|
||||
|
||||
// 初始化函数:加载模拟数据
|
||||
const init = async () => {
|
||||
// 使用模拟数据,不再调用后端API
|
||||
try {
|
||||
@@ -427,6 +455,7 @@ const init = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 危险因素表格合并单元格处理函数
|
||||
const handleSpan = ({ row, column, rowIndex, columnIndex }) => {
|
||||
if (columnIndex === 0) {
|
||||
if (rowIndex === 0) {
|
||||
@@ -473,6 +502,7 @@ const handleSpan = ({ row, column, rowIndex, columnIndex }) => {
|
||||
return [1, 1];
|
||||
};
|
||||
|
||||
// 护理措施表格合并单元格处理函数
|
||||
const arraySpanMethod = ({ row, column, rowIndex, columnIndex }) => {
|
||||
// 护理措施
|
||||
if (columnIndex === 0) {
|
||||
@@ -489,8 +519,9 @@ const arraySpanMethod = ({ row, column, rowIndex, columnIndex }) => {
|
||||
return [1, 1];
|
||||
};
|
||||
|
||||
// 提交表单处理函数
|
||||
const onSubmit = async () => {
|
||||
// 检查上次提交时间
|
||||
// 检查上次提交时间,防止重复提交
|
||||
if (lastSubmit.value && new Date() - lastSubmit.value < 2000) {
|
||||
ElMessage.error('禁止重复提交!');
|
||||
return;
|
||||
@@ -562,6 +593,7 @@ const onSubmit = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 编辑记录处理函数
|
||||
const handleUpdate = (row) => {
|
||||
const loginUser = JSON.parse(window.localStorage.getItem('loginUser'));
|
||||
|
||||
@@ -591,6 +623,7 @@ const handleUpdate = (row) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 重置表单函数
|
||||
const reset = () => {
|
||||
Object.assign(form, {
|
||||
ZKDATE: '',
|
||||
@@ -623,6 +656,7 @@ const reset = () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 删除记录处理函数
|
||||
const handleDelete = (row) => {
|
||||
const loginUser = JSON.parse(window.localStorage.getItem('loginUser'));
|
||||
|
||||
@@ -646,6 +680,7 @@ const handleDelete = (row) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 打印预览函数(暂未实现)
|
||||
const dc_ajax_preview = () => {
|
||||
var args = {
|
||||
report: urlAddRandomNo('./grf/NurseRecord_Pressure_208.grf'),
|
||||
@@ -656,6 +691,7 @@ const dc_ajax_preview = () => {
|
||||
webapp_ws_ajax_run(args);
|
||||
};
|
||||
|
||||
// 数据转换函数,用于报表打印
|
||||
const transformData = () => {
|
||||
const jsonDate = [...tableDataSource.value];
|
||||
|
||||
@@ -802,7 +838,7 @@ const transformData = () => {
|
||||
return transformedData;
|
||||
};
|
||||
|
||||
// 生命周期钩子
|
||||
// 组件挂载后执行的生命周期函数
|
||||
onMounted(() => {
|
||||
try {
|
||||
// 安全获取用户信息
|
||||
@@ -831,6 +867,7 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 页面样式定义 */
|
||||
.business {
|
||||
background: white;
|
||||
border-radius: 5px;
|
||||
@@ -894,4 +931,10 @@ onMounted(() => {
|
||||
margin-bottom: 0px !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* 备注信息列表样式 */
|
||||
.instructions-list {
|
||||
list-style-type: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -1,17 +1,42 @@
|
||||
// 动态引入 template 目录下的所有 .vue 文件
|
||||
/**
|
||||
* 模板组件注册模块
|
||||
* 动态引入 template 目录下的所有 .vue 文件,并将它们注册为全局组件
|
||||
*/
|
||||
|
||||
// 动态引入 template 目录下的所有 .vue 文件(包括中文命名的文件)
|
||||
// 使用 { eager: true } 表示立即加载所有匹配的文件
|
||||
const templates = import.meta.glob('./*.vue', { eager: true });
|
||||
|
||||
// 存储所有加载的组件
|
||||
const components = [];
|
||||
|
||||
// 遍历所有引入的文件
|
||||
for (const path in templates) {
|
||||
try {
|
||||
// 获取组件的默认导出
|
||||
const component = templates[path].default;
|
||||
|
||||
// 检查组件是否有 name 属性,如果没有则跳过
|
||||
if (component && component.name) {
|
||||
components.push(component);
|
||||
} else {
|
||||
console.warn(`组件 ${path} 缺少 name 属性,将不会被注册`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`加载组件 ${path} 时出错:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册所有组件到 Vue 应用实例
|
||||
* @param {Object} app - Vue 应用实例
|
||||
*/
|
||||
const registerComponents = (app) => {
|
||||
components.forEach((component) => {
|
||||
// 使用组件的 name 属性作为组件名称进行注册
|
||||
app.component(component.name, component);
|
||||
})
|
||||
}
|
||||
export { components, registerComponents };
|
||||
});
|
||||
};
|
||||
|
||||
// 导出组件数组和注册函数
|
||||
export { components, registerComponents };
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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() {
|
||||
// 组件挂载后自动初始化数据
|
||||
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">
|
||||
|
||||
@@ -219,6 +219,7 @@ const templateName = ref('');
|
||||
// 事件
|
||||
const emits = defineEmits(['save']);
|
||||
const { proxy } = getCurrentInstance();
|
||||
console.log('EMR组件初始化,proxy:', proxy);
|
||||
|
||||
// 监听表单变化
|
||||
watch(
|
||||
@@ -325,16 +326,107 @@ function cancel() {
|
||||
// 暴露方法给父组件
|
||||
defineExpose({
|
||||
getDetail(encounterId) {
|
||||
getEmrDetail(encounterId).then((res) => {
|
||||
if (res.data) {
|
||||
try {
|
||||
form.value = JSON.parse(res.data.contextJson) || {};
|
||||
} catch (e) {
|
||||
console.log('开始获取病历详情,encounterId:', encounterId);
|
||||
|
||||
// 立即初始化form.value为空对象,确保页面有内容显示
|
||||
form.value = {};
|
||||
|
||||
// 检查API函数是否存在
|
||||
if (typeof getEmrDetail !== 'function') {
|
||||
console.error('getEmrDetail函数未定义');
|
||||
if (proxy) {
|
||||
proxy.$modal.msgError('获取病历详情失败:API函数未定义');
|
||||
}
|
||||
emits('save', true);
|
||||
return;
|
||||
}
|
||||
|
||||
// 添加超时处理,防止请求一直挂起
|
||||
const timeoutPromise = new Promise((_, reject) => {
|
||||
setTimeout(() => {
|
||||
reject(new Error('获取病历详情请求超时'));
|
||||
}, 10000); // 10秒超时
|
||||
});
|
||||
|
||||
// 使用Promise.race处理正常请求和超时
|
||||
Promise.race([getEmrDetail(encounterId), timeoutPromise])
|
||||
.then((res) => {
|
||||
console.log('获取病历详情成功,返回完整数据:', JSON.stringify(res, null, 2));
|
||||
|
||||
// 检查响应是否有效
|
||||
if (!res) {
|
||||
console.error('API返回结果为空');
|
||||
if (proxy) {
|
||||
proxy.$modal.msgError('获取病历详情失败:API返回结果为空');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('res存在,类型:', typeof res);
|
||||
console.log('res的属性:', Object.keys(res));
|
||||
|
||||
// 检查响应码
|
||||
if (res.code !== 200) {
|
||||
console.error('API返回错误代码:', res.code);
|
||||
if (proxy) {
|
||||
proxy.$modal.msgError('获取病历详情失败:' + (res.msg || '未知错误'));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查数据是否存在
|
||||
if (!res.data) {
|
||||
console.log('res.data为空,使用默认值');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('res.data存在,类型:', typeof res.data);
|
||||
console.log('res.data的属性:', Object.keys(res.data));
|
||||
|
||||
// 处理contextJson
|
||||
try {
|
||||
if (res.data.contextJson) {
|
||||
console.log('contextJson存在,值:', res.data.contextJson);
|
||||
console.log('contextJson类型:', typeof res.data.contextJson);
|
||||
|
||||
// 检查contextJson类型
|
||||
if (typeof res.data.contextJson === 'string') {
|
||||
// 尝试解析JSON字符串
|
||||
const parsedData = JSON.parse(res.data.contextJson);
|
||||
// 确保解析结果是对象
|
||||
if (typeof parsedData === 'object' && parsedData !== null) {
|
||||
form.value = parsedData;
|
||||
console.log('解析后的病历数据:', JSON.stringify(form.value, null, 2));
|
||||
} else {
|
||||
form.value = {};
|
||||
console.error('contextJson解析结果不是有效对象:', parsedData);
|
||||
}
|
||||
} else if (typeof res.data.contextJson === 'object') {
|
||||
// 如果已经是对象,直接使用
|
||||
form.value = res.data.contextJson;
|
||||
console.log('直接使用contextJson作为对象:', JSON.stringify(form.value, null, 2));
|
||||
} else {
|
||||
form.value = {};
|
||||
console.error('contextJson类型无效:', typeof res.data.contextJson);
|
||||
}
|
||||
} else {
|
||||
console.log('contextJson为空,使用默认值');
|
||||
}
|
||||
} catch (e) {
|
||||
form.value = {};
|
||||
console.error('病历数据解析失败:', e);
|
||||
console.error('解析失败的contextJson值:', res.data.contextJson);
|
||||
if (proxy) {
|
||||
proxy.$modal.msgError('病历数据解析失败');
|
||||
}
|
||||
}
|
||||
|
||||
emits('save', true);
|
||||
})
|
||||
.catch((error) => {
|
||||
// 处理API调用失败或超时的情况
|
||||
console.error('获取病历详情失败:', error);
|
||||
if (proxy) {
|
||||
proxy.$modal.msgError('获取病历详情失败:' + (error.message || '未知错误'));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1493,6 +1493,7 @@ const { proxy } = getCurrentInstance();
|
||||
const inputRefs = ref({}); // 存储输入框实例,格式: { rowIndex: { fieldName: el } }
|
||||
const requiredProps = ref([]); // 存储必填项 prop 顺序
|
||||
const totalAmount = ref(0);
|
||||
const groupMarkers = ref([]); // 存储分组标记,用于显示层级关系
|
||||
const { method_code, unit_code, rate_code, distribution_category_code, drord_doctor_type } = proxy.useDict(
|
||||
'method_code',
|
||||
'unit_code',
|
||||
|
||||
@@ -20,16 +20,16 @@
|
||||
<el-icon
|
||||
class="delete-icon"
|
||||
title="删除处方单"
|
||||
@click="handleDeletePrescriptionClick(index)"
|
||||
:class="{ 'disabled-icon': isPrescriptionDeletable(index) !== true }"
|
||||
@click="handleDeletePrescriptionClick(pIndex)"
|
||||
:class="{ 'disabled-icon': isPrescriptionDeletable(pIndex) !== true }"
|
||||
style="font-size: 20px !important; margin-left: 10px; color: #f56c6c"
|
||||
>
|
||||
<minus />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="summary">
|
||||
<span class="summary-item">药品数: {{ getPrescriptionMedicineCount(index) }}种</span>
|
||||
<span class="summary-item">总价: ¥ {{ getPrescriptionTotalPrice(index) }}</span>
|
||||
<span class="summary-item">药品数: {{ getPrescriptionMedicineCount(pIndex) }}种</span>
|
||||
<span class="summary-item">总价: ¥ {{ getPrescriptionTotalPrice(pIndex) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
@@ -570,7 +570,10 @@ function getList() {
|
||||
}
|
||||
|
||||
function getListInfo(addNewRow) {
|
||||
// 确保isAdding变量存在
|
||||
if (typeof isAdding !== 'undefined') {
|
||||
isAdding.value = false;
|
||||
}
|
||||
|
||||
// 确保有患者信息
|
||||
if (!props.patientInfo || !props.patientInfo.encounterId) {
|
||||
@@ -580,13 +583,17 @@ function getListInfo(addNewRow) {
|
||||
|
||||
getTcmAdviceList({ encounterId: props.patientInfo.encounterId }).then((res) => {
|
||||
if (res && res.data && Array.isArray(res.data)) {
|
||||
prescriptionList.value = res.data.map((item) => {
|
||||
// 清空当前处方列表
|
||||
tcmPrescriptionList.value = [];
|
||||
|
||||
// 处理返回的数据
|
||||
res.data.forEach((item) => {
|
||||
try {
|
||||
// 解析contentJson获取完整的医嘱数据
|
||||
const contentData = item.contentJson ? JSON.parse(item.contentJson) : {};
|
||||
|
||||
// 合并基础信息和contentJson中的详细信息
|
||||
return {
|
||||
// 创建一个新的处方对象
|
||||
const newPrescription = {
|
||||
...item,
|
||||
...contentData,
|
||||
// 确保关键显示字段存在
|
||||
@@ -596,11 +603,14 @@ function getListInfo(addNewRow) {
|
||||
diagnosisName: contentData.diagnosisName || item.diagnosisName || '',
|
||||
positionName: contentData.positionName || item.positionName || '',
|
||||
doseUnitCode_dictText: contentData.doseUnitCode_dictText || item.doseUnitCode_dictText || '',
|
||||
chineseHerbsDoseQuantity: contentData.chineseHerbsDoseQuantity || item.chineseHerbsDoseQuantity || ''
|
||||
chineseHerbsDoseQuantity: contentData.chineseHerbsDoseQuantity || item.chineseHerbsDoseQuantity || '',
|
||||
prescriptionList: [contentData]
|
||||
};
|
||||
|
||||
// 添加到处方列表
|
||||
tcmPrescriptionList.value.push(newPrescription);
|
||||
} catch (error) {
|
||||
console.error('解析医嘱数据失败:', error, '数据项:', item);
|
||||
return item; // 出错时返回原始数据
|
||||
}
|
||||
});
|
||||
|
||||
@@ -612,11 +622,11 @@ function getListInfo(addNewRow) {
|
||||
}
|
||||
} else {
|
||||
console.error('获取医嘱列表失败或数据格式错误:', res);
|
||||
prescriptionList.value = [];
|
||||
tcmPrescriptionList.value = [];
|
||||
}
|
||||
}).catch(error => {
|
||||
console.error('获取医嘱列表异常:', error);
|
||||
prescriptionList.value = [];
|
||||
tcmPrescriptionList.value = [];
|
||||
});
|
||||
|
||||
tcmDiagnosisList.value = getFromDiagnosis(props.patientInfo.encounterId);
|
||||
@@ -769,7 +779,8 @@ function handleDeletePrescriptionClick(prescriptionIndex) {
|
||||
}
|
||||
|
||||
// 检查是否有已签发的药品
|
||||
const hasChargedItems = prescriptionList.value.some(item => item.statusEnum === 2);
|
||||
const prescription = tcmPrescriptionList.value[prescriptionIndex];
|
||||
const hasChargedItems = prescription.prescriptionList.some(item => item.statusEnum === 2);
|
||||
if (hasChargedItems) {
|
||||
proxy.$modal.msgWarning('该处方单已收费,不能删除');
|
||||
return;
|
||||
@@ -793,16 +804,18 @@ function isPrescriptionDeletable(prescriptionIndex) {
|
||||
}
|
||||
|
||||
// 检查是否有已签发的药品
|
||||
const hasChargedItems = prescriptionList.value.some(item => item.statusEnum === 2);
|
||||
const hasChargedItems = tcmPrescriptionList.value.some(item =>
|
||||
item.prescriptionList && item.prescriptionList.some(med => med.statusEnum === 2)
|
||||
);
|
||||
return !hasChargedItems;
|
||||
}
|
||||
|
||||
// 计算处方总价
|
||||
function getPrescriptionTotalPrice(prescriptionIndex) {
|
||||
const prescription = prescriptionList.value[prescriptionIndex];
|
||||
const prescription = tcmPrescriptionList.value[prescriptionIndex];
|
||||
let totalPrice = 0;
|
||||
if (prescription && prescription.prescriptionDetailsList) {
|
||||
prescription.prescriptionDetailsList.forEach(item => {
|
||||
if (prescription && prescription.prescriptionList) {
|
||||
prescription.prescriptionList.forEach(item => {
|
||||
// 使用decimal.js确保精度计算
|
||||
const quantity = new Decimal(item.minUnitQuantity || 0);
|
||||
const unitPrice = new Decimal(item.unitPrice || 0);
|
||||
@@ -814,9 +827,11 @@ function getPrescriptionTotalPrice(prescriptionIndex) {
|
||||
|
||||
// 获取处方中的药品数量
|
||||
function getPrescriptionMedicineCount(prescriptionIndex) {
|
||||
// 这里需要根据实际的业务逻辑来计算
|
||||
// 假设每个处方对应一组药品,这里简化处理
|
||||
return prescriptionList.value.filter(item => item.statusEnum !== 2).length;
|
||||
const prescription = tcmPrescriptionList.value[prescriptionIndex];
|
||||
if (prescription && prescription.prescriptionList) {
|
||||
return prescription.prescriptionList.length;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -959,7 +974,9 @@ function handleDelete(pIndex) {
|
||||
prescription.expandOrder = [];
|
||||
prescription.isAdding = false;
|
||||
adviceQueryParams.value.adviceType = undefined;
|
||||
groupMarkers.value = getGroupMarkers(prescriptionList.value); // 删除行会出现组号混乱的情况,所以这里重新更新标记
|
||||
// 删除行会出现组号混乱的情况,所以这里重新更新标记
|
||||
const allPrescriptions = tcmPrescriptionList.value.flatMap(p => p.prescriptionList);
|
||||
groupMarkers.value = getGroupMarkers(allPrescriptions);
|
||||
}
|
||||
|
||||
|
||||
@@ -1115,10 +1132,21 @@ function handleSaveSign(row, index) {
|
||||
|
||||
|
||||
function handleSaveBatch() {
|
||||
let saveList = prescriptionList.value
|
||||
.filter((item) => {
|
||||
return item.statusEnum == 1;
|
||||
})
|
||||
// 收集所有需要保存的处方项目
|
||||
let saveList = [];
|
||||
|
||||
// 遍历所有处方
|
||||
for (const prescription of tcmPrescriptionList.value) {
|
||||
if (prescription.prescriptionList) {
|
||||
// 检查处方是否有必填的付数
|
||||
if (!prescription.chineseHerbsDoseQuantity || prescription.chineseHerbsDoseQuantity == 0) {
|
||||
proxy.$modal.msgWarning('请输入付数');
|
||||
return;
|
||||
}
|
||||
|
||||
// 收集该处方下需要保存的项目
|
||||
const itemsToSave = prescription.prescriptionList
|
||||
.filter((item) => item.statusEnum == 1)
|
||||
.map((item, index) => {
|
||||
return {
|
||||
...item,
|
||||
@@ -1130,30 +1158,37 @@ function handleSaveBatch() {
|
||||
patientId: props.patientInfo.patientId,
|
||||
requestId: item.requestId,
|
||||
groupId: item.groupId ? item.groupId : timestamp.toString(),
|
||||
|
||||
chineseHerbsDoseQuantity: prescription.chineseHerbsDoseQuantity,
|
||||
dbOpType: item.requestId ? '2' : '1',
|
||||
};
|
||||
});
|
||||
|
||||
// 将项目添加到保存列表
|
||||
saveList = saveList.concat(itemsToSave);
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否有可保存的项目
|
||||
if (saveList.length == 0) {
|
||||
proxy.$modal.msgWarning('当前没有可保存医嘱');
|
||||
return;
|
||||
}
|
||||
if (
|
||||
prescription.chineseHerbsDoseQuantity == undefined ||
|
||||
prescription.chineseHerbsDoseQuantity == 0
|
||||
) {
|
||||
proxy.$modal.msgWarning('请输入付数');
|
||||
return;
|
||||
}
|
||||
|
||||
// 保存处方
|
||||
saveTcmAdvice({ adviceSaveList: saveList }).then((res) => {
|
||||
if (res.code === 200) {
|
||||
proxy.$modal.msgSuccess('保存成功');
|
||||
getListInfo(true);
|
||||
|
||||
// 重置所有处方的nextId
|
||||
tcmPrescriptionList.value.forEach(prescription => {
|
||||
if (prescription.nextId) {
|
||||
prescription.nextId = 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 获取诊断列表
|
||||
function getFromDiagnosis(encounterId) {
|
||||
|
||||
@@ -3,43 +3,24 @@
|
||||
<div style="width: 15%; height: 100%; border: 1px solid #eee; border-right: 0">
|
||||
<div style="padding: 10px; border: 1px solid #eee; height: 50px; border-right: 0">
|
||||
<span>现诊患者</span>
|
||||
<el-badge
|
||||
:value="waitCount > 0 ? waitCount : ''"
|
||||
:max="10"
|
||||
style="float: right; color: #409eff; cursor: pointer; margin-right: 10px"
|
||||
>
|
||||
<el-badge :value="waitCount > 0 ? waitCount : ''" :max="10"
|
||||
style="float: right; color: #409eff; cursor: pointer; margin-right: 10px">
|
||||
<span @click="openDrawer"> 患者队列 </span>
|
||||
</el-badge>
|
||||
</div>
|
||||
<div style="width: 100%; padding: 10px">
|
||||
<el-input
|
||||
v-model="queryParams.searchKey"
|
||||
placeholder="请输入患者名"
|
||||
clearable
|
||||
style="width: 100%; margin-bottom: 10px"
|
||||
@keyup.enter="getPatientList"
|
||||
>
|
||||
<el-input v-model="queryParams.searchKey" placeholder="请输入患者名" clearable
|
||||
style="width: 100%; margin-bottom: 10px" @keyup.enter="getPatientList">
|
||||
<template #append>
|
||||
<el-button icon="Search" @click="getPatientList" />
|
||||
</template>
|
||||
</el-input>
|
||||
<el-date-picker
|
||||
v-model="registerTime"
|
||||
@change="handleTimeChange"
|
||||
type="date"
|
||||
style="width: 100%; margin-bottom: 10px"
|
||||
:clearable="false"
|
||||
placeholder="挂号时间"
|
||||
format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
<el-date-picker v-model="registerTime" @change="handleTimeChange" type="daterange"
|
||||
style="width: 100%; margin-bottom: 10px" :clearable="false" placeholder="挂号时间" format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD" />
|
||||
<el-scrollbar height="700px">
|
||||
<div
|
||||
v-for="(item, index) in patientList"
|
||||
:class="item.active ? 'patient-card actived' : 'patient-card'"
|
||||
:key="item.id"
|
||||
@click="handleCardClick(item, index)"
|
||||
>
|
||||
<div v-for="(item, index) in patientList" :class="item.active ? 'patient-card actived' : 'patient-card'"
|
||||
:key="item.id" @click="handleCardClick(item, index)">
|
||||
<div class="main-info-container">
|
||||
<!-- <el-avatar
|
||||
:size="30"
|
||||
@@ -78,8 +59,8 @@
|
||||
</div>
|
||||
<div class="disabled-wrapper" style="width: 85%; border: 1px solid #eee; position: relative">
|
||||
<div style="padding: 10px; border: 1px solid #eee; height: 50px; border-left: 0">
|
||||
<el-descriptions :column="5" class="patient-info-descriptions">
|
||||
<el-descriptions-item label="患者信息:" width="420">
|
||||
<el-descriptions :column="4">
|
||||
<el-descriptions-item label="患者信息:" width="150">
|
||||
{{
|
||||
Object.keys(patientInfo).length !== 0
|
||||
? patientInfo.patientName +
|
||||
@@ -88,47 +69,13 @@
|
||||
' / ' +
|
||||
patientInfo.genderEnum_enumText +
|
||||
' / ' +
|
||||
patientInfo.contractName +
|
||||
'/' +
|
||||
patientInfo.phone
|
||||
patientInfo.contractName
|
||||
: '-'
|
||||
}}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="挂号时间:" width="300">
|
||||
<el-descriptions-item label="挂号时间:" width="150">
|
||||
{{ Object.keys(patientInfo).length !== 0 ? formatDate(patientInfo.registerTime) : '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="医生:" width="250">
|
||||
{{ userStore.nickName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="" width="300">
|
||||
<el-button type="primary" plain @click.stop="handleFinish(patientInfo.encounterId)">
|
||||
完诊
|
||||
</el-button>
|
||||
<el-button type="primary" plain @click.stop="handleLeave(patientInfo.encounterId)">
|
||||
暂离
|
||||
</el-button>
|
||||
<el-button type="primary" plain @click.stop="handleRefund(patientInfo.encounterId)">
|
||||
退费
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click.stop="getEnPrescription(patientInfo.encounterId)"
|
||||
>
|
||||
处方单
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click.stop="
|
||||
() => {
|
||||
openDialog = true;
|
||||
}
|
||||
"
|
||||
>
|
||||
办理住院
|
||||
</el-button>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="医生:" width="150">{{
|
||||
userStore.name
|
||||
}}</el-descriptions-item>
|
||||
@@ -147,84 +94,44 @@
|
||||
<el-button type="primary" plain @click.stop="handleRefund(patientInfo.encounterId)">
|
||||
退费
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click.stop="getEnPrescription(patientInfo.encounterId)"
|
||||
>
|
||||
<el-button type="primary" plain @click.stop="getEnPrescription(patientInfo.encounterId)">
|
||||
处方单
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click.stop="openDialog = true"
|
||||
>
|
||||
<el-button type="primary" plain @click.stop="openDialog = true">
|
||||
办理住院
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click.stop="handleCancelEncounter"
|
||||
>
|
||||
<el-button type="primary" plain @click.stop="handleCancelEncounter">
|
||||
取消接诊
|
||||
</el-button>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
<div style="padding: 10px">
|
||||
<el-tabs
|
||||
type="card"
|
||||
style="width: 100%; height: 100%"
|
||||
v-loading="loading"
|
||||
v-model="activeTab"
|
||||
@tab-change="handleClick(activeTab)"
|
||||
>
|
||||
<el-tab-pane label="门诊病历" name="hospitalizationEmr">
|
||||
<hospitalizationEmr
|
||||
:patientInfo="patientInfo"
|
||||
:activeTab="activeTab"
|
||||
@emrSaved="handleEmrSaved"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tabs type="card" style="width: 100%; height: 100%" v-loading="loading" v-model="activeTab"
|
||||
@tab-change="handleClick(activeTab)">
|
||||
<el-tab-pane label="病历" name="emr">
|
||||
<Emr
|
||||
:patientInfo="patientInfo"
|
||||
ref="emrRef"
|
||||
@save="
|
||||
<Emr :patientInfo="patientInfo" ref="emrRef" @save="
|
||||
(value) => {
|
||||
saveStatus = value;
|
||||
}
|
||||
"
|
||||
:visitType="visitType"
|
||||
:firstVisitDate="firstVisitDate"
|
||||
/>
|
||||
" :visitType="visitType" :firstVisitDate="firstVisitDate" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="诊断" name="diagnosis">
|
||||
<Diagnosis
|
||||
:patientInfo="patientInfo"
|
||||
ref="diagnosisRef"
|
||||
@diagnosisSave="
|
||||
<Diagnosis :patientInfo="patientInfo" ref="diagnosisRef" @diagnosisSave="
|
||||
(value) => {
|
||||
saveStatus = value;
|
||||
}
|
||||
"
|
||||
/>
|
||||
" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="医嘱" name="prescription">
|
||||
<prescriptionlist
|
||||
:patientInfo="patientInfo"
|
||||
ref="prescriptionRef"
|
||||
:activeTab="activeTab"
|
||||
:outpatientEmrSaved="outpatientEmrSaved"
|
||||
/>
|
||||
<prescriptionlist :patientInfo="patientInfo" ref="prescriptionRef" :activeTab="activeTab" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="中医" name="tcm">
|
||||
<tcmAdvice :patientInfo="patientInfo" ref="tcmRef" />
|
||||
</el-tab-pane>
|
||||
<!-- <el-tab-pane label="电子处方" name="eprescription">
|
||||
<el-tab-pane label="电子处方" name="eprescription">
|
||||
<eprescriptionlist :patientInfo="patientInfo" ref="eprescriptionRef" />
|
||||
</el-tab-pane>
|
||||
-->
|
||||
</el-tabs>
|
||||
<div class="overlay" v-if="disabled"></div>
|
||||
</div>
|
||||
@@ -232,27 +139,15 @@
|
||||
<el-drawer v-model="drawer" title="患者队列" direction="ltr" @open="handleOpen">
|
||||
<PatientList ref="patientDrawerRef" @toCurrent="handleReceive" />
|
||||
</el-drawer>
|
||||
<RefundListDialog
|
||||
:open="openRefundListDialog"
|
||||
:encounterId="currentEncounterId"
|
||||
@close="openRefundListDialog = false"
|
||||
@refresh="() => prescriptionRef.getListInfo()"
|
||||
/>
|
||||
<HospitalizationDialog
|
||||
:open="openDialog"
|
||||
:patientInfo="patientInfo"
|
||||
:encounterId="currentEncounterId"
|
||||
@close="openDialog = false"
|
||||
/>
|
||||
<PrescriptionInfo
|
||||
:open="openPrescriptionDialog"
|
||||
:precriptionInfo="prescriptionInfo"
|
||||
@close="openPrescriptionDialog = false"
|
||||
/>
|
||||
<RefundListDialog :open="openRefundListDialog" :encounterId="currentEncounterId"
|
||||
@close="openRefundListDialog = false" />
|
||||
<HospitalizationDialog :open="openDialog" :patientInfo="patientInfo" :encounterId="currentEncounterId"
|
||||
@close="openDialog = false" />
|
||||
<PrescriptionInfo :open="openPrescriptionDialog" :precriptionInfo="prescriptionInfo"
|
||||
@close="openPrescriptionDialog = false" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import hospitalizationEmr from './components/hospitalizationEmr/index.vue';
|
||||
import Emr from './components/emr/emr.vue';
|
||||
import {
|
||||
getList,
|
||||
@@ -267,14 +162,13 @@ import RefundListDialog from './components/prescription/refundListDialog.vue';
|
||||
import PatientList from './components/patientList.vue';
|
||||
import Diagnosis from './components/diagnosis/diagnosis.vue';
|
||||
import PrescriptionInfo from './components/prescription/prescriptionInfo.vue';
|
||||
// import eprescriptionlist from './components/eprescriptionlist.vue';
|
||||
import eprescriptionlist from './components/eprescriptionlist.vue';
|
||||
import HospitalizationDialog from './components/hospitalizationDialog.vue';
|
||||
import tcmAdvice from './components/tcm/tcmAdvice.vue';
|
||||
import { formatDate, formatDateStr } from '@/utils/index';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
import { nextTick } from 'vue';
|
||||
import { onBeforeRouteLeave } from 'vue-router';
|
||||
import { updatePatientInfo } from './components/store/patient.js';
|
||||
|
||||
// // 监听路由离开事件
|
||||
// onBeforeRouteLeave((to, from, next) => {
|
||||
@@ -303,18 +197,15 @@ const openRefundListDialog = ref(false);
|
||||
const openDialog = ref(false);
|
||||
const openPrescriptionDialog = ref(false);
|
||||
const saveStatus = ref(false);
|
||||
const outpatientEmrSaved = ref(false); // 门诊病历保存状态
|
||||
const currentEncounterId = ref('');
|
||||
const emits = defineEmits(['click']);
|
||||
// const activeTab = ref('emr');
|
||||
const activeTab = ref('hospitalizationEmr');
|
||||
|
||||
const activeTab = ref('emr');
|
||||
const patientList = ref([]);
|
||||
const patientInfo = ref({});
|
||||
const visitTypeDisabled = ref(false);
|
||||
|
||||
const prescriptionInfo = ref([]);
|
||||
const registerTime = ref(formatDate(new Date()));
|
||||
const registerTime = ref([formatDate(new Date()), formatDate(new Date())]);
|
||||
const patientDrawerRef = ref();
|
||||
const prescriptionRef = ref();
|
||||
const tcmRef = ref();
|
||||
@@ -328,41 +219,12 @@ const firstVisitDate = ref('');
|
||||
const disabled = computed(() => {
|
||||
return Object.keys(patientInfo.value).length === 0;
|
||||
});
|
||||
const shortcuts = [
|
||||
{
|
||||
text: '今天',
|
||||
value: new Date(),
|
||||
},
|
||||
{
|
||||
text: '昨天',
|
||||
value: () => {
|
||||
const date = new Date();
|
||||
date.setDate(date.getDate() - 1);
|
||||
return date;
|
||||
},
|
||||
},
|
||||
{
|
||||
text: '三天内',
|
||||
value: () => {
|
||||
const date = new Date();
|
||||
date.setDate(date.getDate() - 3);
|
||||
return date;
|
||||
},
|
||||
},
|
||||
{
|
||||
text: '一周内',
|
||||
value: () => {
|
||||
const date = new Date();
|
||||
date.setDate(date.getDate() - 7);
|
||||
return date;
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
// const eprescriptionRef = ref();
|
||||
const eprescriptionRef = ref();
|
||||
onMounted(() => {
|
||||
getWaitPatient();
|
||||
});
|
||||
|
||||
getPatientList();
|
||||
// 获取现诊患者列表
|
||||
function getPatientList() {
|
||||
@@ -451,9 +313,9 @@ function handleClick(tab) {
|
||||
case 'tcm':
|
||||
tcmRef.value.getDiagnosisInfo();
|
||||
break;
|
||||
// case 'eprescription':
|
||||
// eprescriptionRef.value.getList();
|
||||
// break;
|
||||
case 'eprescription':
|
||||
eprescriptionRef.value.getList();
|
||||
break;
|
||||
}
|
||||
// if (tab != 'emr') {
|
||||
// if (!saveStatus.value) {
|
||||
@@ -471,11 +333,6 @@ function handleClick(tab) {
|
||||
|
||||
// 查看本次就诊处方单(从医嘱Tab页获取已开立的处方单信息)
|
||||
function getEnPrescription(encounterId) {
|
||||
getEnPrescriptionInfo({ encounterId: encounterId }).then((res) => {
|
||||
console.log('处方单 res', res);
|
||||
prescriptionInfo.value = res.data.records;
|
||||
openPrescriptionDialog.value = true;
|
||||
});
|
||||
// 检查是否有选中的患者
|
||||
if (!patientInfo.value || !patientInfo.value.encounterId) {
|
||||
proxy.$modal.msgWarning('请先选择患者');
|
||||
@@ -553,9 +410,6 @@ function handleCardClick(item, index) {
|
||||
patient.active = patient.encounterId === item.encounterId;
|
||||
});
|
||||
patientInfo.value = item;
|
||||
// 将患者信息保存到store中,供hospitalizationEmr组件使用
|
||||
updatePatientInfo(item);
|
||||
activeTab.value = 'hospitalizationEmr';
|
||||
|
||||
// 优先使用数据库中保存的初复诊值
|
||||
if (item.visitType) {
|
||||
@@ -572,11 +426,17 @@ function handleCardClick(item, index) {
|
||||
}
|
||||
activeTab.value = 'emr';
|
||||
nextTick(() => {
|
||||
prescriptionRef.value.getListInfo();
|
||||
tcmRef.value.getListInfo();
|
||||
diagnosisRef.value.getList();
|
||||
// eprescriptionRef.value.getList();
|
||||
// 确保所有组件引用都已初始化
|
||||
if (prescriptionRef.value) prescriptionRef.value.getListInfo();
|
||||
if (tcmRef.value) tcmRef.value.getListInfo();
|
||||
if (diagnosisRef.value) diagnosisRef.value.getList();
|
||||
if (eprescriptionRef.value) eprescriptionRef.value.getList();
|
||||
if (emrRef.value) {
|
||||
emrRef.value.getDetail(item.encounterId);
|
||||
} else {
|
||||
console.error('emr组件未正确初始化');
|
||||
proxy.$modal.msgError('病历组件加载失败,请刷新页面重试');
|
||||
}
|
||||
setTimeout(() => {
|
||||
loading.value = false;
|
||||
}, 200);
|
||||
@@ -606,8 +466,8 @@ function handleFinish(encounterId) {
|
||||
}
|
||||
|
||||
function handleTimeChange(value) {
|
||||
queryParams.value.registerTimeSTime = value + ' 00:00:00';
|
||||
queryParams.value.registerTimeETime = value + ' 23:59:59';
|
||||
queryParams.value.registerTimeSTime = value[0] + ' 00:00:00';
|
||||
queryParams.value.registerTimeETime = value[1] + ' 23:59:59';
|
||||
getPatientList();
|
||||
}
|
||||
|
||||
@@ -620,11 +480,6 @@ function handleReceive(row) {
|
||||
getWaitPatient();
|
||||
}
|
||||
|
||||
// 处理门诊病历保存成功事件
|
||||
function handleEmrSaved(isSaved) {
|
||||
outpatientEmrSaved.value = isSaved;
|
||||
}
|
||||
|
||||
function openDrawer() {
|
||||
drawer.value = true;
|
||||
}
|
||||
@@ -655,16 +510,6 @@ function handleCancelEncounter(){
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
// 患者信息
|
||||
.patient-info-descriptions {
|
||||
:deep(.el-descriptions__label) {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
:deep(.el-descriptions__content) {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.patient-card {
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
@@ -817,6 +662,7 @@ function handleCancelEncounter(){
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-tabs__header) {
|
||||
padding: 0;
|
||||
position: relative;
|
||||
@@ -826,19 +672,23 @@ function handleCancelEncounter(){
|
||||
:deep(.el-drawer__header) {
|
||||
margin-bottom: 15px !important;
|
||||
}
|
||||
|
||||
:deep(.el-drawer__body) {
|
||||
padding: 10px !important;
|
||||
}
|
||||
|
||||
.el-badge {
|
||||
--el-badge-padding: 6px;
|
||||
}
|
||||
|
||||
.disabled-wrapper .overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 999; /* 确保覆盖在内容上方 */
|
||||
z-index: 999;
|
||||
/* 确保覆盖在内容上方 */
|
||||
cursor: not-allowed;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* @Description: 申请单 (检验、检查、输血、手术)
|
||||
-->
|
||||
<template>
|
||||
<div>
|
||||
<div class="applicationForm-bottom-btn">
|
||||
<el-button-group>
|
||||
<el-button
|
||||
@@ -52,13 +53,14 @@
|
||||
</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,7 +234,8 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
// 获取医疗机构列表
|
||||
getUserBindTenantList().then((res) => {
|
||||
if (loginForm.value.username) {
|
||||
getUserBindTenantList(loginForm.value.username).then((res) => {
|
||||
tenantOptions.value = res.data.map(item => ({
|
||||
label: item.tenantName,
|
||||
value: item.id
|
||||
@@ -245,6 +246,7 @@ onMounted(() => {
|
||||
currentTenantName.value = tenantOptions.value[0].label;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function handleLogin() {
|
||||
@@ -476,7 +478,10 @@ function handleUserName(value) {
|
||||
//getCode();
|
||||
getCookie();
|
||||
|
||||
// 只有当 username 存在时才获取租户列表
|
||||
if (loginForm.value.username) {
|
||||
getTenantList(loginForm.value.username);
|
||||
}
|
||||
</script>
|
||||
|
||||
<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
@@ -16,97 +16,147 @@
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="挂号处理" name="tab3">
|
||||
<el-form ref="formRef" :model="formData" label-width="120px" class="config-form">
|
||||
<el-form ref="formRef" :model="formData" label-width="150px" class="config-form compact-form">
|
||||
<!-- 第一行 -->
|
||||
<div class="form-row">
|
||||
<el-form-item label="病历本费用(元)" prop="medicalRecordFee" style="margin-right: 20px;">
|
||||
<el-input v-model="formData.medicalRecordFee" style="width: 180px" />
|
||||
<el-form-item label="病历本费用(元)" prop="medicalRecordFee">
|
||||
<el-input-number v-model="formData.medicalRecordFee" style="width: 150px" :controls-position="'right'" :step="1" :min="0" />
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-left: 20px;">
|
||||
<el-checkbox v-model="formData.medicalRecordFlag">病历费入账标志</el-checkbox>
|
||||
<el-form-item label="" prop="medicalRecordFlag" checkbox-label>
|
||||
<template #label>
|
||||
<div class="checkbox-label-container">
|
||||
<el-checkbox v-model="formData.medicalRecordFlag" style="margin-right: 8px;" />
|
||||
<span>病历费入账标志</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<!-- 第二行 -->
|
||||
<div class="form-row">
|
||||
<el-form-item label="就诊卡费(元)" prop="patientCardFee" style="margin-right: 20px;">
|
||||
<el-input v-model="formData.patientCardFee" style="width: 180px" />
|
||||
<el-form-item label="就诊卡费(元)" prop="patientCardFee">
|
||||
<el-input-number v-model="formData.patientCardFee" style="width: 150px" :controls-position="'right'" :step="1" :min="0" />
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-left: 20px;">
|
||||
<el-checkbox v-model="formData.isNightShift">是否启用晚班</el-checkbox>
|
||||
<el-form-item label="" prop="isNightShift" checkbox-label>
|
||||
<template #label>
|
||||
<div class="checkbox-label-container">
|
||||
<el-checkbox v-model="formData.isNightShift" style="margin-right: 8px;" />
|
||||
<span>是否启用晚班</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<!-- 第三行 -->
|
||||
<div class="form-row">
|
||||
<el-form-item style="margin-right: 40px;">
|
||||
<el-checkbox v-model="formData.patientCardFlag">就诊卡记账标志</el-checkbox>
|
||||
<el-form-item label="" prop="patientCardFlag" checkbox-label>
|
||||
<template #label>
|
||||
<div class="checkbox-label-container">
|
||||
<el-checkbox v-model="formData.patientCardFlag" style="margin-right: 8px;" />
|
||||
<span>就诊卡记账标志</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-form-item>
|
||||
<el-form-item label="上午接诊起始时间" prop="morningStartTime" style="width: 300px; white-space: nowrap;">
|
||||
<el-input v-model="formData.morningStartTime" style="width: 120px" />
|
||||
<el-form-item label="上午接诊起始时间" prop="morningStartTime">
|
||||
<el-input v-model="formData.morningStartTime" style="width: 150px" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<!-- 第四行 -->
|
||||
<div class="form-row">
|
||||
<el-form-item style="margin-right: 40px;">
|
||||
<el-checkbox v-model="formData.autoGenerateOutpatientNo">自动产生门诊号</el-checkbox>
|
||||
<el-form-item label="" prop="autoGenerateOutpatientNo" checkbox-label>
|
||||
<template #label>
|
||||
<div class="checkbox-label-container">
|
||||
<el-checkbox v-model="formData.autoGenerateOutpatientNo" style="margin-right: 8px;" />
|
||||
<span>自动产生门诊号</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-right: 40px;">
|
||||
<el-checkbox v-model="formData.allowModifyOutpatientNo">建档时是否允许修改门诊号</el-checkbox>
|
||||
<el-form-item label="" prop="allowModifyOutpatientNo" checkbox-label>
|
||||
<template #label>
|
||||
<div class="checkbox-label-container">
|
||||
<el-checkbox v-model="formData.allowModifyOutpatientNo" style="margin-right: 8px;" />
|
||||
<span>允许修改门诊号</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<!-- 第五行 -->
|
||||
<div class="form-row">
|
||||
<el-form-item label="下午起始时间" prop="afternoonStartTime" style="margin-right: 40px;">
|
||||
<el-input v-model="formData.afternoonStartTime" style="width: 120px" />
|
||||
<el-form-item label="下午起始时间" prop="afternoonStartTime">
|
||||
<el-input v-model="formData.afternoonStartTime" style="width: 150px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="晚上起始时间" prop="eveningStartTime">
|
||||
<el-input v-model="formData.eveningStartTime" style="width: 120px" />
|
||||
<el-input v-model="formData.eveningStartTime" style="width: 150px" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<!-- 第六行 -->
|
||||
<div class="form-row">
|
||||
<el-form-item label="挂号有效期" prop="registrationValidity" style="margin-right: 40px;">
|
||||
<el-input v-model="formData.registrationValidity" style="width: 120px" />
|
||||
<el-form-item label="挂号有效期" prop="registrationValidity">
|
||||
<el-input-number v-model="formData.registrationValidity" style="width: 150px" :controls-position="'right'" :step="1" :min="0" />
|
||||
</el-form-item>
|
||||
<el-form-item label="挂号单据模式" prop="registrationDocumentMode">
|
||||
<el-select v-model="formData.registrationDocumentMode" style="width: 150px">
|
||||
<el-option label="使用发票" value="使用发票" />
|
||||
<el-option label="其他模式" value="其他模式" />
|
||||
<el-option label="普通单据" value="其他模式" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<!-- 第七行 -->
|
||||
<div class="form-row">
|
||||
<el-form-item style="margin-right: 40px;">
|
||||
<el-checkbox v-model="formData.exemptFlag">减免标志</el-checkbox>
|
||||
<el-form-item label="" prop="exemptFlag" checkbox-label>
|
||||
<template #label>
|
||||
<div class="checkbox-label-container">
|
||||
<el-checkbox v-model="formData.exemptFlag" style="margin-right: 8px;" />
|
||||
<span>减免标志</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-right: 40px;">
|
||||
<el-checkbox v-model="formData.consultationFlag">义诊标志</el-checkbox>
|
||||
<el-form-item label="" prop="consultationFlag" checkbox-label>
|
||||
<template #label>
|
||||
<div class="checkbox-label-container">
|
||||
<el-checkbox v-model="formData.consultationFlag" style="margin-right: 8px;" />
|
||||
<span>义诊标志</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-right: 40px;">
|
||||
<el-checkbox v-model="formData.enableHolidayFeeFloat">启用法定节假日挂号费浮动</el-checkbox>
|
||||
<el-form-item label="" prop="enableHolidayFeeFloat" checkbox-label>
|
||||
<template #label>
|
||||
<div class="checkbox-label-container">
|
||||
<el-checkbox v-model="formData.enableHolidayFeeFloat" style="margin-right: 8px;" />
|
||||
<span>节假日费浮动</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<!-- 第八行 -->
|
||||
<div class="form-row">
|
||||
<el-form-item label="监护人规定年龄" prop="guardianAge" style="margin-right: 40px;">
|
||||
<el-input v-model="formData.guardianAge" style="width: 120px" />
|
||||
<el-form-item label="监护人规定年龄" prop="guardianAge">
|
||||
<el-input-number v-model="formData.guardianAge" style="width: 150px" :controls-position="'right'" :step="1" :min="0" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-checkbox v-model="formData.enableDoubleScreen">门诊挂号启用双屏</el-checkbox>
|
||||
<el-form-item label="" prop="enableDoubleScreen" checkbox-label>
|
||||
<template #label>
|
||||
<div class="checkbox-label-container">
|
||||
<el-checkbox v-model="formData.enableDoubleScreen" style="margin-right: 8px;" />
|
||||
<span>挂号启用双屏</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<!-- 第九行 -->
|
||||
<div class="form-row">
|
||||
<el-form-item>
|
||||
<el-checkbox v-model="formData.optionalRegistrationType">挂号类型可选择</el-checkbox>
|
||||
<el-form-item label="" prop="optionalRegistrationType" checkbox-label>
|
||||
<template #label>
|
||||
<div class="checkbox-label-container">
|
||||
<el-checkbox v-model="formData.optionalRegistrationType" style="margin-right: 8px;" />
|
||||
<span>挂号类型可选择</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
@@ -132,10 +182,10 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive } from 'vue';
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { getConfigKey, addConfig, updateConfig } from '@/api/system/config';
|
||||
import { listConfig, getConfigKey, addConfig, updateConfig } from '@/api/system/config';
|
||||
|
||||
const router = useRouter();
|
||||
const formRef = ref(null);
|
||||
@@ -164,6 +214,61 @@ const formData = reactive({
|
||||
isPrint: false,
|
||||
});
|
||||
|
||||
// 加载配置数据
|
||||
const loadConfigData = async (showSuccessMessage = true) => {
|
||||
try {
|
||||
// 调用系统配置API获取数据,不设置configType过滤条件以获取所有配置
|
||||
const response = await listConfig({ pageSize: 1000 });
|
||||
|
||||
// 处理响应数据,兼容不同的返回格式
|
||||
let configs = [];
|
||||
if (response && response.data) {
|
||||
if (Array.isArray(response.data)) {
|
||||
configs = response.data;
|
||||
} else if (response.data.rows && Array.isArray(response.data.rows)) {
|
||||
configs = response.data.rows;
|
||||
} else {
|
||||
console.error('返回数据格式不符合预期:', response);
|
||||
}
|
||||
} else if (response && response.rows && Array.isArray(response.rows)) {
|
||||
configs = response.rows;
|
||||
} else {
|
||||
console.error('API返回空响应:', response);
|
||||
}
|
||||
|
||||
console.log('loadConfigData - 获取到的配置列表:', configs);
|
||||
console.log('loadConfigData - 配置总数:', configs.length);
|
||||
|
||||
// 将配置数据映射到表单
|
||||
if (configs && configs.length > 0) {
|
||||
configs.forEach(config => {
|
||||
const { configKey, configValue } = config;
|
||||
|
||||
// 处理布尔类型字段
|
||||
if (configKey in formData) {
|
||||
if (typeof formData[configKey] === 'boolean') {
|
||||
formData[configKey] = configValue === '1';
|
||||
} else {
|
||||
formData[configKey] = configValue;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (showSuccessMessage) {
|
||||
ElMessage.success('配置数据加载成功');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载配置数据失败:', error);
|
||||
ElMessage.warning('无法加载配置数据,使用默认值');
|
||||
}
|
||||
};
|
||||
|
||||
// 组件挂载时加载数据
|
||||
onMounted(() => {
|
||||
loadConfigData();
|
||||
});
|
||||
|
||||
// 默认按钮点击事件
|
||||
const handleDefault = () => {
|
||||
// 重置为默认值
|
||||
@@ -225,40 +330,88 @@ const handleSave = async () => {
|
||||
let successCount = 0;
|
||||
let failedParams = [];
|
||||
|
||||
try {
|
||||
// 先获取所有配置,避免重复调用API
|
||||
const allConfigsResponse = await listConfig({ pageSize: 1000 });
|
||||
console.log('handleSave - listConfig返回完整结果:', JSON.stringify(allConfigsResponse));
|
||||
|
||||
// 检查返回结果结构
|
||||
let allConfigs = [];
|
||||
if (allConfigsResponse.code === 200) {
|
||||
if (allConfigsResponse.data && Array.isArray(allConfigsResponse.data)) {
|
||||
allConfigs = allConfigsResponse.data;
|
||||
} else if (allConfigsResponse.data && allConfigsResponse.data.rows) {
|
||||
allConfigs = allConfigsResponse.data.rows;
|
||||
} else if (Array.isArray(allConfigsResponse.rows)) {
|
||||
allConfigs = allConfigsResponse.rows;
|
||||
} else if (Array.isArray(allConfigsResponse)) {
|
||||
allConfigs = allConfigsResponse;
|
||||
}
|
||||
}
|
||||
|
||||
console.log('handleSave - 最终获取到的所有配置:', allConfigs);
|
||||
console.log('handleSave - 配置总数:', allConfigs.length);
|
||||
|
||||
// 构建配置项映射表,方便快速查找
|
||||
const configMap = new Map();
|
||||
allConfigs.forEach(config => {
|
||||
configMap.set(config.configKey, config);
|
||||
console.log('handleSave - 添加到映射表:', config.configKey);
|
||||
});
|
||||
|
||||
// 调用系统配置API保存每个参数
|
||||
for (const config of configData) {
|
||||
try {
|
||||
// 先查询是否存在该配置
|
||||
const existingConfig = await getConfigKey(config.configKey, { skipErrorMsg: true });
|
||||
const existingConfig = configMap.get(config.configKey);
|
||||
|
||||
if (existingConfig.data && existingConfig.data.configId) {
|
||||
// 如果存在则更新,保留原有数据的configId
|
||||
await updateConfig({
|
||||
console.log(`处理参数: ${config.configName} (${config.configKey})`);
|
||||
console.log(`现有配置:`, existingConfig);
|
||||
console.log(`要保存的值:`, config.configValue);
|
||||
|
||||
if (existingConfig && existingConfig.configId) {
|
||||
// 如果存在则更新,保留原有数据的configId和创建时间
|
||||
console.log(`更新参数 ${config.configKey},使用configId: ${existingConfig.configId}`);
|
||||
const updateResult = await updateConfig({
|
||||
...config,
|
||||
configId: existingConfig.data.configId,
|
||||
createTime: existingConfig.data.createTime, // 保留创建时间
|
||||
remark: existingConfig.data.remark || '收费系统配置参数' // 保留或设置默认备注
|
||||
configId: existingConfig.configId,
|
||||
createTime: existingConfig.createTime,
|
||||
remark: existingConfig.remark || '收费系统配置参数',
|
||||
configType: existingConfig.configType || 'N'
|
||||
});
|
||||
console.log(`更新结果:`, updateResult);
|
||||
} else {
|
||||
// 如果不存在则新增,添加默认备注
|
||||
await addConfig({
|
||||
console.log(`新增参数 ${config.configKey}`);
|
||||
const addResult = await addConfig({
|
||||
...config,
|
||||
remark: '收费系统配置参数'
|
||||
remark: '收费系统配置参数',
|
||||
configType: 'N'
|
||||
});
|
||||
console.log(`新增结果:`, addResult);
|
||||
}
|
||||
successCount++;
|
||||
} catch (paramError) {
|
||||
console.error(`保存参数 ${config.configName} (${config.configKey}) 失败:`, paramError);
|
||||
console.error(`错误详情:`, paramError.response || paramError);
|
||||
failedParams.push(config.configName);
|
||||
// 继续处理下一个参数,不中断整体流程
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取配置列表失败:', error);
|
||||
ElMessage.error('获取配置列表失败,无法保存参数');
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据保存结果显示相应消息
|
||||
if (failedParams.length === 0) {
|
||||
ElMessage.success(`所有 ${successCount} 个参数保存成功`);
|
||||
ElMessage.success(`保存成功`);
|
||||
// 保存成功后重新加载数据,确保页面显示最新配置
|
||||
loadConfigData(false); // 不显示加载成功消息
|
||||
} else if (successCount > 0) {
|
||||
ElMessage.warning(`${successCount} 个参数保存成功,但以下 ${failedParams.length} 个参数保存失败: ${failedParams.join(', ')}`);
|
||||
// 部分成功也重新加载数据
|
||||
loadConfigData(false); // 不显示加载成功消息
|
||||
} else {
|
||||
ElMessage.error(`所有参数保存失败,请检查系统配置`);
|
||||
}
|
||||
@@ -300,23 +453,96 @@ const handleClose = () => {
|
||||
.form-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 5px;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 15px;
|
||||
flex-wrap: nowrap; /* 禁止行内元素换行 */
|
||||
overflow-x: hidden; /* 防止溢出 */
|
||||
}
|
||||
|
||||
.config-form .el-form-item {
|
||||
margin-bottom: 0;
|
||||
margin-right: 0;
|
||||
margin-right: 60px; /* 增加间距 */
|
||||
min-width: 350px; /* 增加最小宽度 */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0; /* 禁止压缩 */
|
||||
}
|
||||
|
||||
/* 紧凑表单样式 */
|
||||
.compact-form {
|
||||
label-width: 150px !important;
|
||||
}
|
||||
|
||||
.compact-form .el-form-item {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* 所有表单标签的统一样式 */
|
||||
.config-form .el-form-item__label {
|
||||
font-weight: 500;
|
||||
width: 120px;
|
||||
width: 220px !important; /* 足够宽的标签宽度 */
|
||||
text-align: right;
|
||||
padding-right: 15px;
|
||||
white-space: nowrap !important; /* 强制不换行 */
|
||||
overflow: visible !important; /* 允许内容溢出(确保不截断) */
|
||||
text-overflow: clip !important; /* 不显示省略号 */
|
||||
flex-shrink: 0 !important; /* 禁止压缩 */
|
||||
font-size: 14px !important; /* 统一字体大小 */
|
||||
line-height: 32px !important; /* 统一行高 */
|
||||
height: 32px !important; /* 统一高度 */
|
||||
margin: 0 !important; /* 清除默认边距 */
|
||||
padding: 0 15px 0 0 !important; /* 统一内边距 */
|
||||
}
|
||||
|
||||
/* 复选框标签样式 */
|
||||
.compact-form .el-form-item[checkbox-label] .el-form-item__label {
|
||||
padding-right: 10px;
|
||||
width: 150px !important;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.compact-form .el-form-item[checkbox-label] .el-form-item__content {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
/* 自定义复选框标签容器 */
|
||||
.checkbox-label-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.checkbox-label-container span {
|
||||
font-size: 14px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* 空标签的样式,用于对齐 */
|
||||
.config-form .el-form-item__label:empty {
|
||||
width: 18px !important;
|
||||
padding-right: 5px !important;
|
||||
}
|
||||
|
||||
.config-form .el-form-item--medium .el-form-item__content {
|
||||
line-height: 28px;
|
||||
line-height: 32px;
|
||||
flex-shrink: 0;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.config-form .el-checkbox {
|
||||
margin-left: 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 确保输入框与标签对齐 */
|
||||
.config-form .el-input {
|
||||
height: 32px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.config-form .el-input__wrapper {
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
|
||||
@@ -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环境中');
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
Reference in New Issue
Block a user