inspect-front/src/views/Department-entry/Medical-examination-vehicle.vue
2025-03-10 17:41:31 +08:00

2447 lines
60 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">
人员列表
<el-button
class="refresh-btn"
:icon="Refresh"
circle
type="success"
@click="handleRefresh"
size="small"
/>
</div>
</div>
<!-- 添加时间筛选 -->
<div class="view-options">
<div class="view-buttons">
<button
v-for="period in timePeriods"
:key="period.value"
class="view-btn"
:class="{ active: selectedPeriod === period.value }"
@click="handlePeriodChange(period.value)"
>
{{ period.label }}
</button>
</div>
<!-- 添加日期选择器 -->
<div v-if="showDatePicker" class="date-picker-container">
<div class="date-picker-wrapper">
<el-date-picker
v-model="customDateRange"
type="daterange"
unlink-panels
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
:shortcuts="shortcuts"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
/>
</div>
<el-button
type="primary"
@click="handleDateSearch"
class="search-button"
>搜索</el-button>
</div>
</div>
<!-- 简化体检编号搜索框 -->
<div class="search-box medical-sn-search">
<input
v-model="searchQuery"
placeholder="请输入姓名或体检编号"
@input="handleLocalSearch"
/>
</div>
</div>
<div class="list-content">
<div
v-for="patient in filteredPatients"
: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>
<el-tag
:type="getStatusTagType(patient)"
size="small"
class="status-tag"
>
{{ getStatusText(patient) }}
</el-tag>
</div>
</div>
<!-- 将分页组件移到list-content外部底部 -->
<div class="pagination-container">
<el-pagination
v-model:current-page="pageNo"
:page-size="20"
small
:total="total"
:pager-count="3"
layout="total, prev, pager, next"
@current-change="handleCurrentChange"
>
<template #total>
<span>共 {{ total }} 条</span>
</template>
</el-pagination>
</div>
</div>
</div>
<!-- 右侧内容区域 -->
<div class="right-content">
<!-- 常规检查结果界面 -->
<div class="report-content" v-if="selectedPatient">
<!-- 基本信息 -->
<div class="basic-info">
<div class="photo-box">
<img v-if="reportData.headPicUrl" :src="reportData.headPicUrl" alt="头像" class="photo"/>
<div v-else class="no-photo">个人照片</div>
</div>
<div class="info-grid">
<div class="info-row">
<div class="info-item">
<label>体检编号:</label>
<span>{{ reportData.medicalSn }}</span>
</div>
<div class="info-item">
<label>身份证号:</label>
<span>{{ reportData.cardId }}</span>
</div>
<div class="info-item">
<label>姓名:</label>
<span>{{ reportData.pname }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<label>性别:</label>
<span>{{ reportData.gender }}</span>
</div>
<div class="info-item">
<label>年龄:</label>
<span>{{ age }}岁</span>
</div>
<div class="info-item">
<label>电话:</label>
<span>{{ reportData.phoneNum }}</span>
</div>
</div>
</div>
</div>
<!-- 检查结果部分 -->
<div class="exam-results">
<!-- 检查项目标签 -->
<div class="exam-tabs">
<div
v-for="tab in examTabs"
:key="tab.id"
:class="['tab-item', { active: currentTab === tab.id }]"
@click="switchTab(tab.id)"
>
<div class="tab-indicator" :style="{ background: tab.color }"></div>
<span>{{ tab.name }}</span>
</div>
</div>
<!-- 检查结果表格 -->
<div class="result-table">
<!-- 特殊检查类型 -->
<All
v-if="isSpecialExam"
:patient="selectedPatient"
:exam-type="currentTab"
/>
<!-- 常规检查项目表格 -->
<template v-else>
<div class="table-header">
<div class="header-row">
<div class="header-cell" style="width: 5%">序号</div>
<div class="header-cell" style="width: 15%">检查项目</div>
<div class="header-cell" style="width: 20%">检查结果</div>
<div class="header-cell" style="width: 10%">单位</div>
<div class="header-cell" style="width: 15%">参考值</div>
<div class="header-cell" style="width: 10%">提示</div>
<div class="header-cell" style="width: 15%">风险</div>
<div class="header-cell" style="width: 10%">阳性/阴性</div>
<div class="header-cell" style="width: 10%">操作</div>
</div>
</div>
<!-- 表格内容 -->
<div class="table-body">
<div v-if="sortedExamItems.length === 0" class="empty-content">
<el-empty description="暂无检查项目" />
</div>
<div v-else>
<div
v-for="(item, index) in sortedExamItems"
:key="item.id"
class="table-row"
:class="{ 'danger-row': item.status === 'danger' }"
:data-item-status="item.itemStatus"
>
<div class="table-cell" style="width: 5%">{{ index + 1 }}</div>
<div class="table-cell" style="width: 15%">{{ item.name }}</div>
<div class="table-cell" style="width: 20%">
<input
type="text"
v-model="item.value"
@change="handleResultChange(item)"
@click="checkEditPermission"
class="cell-input"
:readonly="isReadOnly"
/>
</div>
<div class="table-cell" style="width: 10%">{{ item.unit }}</div>
<div class="table-cell" style="width: 15%">
{{ formatReference(item.reference) }}
</div>
<div class="table-cell" style="width: 10%">{{ item.note }}</div>
<div class="table-cell" style="width: 15%">{{ item.risk }}</div>
<div class="table-cell" style="width: 10%">
<el-tag
v-if="item.positive === '阳性'"
type="danger"
size="small"
effect="light"
class="positive-indicator"
>
阳性
</el-tag>
<span v-else class="negative-text">阴性</span>
</div>
<div class="table-cell" style="width: 10%">
<el-dropdown @command="handleOperation">
<el-button size="small" :class="{ 'view-only': isReadOnly }">
更多操作
<el-icon class="el-icon--right"><arrow-down /></el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item
:command="{ type: 'positive', item: item }"
:class="{ 'is-active': item.positive === '阳性' }"
>
阳性
</el-dropdown-item>
<el-dropdown-item
:command="{ type: 'negative', item: item }"
:class="{ 'is-active': item.positive === '阴性' }"
>
阴性
</el-dropdown-item>
<el-dropdown-item
divided
:command="{ type: 'abandon', item: item }"
:class="{ 'is-danger': item.itemStatus !== '2' }"
style="color: red;"
>
{{ item.itemStatus === '2' ? '恢复正常' : '弃检' }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</div>
</div>
</div>
</template>
</div>
<!-- 修改体检小结部分 -->
<div v-if="['ultrasound', 'ecg'].includes(currentTab)" class="findings-diagnosis-container">
<div class="findings-section">
<div class="section-title">检查所见</div>
<textarea
v-model="conclusionData[currentTab].finding"
placeholder="请输入检查所见"
class="findings-textarea"
:readonly="isReadOnly"
></textarea>
</div>
<div class="diagnosis-section">
<div class="section-title">检查结果</div>
<textarea
v-model="conclusionData[currentTab].diagnosis"
placeholder="请输入检查结果"
class="diagnosis-textarea"
:readonly="isReadOnly"
></textarea>
</div>
</div>
<!-- 其他类型使用单栏小结 -->
<div v-else class="summary-section">
<div class="section-title">体检小结</div>
<textarea
v-model="conclusionData[currentTab].summary"
placeholder="输入多个以分号隔开"
class="summary-textarea"
:readonly="isReadOnly"
></textarea>
</div>
</div>
<!-- 底部操作栏 -->
<div class="action-footer">
<div class="left-section">
<span>检查医生:</span>
<span>{{ user?.nickname || '暂无' }}</span>
<span style="margin-left: 100px;">检查日期:{{ formattedMedicalDateTime }}</span>
</div>
<div class="right-section">
<div class="action-buttons">
<button class="action-btn" @click="checkEditPermission">同步结果</button>
<button class="action-btn">报告预览</button>
<button class="action-btn" @click="checkEditPermission">弃检</button>
<button
v-if="!isReadOnly"
class="action-btn primary"
@click="handleSaveAllResults"
>
保存所有结果
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, computed, onBeforeUnmount } from 'vue'
import { ElDialog, ElLoading, ElMessage, ElMessageBox } from 'element-plus'
import { PatientApi } from '@/api/inspect/inspectpatient'
import { PatientitemsApi } from '@/api/inspect/inspectpatientitems'
import { getUserProfile } from '@/api/system/user/profile'
import ExamImages from './Exam_images.vue'
import CT from './CT.vue' // 导入CT组件
import { ArrowDown, Refresh } from '@element-plus/icons-vue'
import BloodTest from './blood.vue' // 导入血常规组件
import All from './All.vue' // 导入All组件用于超声、心电图等
const dialogTitle = ref('体检报告')
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const status = ref('')
const patients = ref([])
// 患者基本信息数据
const reportData = ref({
medicalSn: '', // 体检编号
cardId: '', // 证件ID
pName: '', // 患者姓名
gender: '', // 性别
birthday: '', // 出生日期
nationality: '', // 国籍
nation: '', // 民族
race: '', // 人种
phoneNum: '', // 电话
status: 0, // 状态
reportType: '', // 报告类型
medicalDateTime: '', // 体检日期
chargeType: '', // 收费方式
totalPrice: 0, // 实际收款金额
headPicUrl: '', // 头像图片路径
summaryResult: '', // 汇总分析结果
auditor: '', // 审核人
auditorTime: '', // 审核时间
})
// 患者体检项目数据
const patientitemData = ref({
medicalSn: '', // 体检编号
itemName: '', // 检查项目名称
itemCode: '', // 项目代号
price: 0, // 项目单价
discountedPrice: 0, // 折扣价
discounted: 0, // 折扣 百分比
sectionID: '', // 科室ID
examDescription: '', // 检查所见
itemResult: '', // 检查结论
unit: '', // 项目单位
highValue: 0, // 取值上限
lowValue: 0, // 取值下限
itemStatus: '', // 0未检 1已检 2放弃 3挂起择日检(待查)
createTime: '', // 创建时间
positive: '', // 是否阳性 1阳性
inspectdoctor: '', // 检查医生
inspecttime: '', // 检查时间
})
const doctorSignature = ref('')
// 检查项目标签数据
const examTabs = ref([
{ id: 'general', name: '一般检查', color: '#006699' },
{ id: 'ultrasound', name: '超声', color: '#0099CC' },
{ id: 'ecg', name: '心电图', color: '#00CCFF' },
{ id: 'blood', name: '血常规', color: '#66CCFF' },
{ id: 'urine', name: '尿常规', color: '#99CCFF' }
])
const currentTab = ref('general')
// 检查结果数据
const examItems = ref({})
// 当前显示的检查结果
const currentExamItems = computed(() => {
return examItems.value[currentTab.value] || [];
})
// 添加排序后的计算属性
const sortedExamItems = computed(() => {
if (!currentExamItems.value) return [];
// 对当前显示的检查项目进行排序
return [...currentExamItems.value].sort((a, b) => {
// 首先按照 itemStatus 排序(未检的排在前面)
if (a.itemStatus !== b.itemStatus) {
// 优先级:未检(0) > 已检(1) > 待查(3) > 弃检(2)
const statusOrder = { '0': 0, '1': 1, '3': 2, '2': 3 };
return statusOrder[a.itemStatus] - statusOrder[b.itemStatus];
}
// 如果状态相同,则按照 id 排序
return a.id - b.id;
});
});
// 修改切换标签页函数,添加小结切换逻辑
const switchTab = (tabId) => {
currentTab.value = tabId
// 不再需要单独设置 activeConclusion
}
// 修改 conclusionData 的数据结构
const conclusionData = ref({
general: { summary: '' },
ultrasound: { finding: '', diagnosis: '' },
ecg: { finding: '', diagnosis: '' },
blood: { summary: '' },
urine: { summary: '' }
})
// 其他数据
const examConclusion = ref('')
const examDate = ref('')
// 添加时间周期选项
const timePeriods = [
{ label: '今日', value: 'today' },
{ label: '本周', value: 'week' },
{ label: '本月', value: 'month' },
{ label: '自定义', value: 'custom' },
{ label: '重置', value: 'reset' }
]
// 添加日期相关的响应式数据
const selectedPeriod = ref('today')
const showDatePicker = ref(false)
const customDateRange = ref([])
// 添加日期快捷选项
const shortcuts = [
{
text: '最近一周',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
return [start, end]
},
},
{
text: '最近一个月',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
return [start, end]
},
},
{
text: '最近三个月',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
return [start, end]
},
},
]
const pageNo = ref(1)
const pageSize = ref(100)
const total = ref(0)
// 添加搜索相关的状态
const searchQuery = ref('')
const originalPatients = ref([]) // 保存原始患者列表
const filteredPatients = ref([]) // 添加过滤后的患者列表
// 添加数据缓存
const patientDataCache = ref(new Map())
// 添加体检编号搜索相关
const medicalSnQuery = ref('')
// 添加本地搜索处理函数
const handleLocalSearch = () => {
if (!searchQuery.value) {
filteredPatients.value = patients.value
return
}
const query = searchQuery.value.toLowerCase()
filteredPatients.value = patients.value.filter(patient =>
(patient.pname && patient.pname.toLowerCase().includes(query)) ||
(patient.medicalSn && patient.medicalSn.toLowerCase().includes(query))
)
}
// 修改获取患者列表数据的函数,确保状态更新
const getPatientList = async () => {
try {
const loading = ElLoading.service({
lock: true,
text: '加载中...',
background: 'rgba(255, 255, 255, 0.7)'
})
const params = {
pageNo: pageNo.value,
pageSize: pageSize.value
}
const res = await PatientApi.getPatientPage(params)
patients.value = res.list
originalPatients.value = res.list // 保存原始列表用于搜索
filteredPatients.value = res.list // 初始化过滤后的列表
total.value = res.total
loading.close()
// 如果当前有选中的患者,更新其状态
if (selectedPatient.value) {
const updatedPatient = res.list.find(p => p.id === selectedPatient.value.id)
if (updatedPatient) {
selectedPatient.value = updatedPatient
}
}
} catch (error) {
console.error('获取患者列表出错:', error)
message.error('获取患者列表出错')
}
}
// 修改获取患者体检项目数据的方法
const getpatientitemData = async (medicalSn) => {
try {
const params = {
medicalSn: medicalSn,
pageNo: 1,
pageSize: 100
}
const itemsRes = await PatientitemsApi.getPatientitemsPage(params)
if (itemsRes.list && itemsRes.list.length > 0) {
patientitemData.value = itemsRes.list[0]
// 获取用户信息
const userProfile = await getUserProfile()
user.value = userProfile
// 检查当前部门的项目状态
const currentDeptItems = itemsRes.list.filter(item =>
item.sectionID === userProfile.deptId || item.sectionID == userProfile.deptId
)
// 如果有项目且都是已检查状态,更新患者状态
if (currentDeptItems.length > 0 && currentDeptItems.every(item => item.itemStatus === '1')) {
// 更新患者列表中的状态
const patientIndex = patients.value.findIndex(p => p.medicalSn === medicalSn)
if (patientIndex !== -1) {
patients.value[patientIndex] = {
...patients.value[patientIndex],
examStatus: '1' // 添加检查状态属性
}
}
}
}
} catch (error) {
console.error('获取患者体检项目数据出错:', error)
message.error('获取患者体检项目数据出错')
}
}
// 修改加载患者数据方法
const loadPatientData = async (patient) => {
try {
// 检查缓存中是否已有数据
const cacheKey = patient.id
if (patientDataCache.value.has(cacheKey)) {
const cachedData = patientDataCache.value.get(cacheKey)
reportData.value = cachedData.reportData
examItems.value = cachedData.examItems
currentTab.value = cachedData.currentTab
return
}
const loading = ElLoading.service({
lock: true,
text: '加载中...',
background: 'rgba(255, 255, 255, 0.7)'
})
try {
// 获取用户信息和部门ID
const [userProfile, patientData, itemsRes] = await Promise.all([
getUserProfile(),
PatientApi.getPatient(patient.id),
PatientitemsApi.getPatientitemsPage({
medicalSn: patient.medicalSn,
pageNo: 1,
pageSize: 100
})
])
user.value = userProfile
// 检查用户是否属于影像科或血常规科室
isImageDepartment.value = checkIsImageDepartment(userProfile.deptId)
reportData.value = patientData
// 如果不是特殊科室,继续加载常规检查数据
if (!isImageDepartment.value && !isBloodTest.value) {
if (itemsRes.list && itemsRes.list.length > 0) {
const itemsByCategory = {
general: [],
ultrasound: [],
ecg: [],
blood: [],
urine: []
}
// 从第一个项目获取体检小结
if (itemsRes.list.length > 0) {
examConclusion.value = itemsRes.list[0].analyse || ''
}
// 根据项目名称分类
itemsRes.list.forEach(item => {
const itemName = (item.itemName || '').toLowerCase()
let category = 'general' // 默认为一般检查
if (itemName.includes('彩超') || itemName.includes('超声') || itemName.includes('b超')) {
category = 'ultrasound'
} else if (itemName.includes('心电图') || itemName.includes('ecg') || itemName.includes('ekg')) {
category = 'ecg'
} else if (itemName.includes('血常规') || itemName.includes('血细胞') || itemName.includes('血红蛋白')) {
category = 'blood'
} else if (itemName.includes('尿常规') || itemName.includes('尿液分析')) {
category = 'urine'
}
const processedItem = {
id: item.id,
name: item.itemName,
value: item.itemResult || '',
unit: item.unit,
reference: `${item.lowValue}-${item.highValue}`,
note: getStatusNote(item),
risk: getRiskLevel(item),
status: getRowStatus(item),
positive: item.positive === '1' ? '阳性' : '阴性',
itemStatus: item.itemStatus,
examDescription: item.examDescription || '',
analyse: item.analyse || '',
sectionID: item.sectionID
}
itemsByCategory[category].push(processedItem)
})
examItems.value = itemsByCategory
// 默认选择"全部检查"标签
currentTab.value = 'all'
}
}
// 根据不同类型的检查项目,加载对应的小结
const conclusions = {
general: { summary: '' },
ultrasound: { finding: '', diagnosis: '' },
ecg: { finding: '', diagnosis: '' },
blood: { summary: '' },
urine: { summary: '' }
}
itemsRes.list.forEach(item => {
const itemName = (item.itemName || '').toLowerCase()
let category = 'general'
if (itemName.includes('彩超') || itemName.includes('超声')) {
category = 'ultrasound'
} else if (itemName.includes('心电图')) {
category = 'ecg'
} else if (itemName.includes('血常规')) {
category = 'blood'
} else if (itemName.includes('尿常规')) {
category = 'urine'
}
if (item.analyse) {
if (['ultrasound', 'ecg'].includes(category)) {
// 只对超声和心电图解析检查所见和结果
const parts = item.analyse.split('\n')
parts.forEach(part => {
if (part.startsWith('检查所见:')) {
conclusions[category].finding = part.replace('检查所见:', '')
} else if (part.startsWith('检查结果:')) {
conclusions[category].diagnosis = part.replace('检查结果:', '')
}
})
} else {
conclusions[category].summary = item.analyse
}
}
})
conclusionData.value = conclusions
patientDataCache.value.set(cacheKey, {
reportData: { ...reportData.value },
examItems: { ...examItems.value },
currentTab: currentTab.value
})
} finally {
loading.close()
}
} catch (error) {
console.error('获取患者详细信息出错:', error)
ElMessage.error('获取患者详细信息失败')
}
}
// 修改检查是否为影像科的函数
const checkIsImageDepartment = (deptId) => {
// 强制返回true用于测试
// return true;
// 如果deptId是对象尝试获取其id属性
const id = typeof deptId === 'object' ? deptId.id || deptId.deptId : deptId
// 影像科的ID列表 - 根据实际情况调整
const imageDeptIds = ['7', '8', '9', '10', '11', '12', '13', 'CT室', 'DR室', '超声科', '放射科', '影像科', 'CT', 'MRI', '超声', '放射']
// 检查ID是否在列表中
const result = imageDeptIds.includes(String(id))
return result
}
// 修改获取状态提示的函数
const getStatusNote = (item) => {
if (!item.reference || item.reference === 'null-null') {
return ''
}
const value = parseFloat(item.itemResult)
const [low, high] = item.reference.split('-').map(val => val === 'null' ? null : Number(val))
if (low === null || high === null) {
return ''
}
if (value < low) return '↓'
if (value > high) return '↑'
return '-'
}
// 修改获取风险等级的函数
const getRiskLevel = (item) => {
if (!item.reference || item.reference === 'null-null') {
return ''
}
const value = parseFloat(item.itemResult)
const [low, high] = item.reference.split('-').map(val => val === 'null' ? null : Number(val))
if (low === null || high === null) {
return ''
}
if (value < low) return '低于正常值'
if (value > high) return '高于正常值'
return '正常'
}
// 修改获取行状态的函数
const getRowStatus = (item) => {
if (!item.reference || item.reference === 'null-null') {
return ''
}
const value = parseFloat(item.itemResult)
const [low, high] = item.reference.split('-').map(val => val === 'null' ? null : Number(val))
if (low === null || high === null) {
return ''
}
if (value > high) {
return 'danger'
}
return ''
}
// 修改科室名称映射函数
const getSectionName = (sectionId) => {
// 获取该科室下的所有检查项目
const items = examItems.value[sectionId] || []
// 检查是否包含特定检查项目
const hasBloodTest = items.some(item => item.name.includes('血常规'))
const hasUrineTest = items.some(item => item.name.includes('尿常规'))
const hasImageTest = items.some(item =>
item.name.includes('CT') ||
item.name.includes('MRI') ||
item.name.includes('超声') ||
item.name.includes('X线') ||
item.name.includes('影像')
)
// 根据检查项目类型返回对应科室名称
if (hasBloodTest) return '血液检查'
if (hasUrineTest) return '尿液检查'
if (hasImageTest) return '影像检查'
return '一般检查'
}
// 标签颜色映射
const tabColors = ['#003366', '#006699', '#0099CC', '#00CCFF']
const getTabColor = (index) => {
return tabColors[index % tabColors.length]
}
// 修改患者选择处理函数
const handlePatientSelect = async (patient) => {
try {
// 清理当前数据
examConclusion.value = ''
examItems.value = {}
currentTab.value = 'general' // 设置默认选中一般检查
// 清理该患者的缓存
if (patientDataCache.value.has(patient.id)) {
patientDataCache.value.delete(patient.id)
}
// 设置选中患者
selectedPatient.value = patient
// 重新加载患者数据
await loadPatientData(patient)
// 如果有体检编号,获取体检项目数据
if (patient.medicalSn) {
await getpatientitemData(patient.medicalSn)
}
// 确保切换完数据后,标签页仍然是一般检查
currentTab.value = 'general'
} catch (error) {
console.error('切换患者失败:', error)
message.error('切换患者失败')
// 出错时重置状态
isImageDepartment.value = false
}
}
// 添加判断是否为特殊检查的计算属性
const isSpecialExam = computed(() => {
if (!selectedPatient.value || !currentTab.value) return false
// 检查当前标签是否为特殊检查类型
return ['ultrasound', 'ecg', 'blood', 'urine'].includes(currentTab.value)
})
onMounted(async () => {
// 清理页面状态
patients.value = []
filteredPatients.value = [] // 初始化过滤后的列表
selectedPatient.value = null
reportData.value = {
medicalSn: '',
cardId: '',
pName: '',
gender: '',
birthday: '',
nationality: '',
nation: '',
race: '',
phoneNum: '',
status: 0,
reportType: '',
medicalDateTime: '',
chargeType: '',
totalPrice: 0,
headPicUrl: '',
summaryResult: '',
auditor: '',
auditorTime: ''
}
patientitemData.value = {
medicalSn: '',
itemName: '',
itemCode: '',
price: 0,
discountedPrice: 0,
discounted: 0,
sectionID: '',
examDescription: '',
itemResult: '',
unit: '',
highValue: 0,
lowValue: 0,
itemStatus: '',
createTime: '',
positive: '',
inspectdoctor: '',
inspecttime: ''
}
customDateRange.value = []
// 初始化科室类型
try {
const userProfile = await getUserProfile()
user.value = userProfile
isImageDepartment.value = checkIsImageDepartment(userProfile.deptId)
// 添加默认查询所有人员
await getPatientList()
} catch (error) {
console.error('获取用户信息失败:', error)
isImageDepartment.value = false
}
// 设置默认为今日
const today = new Date()
selectedPeriod.value = 'today'
const todayStart = new Date(today)
todayStart.setHours(0, 0, 0, 0)
const todayEnd = new Date(today)
todayEnd.setHours(23, 59, 59, 999)
customDateRange.value = [todayStart, todayEnd]
// 获取今日数据
await fetchPatientsByDate()
})
// 修改处理时间周期切换的函数
const handlePeriodChange = (period) => {
selectedPeriod.value = period
// 清除选中状态
selectedPatient.value = null
const today = new Date()
let startDate, endDate
switch (period) {
case 'today':
startDate = new Date(today.setHours(0, 0, 0, 0))
endDate = new Date(today.setHours(23, 59, 59, 999))
customDateRange.value = [startDate, endDate]
showDatePicker.value = false
fetchPatientsByDate()
break
case 'week':
startDate = new Date(today)
startDate.setDate(today.getDate() - today.getDay())
endDate = new Date(today)
endDate.setDate(startDate.getDate() + 6)
customDateRange.value = [startDate, endDate]
showDatePicker.value = false
fetchPatientsByDate()
break
case 'month':
startDate = new Date(today.getFullYear(), today.getMonth(), 1)
endDate = new Date(today.getFullYear(), today.getMonth() + 1, 0)
customDateRange.value = [startDate, endDate]
showDatePicker.value = false
fetchPatientsByDate()
break
case 'custom':
showDatePicker.value = !showDatePicker.value
break
case 'reset':
selectedPeriod.value = 'today'
const todayStart = new Date(today.setHours(0, 0, 0, 0))
const todayEnd = new Date(today.setHours(23, 59, 59, 999))
customDateRange.value = [todayStart, todayEnd]
showDatePicker.value = false
fetchPatientsByDate()
break
}
}
// 修改按日期获取患者列表方法
const fetchPatientsByDate = async () => {
try {
if (!customDateRange.value || customDateRange.value.length !== 2) return
const [startDate, endDate] = customDateRange.value
const params = {
pageNo: pageNo.value,
pageSize: pageSize.value,
medicalDateTime: [
`${formatDate(startDate)} 00:00:00`,
`${formatDate(endDate)} 23:59:59`
]
}
const res = await PatientApi.getPatientPage(params)
patients.value = res.list
originalPatients.value = res.list
filteredPatients.value = res.list
total.value = res.total
// 如果没有查询到患者,清除右侧详情
if (!res.list || res.list.length === 0) {
selectedPatient.value = null
}
} catch (error) {
console.error('按日期获取患者列表失败:', error)
message.error('获取患者列表失败')
}
}
// 修改日期搜索处理方法
const handleDateSearch = () => {
if (customDateRange.value && customDateRange.value.length === 2) {
fetchPatientsByDate()
} else {
message.warning('请选择日期范围')
}
}
// 添加格式化后的检查日期计算属性
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 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 selectedPatient = ref(null)
// 添加用户信息的响应式引用
const user = ref(null)
// 加载数据
const loadData = async () => {
reportData.value = await PatientApi.getPatient(1)
}
// 添加计算属性检查是否所有项目都已完成
const isAllItemsChecked = computed(() => {
if (!sortedExamItems.value || sortedExamItems.value.length === 0) return false
return sortedExamItems.value.every(item => item.itemStatus === '1')
})
// 修改检查编辑权限的方法
const checkEditPermission = () => {
if (isAllItemsChecked.value) {
ElMessage.warning('所有检查项目已完成,不可进行编辑')
return false
}
return true
}
// 修改结果变化处理函数
const handleResultChange = (item) => {
if (!checkEditPermission()) {
// 如果没有编辑权限,恢复原值
item.value = item.originalValue || ''
return
}
// 如果有输入值,设置为已检状态
if (item.value) {
item.itemStatus = '1'
} else {
item.itemStatus = '0'
}
item.originalValue = item.value
if (item.reference && item.reference !== 'null-null') {
const value = parseFloat(item.value)
const [low, high] = item.reference.split('-').map(val => val === 'null' ? null : Number(val))
if (low !== null && high !== null) {
item.note = getStatusNote({ itemResult: value, lowValue: low, highValue: high })
item.risk = getRiskLevel({ itemResult: value, lowValue: low, highValue: high })
item.status = getRowStatus({ itemResult: value, lowValue: low, highValue: high })
}
}
}
// 修改操作处理函数
const handleOperation = ({ type, item }) => {
if (!checkEditPermission()) return
switch (type) {
case 'positive':
item.positive = '阳性'
item.itemStatus = '1'
break
case 'negative':
item.positive = '阴性'
item.itemStatus = '1'
break
case 'abandon':
if (item.itemStatus === '2') {
item.itemStatus = '0'
ElMessage.success('已恢复正常状态')
} else {
ElMessageBox.confirm(
'确定要弃检该项目吗?弃检后将无法编辑该项目。',
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
).then(() => {
item.itemStatus = '2'
ElMessage.success('已设置为弃检')
}).catch(() => {
ElMessage.info('已取消弃检')
})
}
break
}
}
// 添加禁用状态的计算属性,用于控制界面元素
const isDisabled = computed(() => {
return isAllItemsChecked.value
})
// 添加只读状态的计算属性
const isReadOnly = computed(() => {
return isAllItemsChecked.value
})
// 修改分页处理函数
const handleCurrentChange = (val) => {
pageNo.value = val
getPatientList() // 使用通用查询函数替代特定日期查询
}
// 修改签名加载错误处理
const handleSignatureError = (e) => {
e.target.style.display = 'none'
}
// 添加缓存清理函数
const clearPatientCache = () => {
patientDataCache.value.clear()
}
// 在组件卸载时清理缓存
onBeforeUnmount(() => {
clearPatientCache()
})
// 添加判断是否为影像类检查的计算属性
const isImageExam = computed(() => {
const items = currentExamItems.value || []
return items.some(item => {
const itemName = (item.name || '').toLowerCase()
return (
itemName.includes('ct') ||
itemName.includes('mri') ||
itemName.includes('超声') ||
itemName.includes('x线') ||
itemName.includes('心电图') ||
itemName.includes('影像') ||
itemName.includes('胸片') ||
itemName.includes('内镜') ||
itemName.includes('放射') ||
itemName.includes('b超') ||
itemName.includes('彩超') ||
itemName.includes('心超')
)
})
})
// 添加检查项目状态的计算属性
const patientExamStatus = computed(() => {
if (!selectedPatient.value?.medicalSn) return '0'
const currentItems = Object.values(examItems.value)
.flat()
.filter(item => item.sectionID === user.value?.deptId)
if (!currentItems.length) return '0'
const allChecked = currentItems.every(item => item.itemStatus === '1')
return allChecked ? '1' : '0'
})
// 修改获取状态文本的方法
const getStatusText = (patient) => {
if (patient.examStatus === '1') {
return '已检查'
}
if (selectedPatient.value?.id === patient.id) {
const currentDeptItems = Object.values(examItems.value)
.flat()
.filter(item => item.sectionID === user.value?.deptId)
if (currentDeptItems.length > 0 && currentDeptItems.every(item => item.itemStatus === '1')) {
return '已检查'
}
}
return '待检查'
}
// 修改状态标签类型
const getStatusTagType = (patient) => {
return getStatusText(patient) === '已检查' ? 'success' : 'info'
}
// 添加参考值格式化函数
const formatReference = (reference) => {
if (!reference || reference === 'null-null') {
return '-'
}
const [low, high] = reference.split('-')
if (!low || !high || low === 'null' || high === 'null') {
return '-'
}
return `${low}-${high}`
}
// 添加isImageDepartment的响应式引用
const isImageDepartment = ref(false)
// 添加判断是否为血常规检查的计算属性
const isBloodTest = computed(() => {
if (!selectedPatient.value) return false
const currentItems = Object.values(examItems.value)
.flat()
.filter(item => {
const itemName = (item.name || '').toLowerCase()
return itemName.includes('血常规') ||
itemName.includes('血细胞') ||
itemName.includes('血红蛋白') ||
itemName.includes('白细胞') ||
itemName.includes('红细胞') ||
itemName.includes('血小板')
})
return currentItems.length > 0
})
// 添加日期格式化函数
const formatDate = (date) => {
if (!date) return ''
const d = new Date(date)
const year = d.getFullYear()
const month = String(d.getMonth() + 1).padStart(2, '0')
const day = String(d.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
}
// 修改刷新处理函数
const handleRefresh = async () => {
try {
// 重置日期相关状态
selectedPeriod.value = 'reset'
showDatePicker.value = false
customDateRange.value = []
// 重置搜索条件
searchQuery.value = ''
// 重置选中状态
selectedPatient.value = null
// 重置页码
pageNo.value = 1
// 重新获取患者列表
await getPatientList()
ElMessage.success('刷新成功')
} catch (error) {
console.error('刷新失败:', error)
ElMessage.error('刷新失败')
}
}
// 修改验证方法,只验证四个标签页的内容
const validateAllResults = () => {
const errors = []
// 检查超声
if (conclusionData.value.ultrasound) {
if (!conclusionData.value.ultrasound.finding?.trim()) {
errors.push('超声检查所见不能为空')
}
if (!conclusionData.value.ultrasound.diagnosis?.trim()) {
errors.push('超声检查结果不能为空')
}
}
// 检查心电图
if (conclusionData.value.ecg) {
if (!conclusionData.value.ecg.finding?.trim()) {
errors.push('心电图检查所见不能为空')
}
if (!conclusionData.value.ecg.diagnosis?.trim()) {
errors.push('心电图检查结果不能为空')
}
}
// 检查血常规
if (conclusionData.value.blood) {
if (!conclusionData.value.blood.summary?.trim()) {
errors.push('血常规体检小结不能为空')
}
}
// 检查尿常规
if (conclusionData.value.urine) {
if (!conclusionData.value.urine.summary?.trim()) {
errors.push('尿常规体检小结不能为空')
}
}
if (errors.length > 0) {
ElMessage({
message: errors.join('\n'),
type: 'warning',
duration: 5000,
showClose: true,
grouping: true
})
return false
}
return true
}
// 修改统一保存方法
const handleSaveAllResults = async () => {
if (!checkEditPermission()) return
// 验证所有标签页的内容
if (!validateAllResults()) return
try {
const userProfile = await getUserProfile()
user.value = userProfile
const currentTimestamp = Date.now()
// 收集所有标签页的所有检查项目
let allUpdatedItems = []
// 添加控制台输出,检查当前数据
console.log('当前标签页:', currentTab.value)
console.log('结论数据:', conclusionData.value)
console.log('当前检查项目:', currentExamItems.value)
// 遍历所有检查项目
Object.keys(examItems.value).forEach(tabKey => {
const items = examItems.value[tabKey] || []
items.forEach(item => {
const itemName = (item.name || '').toLowerCase()
console.log('处理项目:', item.name, '项目ID:', item.id, '标签页:', tabKey)
// 基础字段
const baseFields = {
id: item.id,
medicalSn: selectedPatient.value?.medicalSn,
itemStatus: item.itemStatus || '1',
inspectdoctor: user.value?.nickname || '',
inspecttime: currentTimestamp,
sectionID: user.value?.deptId
}
// 根据项目类型处理不同的字段
if (itemName.includes('超声') || itemName.includes('彩超')) {
console.log('超声项目:', item.name, '所见:', conclusionData.value.ultrasound?.finding, '结果:', conclusionData.value.ultrasound?.diagnosis)
allUpdatedItems.push({
...baseFields,
examDescription: conclusionData.value.ultrasound?.finding?.trim() || '',
itemResult: conclusionData.value.ultrasound?.diagnosis?.trim() || ''
})
} else if (itemName.includes('心电图')) {
console.log('心电图项目:', item.name, '所见:', conclusionData.value.ecg?.finding, '结果:', conclusionData.value.ecg?.diagnosis)
allUpdatedItems.push({
...baseFields,
examDescription: conclusionData.value.ecg?.finding?.trim() || '',
itemResult: conclusionData.value.ecg?.diagnosis?.trim() || ''
})
} else if (itemName.includes('血常规')) {
console.log('血常规项目:', item.name, '小结:', conclusionData.value.blood?.summary)
allUpdatedItems.push({
...baseFields,
itemResult: conclusionData.value.blood?.summary?.trim() || ''
})
} else if (itemName.includes('尿常规')) {
console.log('尿常规项目:', item.name, '小结:', conclusionData.value.urine?.summary)
allUpdatedItems.push({
...baseFields,
itemResult: conclusionData.value.urine?.summary?.trim() || ''
})
}
})
})
console.log('最终要更新的项目:', allUpdatedItems)
if (allUpdatedItems.length === 0) {
ElMessage.warning('没有需要保存的检查项目')
return
}
// 批量更新所有检查项目
await PatientitemsApi.updatePatientitemsBatch(allUpdatedItems)
ElMessage.success('所有检查结果保存成功')
// 重新加载数据以更新界面
await refreshExamData()
} catch (error) {
console.error('保存失败:', error)
ElMessage.error(`保存失败: ${error.message || '请检查数据是否完整'}`)
}
}
// 添加刷新数据的方法
const refreshExamData = async () => {
try {
const params = {
medicalSn: selectedPatient.value?.medicalSn,
pageNo: 1,
pageSize: 100
}
const itemsRes = await PatientitemsApi.getPatientitemsPage(params)
if (itemsRes.list && itemsRes.list.length > 0) {
// 更新检查项目数据
const currentDeptItems = itemsRes.list.filter(item =>
item.sectionID === user.value?.deptId
)
// 更新结论数据
currentDeptItems.forEach(item => {
if (['ultrasound', 'ecg'].includes(currentTab.value)) {
conclusionData.value[currentTab.value] = {
finding: item.examDescription || '',
diagnosis: item.itemResult || ''
}
} else {
conclusionData.value[currentTab.value] = {
summary: item.itemResult || ''
}
}
})
// 更新检查状态
if (selectedPatient.value) {
const allChecked = currentDeptItems.every(item => item.itemStatus === '1')
selectedPatient.value.examStatus = allChecked ? '1' : '0'
}
}
} catch (error) {
console.error('刷新数据失败:', error)
}
}
</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;
display: flex;
align-items: center;
justify-content: space-between;
}
.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;
}
.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;
gap: 10px; /* 添加间隔 */
margin-bottom: 15px;
padding: 10px 0;
}
.tab-item {
position: relative;
padding: 8px 16px;
cursor: pointer;
display: flex;
align-items: center;
gap: 6px;
border-radius: 4px;
background: #f5f7fa; /* 添加底色 */
color: #606266;
font-size: 14px;
border: 1px solid #dcdfe6; /* 添加边框 */
transition: all 0.3s;
}
.tab-indicator {
width: 10px;
height: 10px;
border-radius: 2px;
}
.tab-item:hover {
background: #ecf5ff;
border-color: #c6e2ff;
}
.tab-item.active {
background: #ecf5ff;
border-color: #409EFF;
color: #409EFF;
font-weight: 500;
}
.result-table {
margin: 20px 0;
border: 1px solid #ebeef5;
border-radius: 4px;
height: 520px; /* 固定高度与Charge.vue保持一致 */
display: flex;
flex-direction: column;
background: #fff;
}
/* 表头样式 */
.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;
overflow-x: hidden;
}
.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 {
margin-top: 20px;
padding: 20px;
background: #f8f9fa;
border-radius: 4px;
}
.section-title {
font-size: 16px;
font-weight: 500;
color: #303133;
margin-bottom: 15px;
padding-left: 10px;
border-left: 4px solid #409eff;
}
.summary-textarea {
width: 100%;
height: 120px;
padding: 12px;
border: 1px solid #dcdfe6;
border-radius: 4px;
resize: none;
font-size: 14px;
line-height: 1.5;
background: #fff;
}
.summary-textarea:focus {
outline: none;
border-color: #409EFF;
}
.summary-textarea[readonly] {
background-color: #f5f7fa;
cursor: not-allowed;
}
.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;
align-items: center;
gap: 8px;
flex-wrap: wrap;
}
.name {
min-width: 64px; /* 预留四个汉字的宽度 */
max-width: 64px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: inline-block;
}
.medical-sn {
color: #909399;
font-size: 12px;
margin-right: 4px;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.status-tag {
margin-left: auto; /* 将状态标签推到右侧 */
font-size: 12px;
flex-shrink: 0; /* 防止标签被压缩 */
}
.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; /* 确保分页始终在底部 */
position: sticky; /* 添加粘性定位 */
bottom: 0; /* 固定在底部 */
z-index: 1; /* 确保在内容之上 */
width: 100%; /* 确保宽度填满容器 */
}
/* 自定义分页组件样式 */
:deep(.el-pagination) {
font-size: 12px;
justify-content: flex-start;
width: 100%;
white-space: nowrap; /* 防止内容换行 */
}
: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;
}
/* 添加图片展示区域样式 */
.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: #f5f7fa;
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;
}
/* 固定列样式 */
.fixed-cell {
position: sticky;
background: #fff;
z-index: 1;
}
.table-row .fixed-cell:nth-child(1) {
left: 0;
}
.table-row .fixed-cell:nth-child(2) {
left: 5%;
}
/* 更新搜索框样式 */
.medical-sn-search {
margin-top: 10px;
}
.medical-sn-search input {
width: 100%;
padding: 6px 12px;
border: 1px solid #dcdfe6;
border-radius: 4px;
font-size: 13px;
}
.medical-sn-search input:focus {
border-color: #409EFF;
outline: none;
}
.status-tag {
margin-left: 8px;
font-size: 12px;
}
.patient-info {
display: flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
}
.medical-sn {
color: #909399;
font-size: 12px;
margin-right: 4px;
}
.action-btn:disabled {
background-color: #a0cfff;
cursor: not-allowed;
opacity: 0.7;
}
:deep(.el-dropdown.is-disabled) {
opacity: 0.7;
cursor: not-allowed;
}
:deep(.el-button.is-disabled) {
background-color: #a0cfff;
cursor: not-allowed;
opacity: 0.7;
}
/* 修改只读输入框样式 */
.cell-input[readonly] {
background-color: transparent;
cursor: not-allowed;
}
/* 保持按钮样式正常 */
.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;
}
/* 只读状态的输入框样式 */
.cell-input[readonly] {
background-color: transparent;
cursor: not-allowed;
}
/* 只读状态的文本框样式 */
.summary-textarea[readonly] {
background-color: #f5f7fa;
cursor: not-allowed;
}
/* 只读状态下的按钮样式 */
.view-only {
opacity: 0.7;
cursor: not-allowed;
}
.right-content {
flex: 1;
display: flex;
flex-direction: column;
height: 100%;
overflow: hidden;
}
.tabs-container {
flex-shrink: 0;
padding: 10px 15px;
border-bottom: 1px solid #ebeef5;
}
.content-container {
flex: 1;
overflow: auto;
position: relative;
}
.footer-container {
flex-shrink: 0;
padding: 10px 15px;
border-top: 1px solid #ebeef5;
background: #f8f9fa;
}
.no-patient-selected {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
.refresh-btn {
padding: 6px;
margin-left: 8px;
}
.refresh-btn:hover {
opacity: 0.8;
}
/* 添加双栏布局相关样式 */
.findings-diagnosis-container {
display: flex;
gap: 20px;
margin: 15px 0;
}
.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 {
width: 100%;
height: 120px;
padding: 12px;
border: 1px solid #dcdfe6;
border-radius: 4px;
resize: none;
font-size: 14px;
line-height: 1.5;
background: #fff;
}
.findings-textarea:focus,
.diagnosis-textarea:focus {
outline: none;
border-color: #409EFF;
}
.findings-textarea[readonly],
.diagnosis-textarea[readonly] {
background-color: #f5f7fa;
cursor: not-allowed;
}
</style>