inspect-front/src/views/summary/examination/index.vue
2025-03-03 16:42:39 +08:00

1094 lines
23 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="medical-report">
<!-- 左侧人员列表 -->
<div class="patient-list">
<div class="list-header">
<div class="filter-options">
<div class="header-title">人员列表</div>
<el-radio-group v-model="inspectionStatus">
<el-radio size="large" :label="1">未总检</el-radio>
<el-radio size="large" :label="0">已总检</el-radio>
</el-radio-group>
</div>
<div class="search-box">
<input
type="text"
v-model="searchQuery"
placeholder="请输入姓名"
@input="handleSearch"
/>
<i class="el-icon-search search-icon"></i>
</div>
</div>
<div class="list-content">
<div
v-for="patient in patients"
:key="patient.id"
class="patient-item"
@click="handlePatientSelect(patient)"
:class="{ active: selectedPatient?.id === patient.id }"
>
<div class="patient-info">
<span class="name">{{ patient.pname }}</span>
<span class="medical-sn">{{ patient.medicalSn }}</span>
</div>
</div>
<!-- 将分页组件移到list-content内部底部 -->
<div class="pagination-container">
<el-pagination
v-model:current-page="pageNo"
:page-size="20"
small
:total="total"
layout="total, prev, pager, next, jumper"
@current-change="handleCurrentChange"
>
<template #total>
<span>共 {{ total }} 条</span>
</template>
</el-pagination>
</div>
</div>
</div>
<div class="report-content" >
<ContentWrap :istable="true">
<el-form class="-mb-15px" :inline="true">
<!-- <el-form-item label="条码" prop="medicalSn">
<el-input v-model="medicalSn" placeholder="请输入条码" clearable class="!w-240px" @blur="handleBlur"/>
</el-form-item>-->
<el-form-item>
<el-button @click="save" type="primary" :disabled="!(formData2.auditStatus!=0)">汇总保存</el-button>
<el-button @click="submit" type="primary" :disabled="!(formData2.auditStatus!=0)">提交</el-button>
<!-- <el-button @click="go" type="primary">打印</el-button>
<el-button @click="goto" type="primary">打印导检单</el-button>-->
</el-form-item>
</el-form>
</ContentWrap>
<ContentWrap :istable="true">
<el-form class="-mb-15px" :inline="true">
<el-form-item label="体检编号" prop="medicalSn">
<el-input v-model="formData2.medicalSn" class="!w-215px" disabled/>
</el-form-item>
<el-form-item label="姓名" prop="pname">
<el-input v-model="formData2.pname" class="!w-200px" disabled/>
</el-form-item>
<el-form-item label="性别" prop="gender">
<el-select v-model="formData2.gender" placeholder="请选择" class="!w-120px" disabled>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="出生日期" prop="birthday" >
<el-date-picker
v-model="formData2.birthday"
type="date"
value-format="x"
class="!w-1/1"
disabled
/>
</el-form-item>
<el-form-item label="登记日期" prop="medicalDateTime">
<el-date-picker
v-model="formData2.medicalDateTime"
type="date"
value-format="x"
class="!w-1/1"
disabled
/>
</el-form-item>
</el-form>
</ContentWrap>
<el-row :gutter="20">
<!-- 左侧部门树 -->
<el-col :span="8" :xs="24">
<ContentWrap class="h-1/1">
<el-table :data="list" @row-click="rowChange" :show-overflow-tooltip="true" :scroll-x="true">
<el-table-column label="用户编号" align="center" key="id" prop="id" v-if="false"/>
<el-table-column label="模块名称" align="center" prop="groupname" min-width="150"/>
<el-table-column label="科室小结" align="center" prop="analyse" min-width="320" />
</el-table>
</ContentWrap>
</el-col>
<el-col :span="2" :xs="24">
<ContentWrap class="h-1/1">
<ul style="list-style-type: none;margin-left: -6px;">
<li style="margin-top: 10px">
<el-button type="primary" @click="checkAll">全部选中</el-button>
</li>
<li style="margin-top: 10px">
<el-button type="primary" @click="autoEncoding">自动编码</el-button>
</li>
<li style="margin-top: 10px">
<el-button type="primary" @click="clearEncoding">清除编码</el-button>
</li>
</ul>
</ContentWrap>
</el-col>
<el-col :span="14" :xs="24">
<ContentWrap class="h-1/1">
<ol :style="{ listStyleType: showNumbers ? 'decimal' : 'none' }" style="margin-left: 15px">
<li v-for="(item, index) in list3" :key="index" @click="handleClick(item)">
<span style="display: block"> {{ analyseFlag ? '【' : '' }} {{ item.groupname }} {{ analyseFlag ? '】' : '' }}</span>
<span style="display: block" v-if="analyseFlag">
<el-input v-model="item.analyse" placeholder="请输入" type="textarea" :disabled="!editFlag"/>
</span>
</li>
</ol>
</ContentWrap>
</el-col>
</el-row>
</div>
</div>
</template>
<script setup lang="ts">
import * as SummaryApi from '@/api/summary'
import {DICT_TYPE, getIntDictOptions} from "@/utils/dict";
import {onMounted, ref} from "vue";
import {PatientApi} from "@/api/inspect/inspectpatient";
import { useRouter } from 'vue-router'
import {newHiprintPrintTemplate} from "@/views/summary/utils/template-helper";
import printData from "@/views/summary/print/printData";
import {usePaper} from "@/views/summary/hooks/use-paper";
import {useZoom} from "@/views/summary/hooks/use-zoom";
import template from "../print/template";
import {groupNameItemsOfMedicalSn} from "@/api/summary";
const router = useRouter()
const go = () => {
router.push({
name: 'PrintInfo',
params: {
medicalSn: medicalSn.value // 对应路由中的动态片段 :id
}
})
}
const templateRef = ref(template);
let hiprintTemplate;
const TEMPLATE_KEY = getCurrentInstance().type.name; // 存储模板对象的 key
const { paperTypes, curPaperType, paperPopVisible, paperWidth, paperHeight, showPaperPop, setPaper, setPaperOther } = usePaper(TEMPLATE_KEY);
const { scaleValue, changeScale } = useZoom(TEMPLATE_KEY);
const goto = () =>{
hiprintTemplate = newHiprintPrintTemplate(TEMPLATE_KEY, {
template: templateRef.value, // 模板json(object)
settingContainer: "#PrintElementOptionSetting", // 元素参数容器
});
// 参数: 打印时设置 左偏移量,上偏移量
let options = { leftOffset: -1, topOffset: -1 };
// 扩展
let ext = {
callback: () => {
console.log("浏览器打印窗口已打开");
},
styleHandler: () => {
// 重写 文本 打印样式
return "<style>.hiprint-printElement-text{color:red !important;}</style>";
},
};
// 调用浏览器打印
hiprintTemplate.print(printData, options, ext);
}
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const list = ref([]);
const list3 = ref([]) // 列表的数
const showNumbers = ref(false)
const analyseFlag = ref(false)
const editFlag = ref(true)
const checkAll = () => {
showNumbers.value = false; // 切换显示序号的状态
list3.value = list.value
}
const automaticRollups = () => {
ElMessageBox.confirm('自动汇总将会覆盖现有汇总内容是否继续', '提示', {
confirmButtonText: '继 续',
cancelButtonText: '取 消',
type: 'warning'
}).then(async () => {
analyseFlag.value = true;
list3.value = list.value
})
}
const autoEncoding = () => {
showNumbers.value = true; // 切换显示序号的状态
}
const clearEncoding = () => {
showNumbers.value = false; // 切换显示序号的状态
}
const rowChange = (row)=>{
var flagChange = true;
for (let i = 0; i < list3.value.length; i++) {
if (list3.value[i].id == row.id){
flagChange = false;
}
}
if (flagChange){
list3.value.push(row)
}
}
const handleClick = (item) =>{
analyseFlag.value = true
}
const medicalSn = ref()
const formData2 = ref({
id: undefined,
medicalSn: undefined,
pname: undefined,
gender: undefined,
birthday: undefined,
medicalDateTime: undefined,
auditStatus: undefined,
})
const handleBlur = async () =>{
const patientInfo = await SummaryApi.getPatient(medicalSn.value)
const patientItemsInfo = await SummaryApi.groupNameItemsOfMedicalSn(medicalSn.value)
formData2.value = patientInfo
//list.value = patientItemsInfo
const isCheck = await SummaryApi.isExistUncheck(medicalSn.value);
if (isCheck){
await ElMessageBox({
title: '提示',
message: h('p', null, [
h('span', {style: 'color: red'}, '该患者存在检查项目未查或者待查,请全部检查完再进行汇总!'),
]),
})
}else {
list.value = patientItemsInfo
}
}
const save = async () =>{
if(formData2.value.medicalSn == null || formData2.value.medicalSn == ''){
message.error(t('请选择患者或者输入条码!'))
return
}
if (formData2.value.auditStatus == 2){
message.error(t('已提交,不能进行修改汇总!'))
return
}
const isCheck = await SummaryApi.isExistUncheck(medicalSn.value);
if (isCheck){
await ElMessageBox({
title: '提示',
message: h('p', null, [
h('span', {style: 'color: red'}, '该患者存在检查项目未查或者待查,请全部检查完再进行汇总!'),
]),
})
}else {
if(list3.value.length<1){
message.error(t('检查项目没有进行分析请进行分析再进行汇总保存'))
}else {
await SummaryApi.updateItemsAnalyse(list3.value)
message.success(t('保存成功'))
await fetchPatientsByDate()
}
}
}
const submitFlag = ref(false)
const submit = async () =>{
if (submitFlag.value){
message.error(t('已提交,无须再次提交!'))
return
}
if(formData2.value.medicalSn == null || formData2.value.medicalSn == ''){
message.error(t('请选择患者!'))
return
}
if(formData2.value.auditStatus == 0){
message.error(t('已审核通过,无须再次提交!'))
}else if (formData2.value.auditStatus == 2){
message.error(t('已提交,无须再次提交!'))
}else {
await SummaryApi.updateAudit(medicalSn.value,2,'')
message.success(t('提交成功'))
submitFlag.value = true
}
}
// 添加选中患者的状态
const selectedPatient = ref(null)
const patients = ref([])
const originalPatients = ref([]) // 保存原始患者列表
const searchQuery = ref('')
// 添加搜索处理函数
const handleSearch = () => {
fetchPatientsByDate()
}
// 修改患者选择处理函数
const handlePatientSelect = async (patient) => {
// 设置选中患者
medicalSn.value = patient.medicalSn
selectedPatient.value = patient
const patientInfo = await SummaryApi.getPatient(patient.medicalSn)
const patientItemsInfo = await SummaryApi.groupNameItemsOfMedicalSn(patient.medicalSn)
formData2.value = patientInfo
//list.value = patientItemsInfo
if(patientInfo.auditStatus == 0 || patientInfo.auditStatus == 2){
editFlag.value = false
}else {
editFlag.value = true
}
const isCheck = await SummaryApi.isExistUncheck(patient.medicalSn);
if (isCheck){
await ElMessageBox({
title: '提示',
message: h('p', null, [
h('span', {style: 'color: red'}, '该患者存在检查项目未查或者待查,请全部检查完再进行汇总!'),
]),
})
}else {
list.value = patientItemsInfo
}
if(patientInfo.auditStatus == 0){
analyseFlag.value = true;
showNumbers.value = true; // 切换显示序号的状态
list3.value = patientItemsInfo
}
}
const pageNo = ref(1)
const pageSize = ref(20)
const total = ref(0)
const inspectionStatus = ref(1)
// 添加分页处理函数
const handleCurrentChange = (val) => {
pageNo.value = val
fetchPatientsByDate()
}
onMounted(() => {
// 清理页面状态
patients.value = []
selectedPatient.value = null
inspectionStatus.value = 1
// 获取今日数据
fetchPatientsByDate()
})
const fetchPatientsByDate = async () => {
const params = {
pageNo: pageNo.value,
pageSize: pageSize.value,
pName: searchQuery.value,
inspectionStatus: inspectionStatus.value,
}
const res = await PatientApi.getPatientPage(params)
originalPatients.value = res.list
patients.value = res.list
total.value = res.total
}
watch(inspectionStatus, (newValue, oldValue) => {
fetchPatientsByDate()
});
</script>
<style scoped>
.medical-report {
display: flex;
height: 83vh;
min-height: 600px;
overflow: hidden;
}
.patient-list {
width: 280px;
background: #fff;
border-right: 1px solid #e6e6e6;
}
.list-header {
padding: 0;
}
.header-title {
font-size: 14px;
background: #fff;
border-bottom: 1px solid #fff;
color: #333;
}
.filter-options {
padding: 10px 15px;
border-bottom: 1px solid #e6e6e6;
}
.radio-label {
margin-right: 20px;
cursor: pointer;
font-size: 14px;
color: #606266;
}
.radio-label input[type="radio"] {
margin-right: 4px;
vertical-align: middle;
}
.view-options {
padding: 10px 15px;
display: flex;
flex-direction: column;
border-bottom: 1px solid #e6e6e6;
}
.view-buttons {
display: flex;
gap: 8px;
}
.view-btn {
padding: 5px 12px;
border: none;
background: none;
cursor: pointer;
font-size: 13px;
color: #606266;
border-radius: 3px;
}
.view-btn:hover {
color: #409EFF;
background: #ecf5ff;
}
.view-btn.active {
color: #409EFF;
background: #ecf5ff;
}
.search-box {
padding: 10px 15px;
position: relative;
border-bottom: 1px solid #e6e6e6;
}
.search-box input {
width: 100%;
padding: 8px 30px 8px 10px;
border: 1px solid #dcdfe6;
border-radius: 4px;
font-size: 13px;
}
.search-box input:focus {
border-color: #409EFF;
outline: none;
}
.search-icon {
position: absolute;
right: 25px;
top: 50%;
transform: translateY(-50%);
color: #c0c4cc;
}
.patient-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 15px;
border-bottom: 1px solid #e6e6e6;
}
.report-content {
flex: 1;
display: flex;
flex-direction: column;
position: relative;
background: #fff;
margin-left: 10px;
}
.main-content {
flex: 1;
overflow-y: auto;
padding: 20px;
padding-bottom: 60px;
}
.progress-nav {
display: flex;
margin-bottom: 20px;
position: relative;
}
.nav-item {
position: relative;
padding: 8px 40px;
background: #E4E7ED;
color: #606266;
font-size: 14px;
cursor: pointer;
display: flex;
align-items: center;
margin-right: 4px;
}
.nav-item:after {
content: '';
position: absolute;
right: -20px;
top: 0;
border-left: 20px solid #E4E7ED;
border-top: 18px solid transparent;
border-bottom: 18px solid transparent;
z-index: 1;
}
.nav-item.active {
background: #409EFF;
color: white;
}
.nav-item.active:after {
border-left-color: #409EFF;
}
.basic-info {
display: flex;
gap: 20px;
padding: 20px;
background: #F8F9FA;
border-radius: 4px;
}
.photo-box {
width: 120px;
height: 160px;
background: #fff;
border: 1px dashed #dcdfe6;
display: flex;
align-items: center;
justify-content: center;
}
.no-photo {
color: #909399;
font-size: 14px;
}
.photo {
width: 100%;
height: 100%;
object-fit: cover;
}
.info-grid {
flex: 1;
}
.info-row {
display: flex;
margin-bottom: 15px;
}
.info-row:last-child {
margin-bottom: 0;
}
.info-item {
flex: 1;
display: flex;
align-items: center;
min-width: 0;
}
.info-item label {
color: #606266;
margin-right: 8px;
white-space: nowrap;
}
.info-item span {
color: #333;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.full-width {
width: 100%;
}
.full-width .info-item {
flex: none;
width: 100%;
}
.full-width .info-item span {
flex: 1;
}
.exam-tabs {
display: flex;
}
.tab-item {
position: relative;
padding: 8px 20px;
margin-right: -1px;
cursor: pointer;
display: flex;
align-items: center;
gap: 6px;
border-radius: 4px;
background: #fff;
color: #606266;
font-size: 14px;
}
.tab-indicator {
width: 12px;
height: 12px;
border-radius: 2px;
}
.tab-item.active {
background: #f5f7fa;
border-bottom-color: transparent;
border: 1px solid #409EFF;
border-radius: 4px;
font-weight: 500;
font-size: 14px;
}
.result-table {
flex: 1;
background: #fff;
max-height: 543px;
display: flex;
flex-direction: column;
}
/* 表头样式 */
.table-header {
background: #f5f7fa;
border-bottom: 1px solid #ebeef5;
}
.header-row {
display: flex;
width: 100%;
}
.header-cell {
padding: 12px 8px;
font-weight: 500;
color: #606266;
text-align: left;
border-right: 1px solid #ebeef5;
}
/* 表格主体样式 */
.table-body {
flex: 1;
overflow-y: auto;
max-height: calc(543px - 43px);
}
.table-row {
display: flex;
border-bottom: 1px solid #ebeef5;
}
.table-cell {
padding: 12px 8px;
border-right: 1px solid #ebeef5;
display: flex;
align-items: center;
}
/* 输入框和下拉框样式 */
.cell-input,
.cell-select {
width: 100%;
border: none;
background: transparent;
outline: none;
padding: 0;
}
/* 警告和危险行样式 */
.danger-row {
background: #fc00262d;
}
/* 美化滚动条 */
.table-body::-webkit-scrollbar {
width: 6px;
height: 6px;
}
.table-body::-webkit-scrollbar-thumb {
background: #c0c4cc;
border-radius: 3px;
}
.table-body::-webkit-scrollbar-track {
background: #f5f7fa;
}
/* 修改体检小结样式 */
.summary-section {
width: 51%; /* 设置宽度为50% */
margin-left: auto; /* 靠右对齐 */
padding: 10px;
}
.section-title {
font-size: 14px;
padding: 5px;
color: #606266;
font-weight: bold;
}
.summary-textarea {
width: 100%;
height: 200px; /* 调整高度 */
padding: 8px;
border: 1px solid #dcdfe6;
border-radius: 4px;
resize: none;
font-size: 14px;
line-height: 1.5;
}
.summary-textarea:focus {
outline: none;
border-color: #409EFF;
}
.action-footer {
position: absolute;
bottom: 0;
left: 0;
right: 0;
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 20px;
background: #fff;
border-top: 1px solid #ebeef5;
z-index: 10;
}
.left-section {
display: flex;
align-items: center;
gap: 20px;
}
.signature {
height: 30px;
margin: 0 10px;
object-fit: contain;
}
.right-section {
display: flex;
gap: 10px;
}
.action-btn {
padding: 6px 16px;
border: none;
border-radius: 4px;
background: #40B6FF;
color: white;
cursor: pointer;
font-size: 14px;
transition: all 0.3s;
}
.action-btn:hover {
opacity: 0.9;
}
.action-btn.primary {
background: #40B6FF;
}
.action-buttons {
display: flex;
gap: 15px;
}
.dialog-footer {
display: flex;
justify-content: flex-end;
margin-top: 20px;
gap: 10px;
}
.date-picker-container {
margin-top: 10px;
background: #fff;
padding: 10px 0;
width: 100%;
}
.date-picker-wrapper {
display: flex;
gap: 10px;
align-items: center;
margin-bottom: 10px;
}
.search-button {
width: 100%;
margin-top: 8px;
height: 32px;
}
.patient-info {
display: flex;
gap: 10px;
align-items: center;
}
.medical-sn {
color: #909399;
font-size: 12px;
}
.list-content {
height: calc(100% - 180px);
overflow-y: auto;
position: relative;
display: flex;
flex-direction: column;
}
/* 添加空状态样式 */
.empty-content {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
background: #fff;
border-radius: 4px;
}
/* 添加选中状态样式 */
.patient-item.active {
background-color: #ecf5ff;
}
.patient-item:hover {
background-color: #f5f7fa;
cursor: pointer;
}
.result-table td input {
width: 100%;
padding: 4px 8px;
border: none;
background: transparent;
box-sizing: border-box;
}
.result-table td {
padding: 8px;
border: 1px solid #ebeef5;
text-align: left;
min-width: 100px; /* 设置最小宽度 */
}
/* 为明细结果列设置固定宽度 */
.result-table th:nth-child(3),
.result-table td:nth-child(3) {
width: 200px; /* 可以根据需要调整宽度 */
}
/* 修改分页容器样式 */
.pagination-container {
padding: 8px;
background: #fff;
border-top: 1px solid #e6e6e6;
margin-top: auto;
display: flex;
justify-content: center;
}
/* 自定义分页组件样式 */
:deep(.el-pagination) {
font-size: 12px;
justify-content: flex-start;
width: 100%;
}
:deep(.el-pagination .el-pagination__total) {
margin-right: 8px;
}
:deep(.el-pagination .el-pagination__jump) {
margin-left: 8px;
}
:deep(.el-pagination .el-input__inner) {
height: 24px;
line-height: 24px;
}
:deep(.el-pagination .el-pagination__editor.el-input) {
width: 50px;
}
.no-signature {
color: #909399;
font-size: 14px;
margin: 0 10px;
}
/* 添加图片展示区域样式 */
.result-table {
flex: 1;
overflow: auto;
background: #fff;
}
/* 确保图片展示组件能够正确填充空间 */
:deep(.exam-images) {
height: 100%;
display: flex;
flex-direction: column;
}
/* 美化滚动条样式 */
.result-table::-webkit-scrollbar {
width: 6px;
height: 6px;
}
.result-table::-webkit-scrollbar-thumb {
background: #c0c4cc;
border-radius: 3px;
}
.result-table::-webkit-scrollbar-track {
background: #f5f7fa;
}
/* 添加文字按钮样式 */
.text-button {
cursor: pointer;
font-size: 15px;
transition: all 0.3s;
}
.text-button.danger {
color: #F56C6C;
}
.text-button.danger:hover {
color: #f78989;
}
.positive-indicator {
margin-left: 8px;
font-size: 12px;
}
.table-cell {
display: flex;
align-items: center;
gap: 4px;
}
/* 添加下拉菜单相关样式 */
.el-dropdown-link {
cursor: pointer;
color: #409EFF;
display: flex;
align-items: center;
font-size: 14px;
}
.el-dropdown-link:hover {
color: #66b1ff;
}
:deep(.el-dropdown-menu__item.is-active) {
color: #409EFF;
background-color: #ecf5ff;
}
:deep(.el-dropdown-menu__item--divided) {
margin-top: 6px;
border-top: 1px solid #ebeef5;
}
:deep(.el-dropdown-menu__item--divided:before) {
height: 1px;
margin: 0 -20px;
background-color: #ebeef5;
}
.negative-text {
color: #333;
font-size: 14px;
}
/* 修改下拉按钮样式以匹配 baseUI */
:deep(.el-dropdown) {
margin-right: 8px;
}
:deep(.el-button) {
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
}
/* 添加禁用状态的样式 */
.cell-input:disabled {
background-color: #ebeef5;
cursor: not-allowed;
color: #606266;
}
/* 修改弃检行的样式判断 */
.table-row[data-item-status="2"] {
background-color: #ebeef5;
color: #606266;
}
/* 修改弃检状态下的下拉菜单样式判断 */
.table-row[data-item-status="2"] .el-dropdown {
opacity: 0.8;
}
</style>