体检车录入

This commit is contained in:
Euni4U 2025-03-10 17:41:31 +08:00
parent 0f1a02a2d8
commit c5ba087051
3 changed files with 2998 additions and 0 deletions

View File

@ -0,0 +1,550 @@
<template>
<div class="all-container">
<!-- 检查结果部分 -->
<div class="exam-results">
<!-- 影像检查结果 -->
<div class="image-results">
<!-- 影像图片展示区 -->
<div class="image-gallery">
<div class="image-content">
<div
v-if="imageUrls.length > 0"
class="image-grid"
:class="{ 'single-image': imageUrls.length === 1 }"
>
<div v-for="(url, index) in imageUrls" :key="index" class="image-item">
<el-image
:src="url"
:preview-src-list="imageUrls"
:initial-index="index"
fit="contain"
class="medical-image"
@error="handleImageError"
:preview-teleported="true"
>
<template #error>
<div class="image-error">
<el-icon><Picture /></el-icon>
<span>加载失败</span>
</div>
</template>
</el-image>
</div>
</div>
<el-empty v-else description="暂无影像资料" />
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed, watch, onMounted } from 'vue'
import { ElMessage, ElMessageBox, ElLoading } from 'element-plus'
import { PatientApi } from '@/api/inspect/inspectpatient'
import { PatientitemsApi } from '@/api/inspect/inspectpatientitems'
import { getUserProfile } from '@/api/system/user/profile'
import { PacsDataApi } from '@/api/inspect/inspectpacsdata'
import { Picture } from '@element-plus/icons-vue'
// props
const props = defineProps({
patient: {
type: Object,
required: true
},
examType: {
type: String,
default: '' //
}
})
//
const reportData = ref({})
const imageUrls = ref([])
const imageFinding = ref('')
const imageDiagnosis = ref('')
const examConclusion = ref('')
const user = ref(null)
const patientDataCache = ref(new Map())
const pacsData = ref([])
const isImageDepartment = ref(false)
//
const currentItem = ref(null)
// URL
const getImageUrls = async () => {
try {
//
if (!reportData.value.medicalSn) {
console.warn('缺少体检编号(medicalSn)')
return []
}
// PACS
const response = await PacsDataApi.getPacsDataPage({
code: reportData.value.medicalSn,
pageNo: 1,
pageSize: 100
})
if (!response?.list) {
return []
}
pacsData.value = response.list
//
let filteredData = response.list
// type
if (props.examType) {
// APItype -
const typePatterns = {
'ultrasound': ['ultrasound', 'us', '超声', '彩超', 'b超', 'doppler'],
'ecg': ['ecg', 'ekg', '心电图', 'electrocardiogram'],
'blood': ['blood', 'cbc', '血常规', '血液', 'bloodtest'],
'urine': ['urine', 'ua', '尿常规', '尿液', 'urinalysis']
}
//
const patterns = typePatterns[props.examType]
if (patterns && patterns.length > 0) {
// 使
filteredData = response.list.filter(item => {
if (!item.type) return false
const itemType = item.type.toLowerCase()
return patterns.some(pattern => itemType.includes(pattern.toLowerCase()))
})
}
}
// ""
if (filteredData.length === 0) {
return []
}
// 使dataURL
const urls = filteredData.map((item) => item.data).filter((url) => url)
return urls
} catch (error) {
ElMessage.error('获取影像数据失败,请联系管理员')
return []
}
}
//
const handleImageError = (e) => {
e.target.src = 'https://via.placeholder.com/500x400?text=Image+Not+Found'
}
//
const age = computed(() => {
if (!reportData.value.birthday) return ''
// YYYY-MM-DD
const birthDate = new Date(reportData.value.birthday)
if (isNaN(birthDate.getTime())) return '' //
const today = new Date()
let age = today.getFullYear() - birthDate.getFullYear()
const monthDiff = today.getMonth() - birthDate.getMonth()
// 1
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
age--
}
return age
})
//
const formattedMedicalDateTime = computed(() => {
if (!reportData.value.medicalDateTime) return ''
const date = new Date(reportData.value.medicalDateTime)
return date
.toLocaleDateString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit'
})
.replace(/\//g, '-')
})
//
const isReadOnly = computed(() => {
// 0
// 1
return currentItem.value?.itemStatus === '1'
})
//
const checkEditPermission = () => {
if (isReadOnly.value) {
ElMessage.warning('检查结果已保存,不可进行编辑')
return false
}
return true
}
//
const handleSaveResults = async () => {
try {
if (!checkEditPermission()) {
return
}
const userProfile = await getUserProfile()
user.value = userProfile
//
const currentTime = new Date().getTime()
//
if (!currentItem.value || !currentItem.value.id) {
ElMessage.error('未找到当前检查项目信息')
return
}
//
const updatedItems = [
{
id: currentItem.value.id, // 使ID
examDescription: imageFinding.value, //
itemResult: imageDiagnosis.value, //
itemStatus: '1', //
inspectdoctor: user.value?.nickname || '',
inspecttime: currentTime
}
]
const updateResult = await PatientitemsApi.updatePatientitemsBatch(updatedItems)
//
currentItem.value.itemStatus = '1'
currentItem.value.examDescription = imageFinding.value
currentItem.value.itemResult = imageDiagnosis.value
ElMessage.success('保存成功')
} catch (error) {
console.error('保存失败:', error)
console.error('错误详情:', error.response || error)
ElMessage.error(`保存失败: ${error.message || '未知错误'}`)
}
}
//
const loadPatientData = async (patient) => {
if (!patient || !patient.id) {
return
}
try {
const cacheKey = patient.id
if (patientDataCache.value.has(cacheKey)) {
const cachedData = patientDataCache.value.get(cacheKey)
reportData.value = cachedData.reportData
return
}
const loading = ElLoading.service({
lock: true,
text: '加载中...',
background: 'rgba(255, 255, 255, 0.7)'
})
try {
//
const [userProfile, patientData] = await Promise.all([
getUserProfile(),
PatientApi.getPatient(patient.id)
])
user.value = userProfile
reportData.value = patientData
//
if (reportData.value.medicalSn) {
try {
const patientItemsResponse = await PatientitemsApi.getPatientitemsPage({
medicalSn: reportData.value.medicalSn,
pageNo: 1,
pageSize: 100
})
if (patientItemsResponse?.list && patientItemsResponse.list.length > 0) {
//
currentItem.value = patientItemsResponse.list[0]
console.log('找到的当前检查项目:', currentItem.value)
//
if (currentItem.value) {
imageFinding.value = currentItem.value.examDescription || ''
imageDiagnosis.value = currentItem.value.itemResult || ''
}
//
imageUrls.value = await getImageUrls()
}
} catch (error) {
console.error('获取患者检查项目失败:', error)
}
}
//
patientDataCache.value.set(cacheKey, {
reportData: { ...reportData.value }
})
} finally {
loading.close()
}
} catch (error) {
console.error('获取患者详细信息出错:', error)
ElMessage.error('获取患者详细信息失败')
}
}
//
watch(
() => props.patient,
(newPatient) => {
if (newPatient) {
loadPatientData(newPatient)
}
},
{ immediate: true }
)
//
watch(
() => props.examType,
async (newType) => {
if (newType && reportData.value.medicalSn) {
console.log('检查类型变更为:', newType)
imageUrls.value = await getImageUrls()
}
},
{ immediate: true }
)
//
onMounted(async () => {
if (props.patient) {
//
await loadPatientData(props.patient)
}
})
//
const getExamTypeTitle = () => {
const typeMap = {
ultrasound: '超声',
ecg: '心电图',
blood: '血常规',
urine: '尿常规'
}
return typeMap[props.examType] || '检查'
}
</script>
<style scoped>
.all-container {
height: 520px;
padding: 10px;
background: #fff;
border-radius: 4px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
overflow: auto;
}
.exam-results {
flex: 1;
display: flex;
flex-direction: column;
height: 100%;
}
.image-results {
flex: 1;
display: flex;
flex-direction: column;
gap: 20px;
height: 100%;
}
.image-gallery {
height: 100%;
border-radius: 4px;
}
.image-content {
height: 100%;
padding: 8px;
overflow: auto;
}
.image-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
gap: 10px;
height: 100%;
place-items: center;
}
.image-item {
width: 100%;
height: 100%;
max-width: 600px;
max-height: 450px;
aspect-ratio: 4/3;
border-radius: 4px;
overflow: hidden;
transition: transform 0.3s;
}
.image-item:hover {
transform: scale(1.02);
}
.single-image {
display: flex;
justify-content: center;
}
.single-image .image-item {
width: 90%;
height: 90%;
}
.medical-image {
width: 100%;
height: 100%;
}
.no-images {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
color: #909399;
}
.findings-diagnosis-container {
display: flex;
gap: 20px;
margin-bottom: 20px;
}
.findings-section,
.diagnosis-section {
flex: 1;
padding: 15px;
background: #f8f9fa;
border-radius: 4px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
}
.section-title {
font-size: 16px;
font-weight: 500;
color: #303133;
margin-bottom: 15px;
padding-left: 10px;
border-left: 4px solid #409eff;
}
.findings-textarea,
.diagnosis-textarea {
height: 120px;
width: 100%;
padding: 12px;
border: 1px solid #dcdfe6;
border-radius: 4px;
resize: none;
font-size: 14px;
line-height: 1.5;
background: #fff;
transition: border-color 0.3s;
}
.findings-textarea:focus,
.diagnosis-textarea:focus {
outline: none;
border-color: #409eff;
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}
.findings-textarea[readonly],
.diagnosis-textarea[readonly] {
background-color: #f5f7fa;
cursor: not-allowed;
}
.action-footer {
background: #fff;
border-top: 1px solid #ebeef5;
margin-top: auto;
}
.footer-content {
padding: 15px 0;
display: flex;
justify-content: space-between;
align-items: center;
}
.doctor-info {
display: flex;
gap: 20px;
color: #606266;
font-size: 14px;
}
.action-buttons {
display: flex;
gap: 15px;
}
.action-btn {
padding: 8px 20px;
border: none;
border-radius: 4px;
background: #f0f2f5;
color: #606266;
cursor: pointer;
font-size: 14px;
transition: all 0.3s;
font-weight: 500;
}
.action-btn:hover {
background: #e6e8eb;
}
.action-btn.primary {
background: #409eff;
color: white;
}
.action-btn.primary:hover {
background: #66b1ff;
}
.image-error {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 8px;
background: #f8f9fa;
color: #909399;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -1133,6 +1133,7 @@ const handlePersonInfoPrintInspection = async () => {
let ext = {
callback: () => {
console.log("浏览器打印窗口已打开");
console.log(templateRef.value)
},
styleHandler: () => {
//