- 修复诊断组件中el-popover模板语法错误,添加template标签 - 优化患者历史数据处理逻辑,确保数组类型安全并正确构建树形结构 - 完善住院办理流程中的组织机构数据获取和筛选逻辑 - 添加详细的控制台日志用于调试住院办理功能 - 修复办理住院按钮的禁用状态计算逻辑 - 优化患者卡片点击事件处理,确保就诊ID正确传递 - 添加诊断信息完整性检查并提供用户引导 - 修复检验申请组件中的监听器和暴露方法逻辑
1478 lines
45 KiB
Vue
1478 lines
45 KiB
Vue
<template>
|
||
<div style="max-height: 750px; overflow-y: auto">
|
||
|
||
<!-- 顶部:检验信息表格 -->
|
||
<div class="inspection-section" style="margin-bottom: 20px">
|
||
<div class="section-header">
|
||
<div class="title">
|
||
<i class="el-icon-document-checked"></i>
|
||
<span>检验信息</span>
|
||
</div>
|
||
<div class="actions">
|
||
<el-button type="primary" @click="handleNewApplication" plain>
|
||
新增
|
||
</el-button>
|
||
<el-button type="primary" @click="handleSave" plain>
|
||
保存
|
||
</el-button>
|
||
</div>
|
||
</div>
|
||
|
||
<el-table
|
||
ref="inspectionTableRef"
|
||
:data="inspectionList"
|
||
border
|
||
style="width: 100%"
|
||
max-height="300"
|
||
@selection-change="handleSelectionChange"
|
||
@cell-click="handleCellClick"
|
||
>
|
||
<el-table-column type="selection" width="55" align="center" />
|
||
<el-table-column label="申请ID" prop="applicationId" width="90" align="center" />
|
||
<el-table-column label="申请单号" prop="applicationNo" width="140" align="center" />
|
||
<el-table-column label="检验项目" prop="inspectionItem" width="150" align="center" />
|
||
<el-table-column label="申请医生" prop="doctorName" width="120" align="center" />
|
||
<el-table-column label="急" width="60" align="center">
|
||
<template #default="scope">
|
||
<el-checkbox :model-value="scope.row.isUrgent" disabled />
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="收费" width="80" align="center">
|
||
<template #default="scope">
|
||
<el-checkbox :model-value="scope.row.needCharge" disabled />
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="退费" width="80" align="center">
|
||
<template #default="scope">
|
||
<el-checkbox :model-value="scope.row.needRefund" disabled />
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="执行" width="80" align="center">
|
||
<template #default="scope">
|
||
<el-checkbox :model-value="scope.row.needExecute" disabled />
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="金额" prop="amount" width="90" align="right">
|
||
<template #default="scope">
|
||
¥{{ scope.row.amount || '0.00' }}
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="操作" width="120" align="center">
|
||
<template #default="scope">
|
||
<el-button type="text" size="small" @click="handlePrint(scope.row)">打印</el-button>
|
||
<el-button type="text" size="small" style="color: #f56c6c" @click="handleDelete(scope.row)">删除</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
|
||
<!-- 分页 -->
|
||
<div class="pagination-container" style="text-align: center; margin-top: 10px">
|
||
<el-pagination
|
||
v-model:current-page="queryParams.pageNo"
|
||
v-model:page-size="queryParams.pageSize"
|
||
:page-sizes="[10, 20, 50, 100]"
|
||
:total="total"
|
||
layout="total, sizes, prev, pager, next, jumper"
|
||
@size-change="handleSizeChange"
|
||
@current-change="handleCurrentChange"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 下方:申请单和检验项目选择器 -->
|
||
<div style="display: flex; gap: 20px">
|
||
<!-- 左侧:申请单和检验信息 -->
|
||
<div style="width: 55%">
|
||
<el-tabs v-model="leftActiveTab" style="width: 100%">
|
||
<el-tab-pane label="申请单" name="application">
|
||
<div class="application-form" style="padding: 20px; height: 700px; overflow-y: auto; border: 1px solid #e4e7ed; border-radius: 4px; margin: 10px;">
|
||
<div style="margin-bottom: 20px">
|
||
<label style="display: block; margin-bottom: 5px; font-weight: bold">申请单号</label>
|
||
<el-input v-model="formData.applicationNo" disabled size="small" />
|
||
</div>
|
||
|
||
<!-- 患者信息行 -->
|
||
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 15px; margin-bottom: 20px">
|
||
<div>
|
||
<label style="display: block; margin-bottom: 5px; font-weight: bold">姓名</label>
|
||
<el-input v-model="formData.patientName" disabled size="small" />
|
||
</div>
|
||
<div>
|
||
<label style="display: block; margin-bottom: 5px; font-weight: bold">就诊卡号</label>
|
||
<el-input v-model="formData.cardNo" disabled size="small" />
|
||
</div>
|
||
<div>
|
||
<label style="display: block; margin-bottom: 5px; font-weight: bold">费用性质</label>
|
||
<el-select v-model="formData.feeType" placeholder="请选择费用性质" size="small" style="width: 100%">
|
||
<el-option label="自费医疗" value="self" />
|
||
<el-option label="医保" value="medical" />
|
||
<el-option label="公费医疗" value="public" />
|
||
<el-option label="商业保险" value="commercial" />
|
||
<el-option label="其他" value="other" />
|
||
</el-select>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 申请信息行 -->
|
||
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 15px; margin-bottom: 20px">
|
||
<div>
|
||
<label style="display: block; margin-bottom: 5px; font-weight: bold">申请日期</label>
|
||
<el-date-picker
|
||
v-model="formData.applicationDate"
|
||
type="datetime"
|
||
placeholder="选择日期时间"
|
||
size="small"
|
||
format="YYYY-MM-DD HH:mm:ss"
|
||
value-format="YYYY-MM-DD HH:mm:ss"
|
||
style="width: 100%"
|
||
/>
|
||
</div>
|
||
<div>
|
||
<label style="display: block; margin-bottom: 5px; font-weight: bold">申请科室</label>
|
||
<el-select v-model="formData.departmentName" placeholder="请选择申请科室" size="small" style="width: 100%" disabled>
|
||
<el-option label="内科" value="internal" />
|
||
<el-option label="外科" value="surgery" />
|
||
<el-option label="儿科" value="pediatrics" />
|
||
</el-select>
|
||
</div>
|
||
<div>
|
||
<label style="display: block; margin-bottom: 5px; font-weight: bold">申请医生</label>
|
||
<el-select v-model="formData.doctorName" placeholder="请选择申请医生" size="small" style="width: 100%" disabled>
|
||
<el-option label="张医生" value="doctor_zhang" />
|
||
<el-option label="李医生" value="doctor_li" />
|
||
<el-option label="王医生" value="doctor_wang" />
|
||
</el-select>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 执行科室 -->
|
||
<div style="margin-bottom: 20px" :class="{ 'form-item-error': validationErrors.executeDepartment }">
|
||
<label style="display: block; margin-bottom: 5px; font-weight: bold">执行科室 <span style="color: #f56c6c">*</span></label>
|
||
<el-select
|
||
v-model="formData.executeDepartment"
|
||
placeholder="请选择执行科室"
|
||
size="small"
|
||
style="width: 100%"
|
||
:class="{ 'is-error': validationErrors.executeDepartment }"
|
||
>
|
||
<el-option label="医学检验科" value="medical_lab" />
|
||
<el-option label="放射科" value="radiology" />
|
||
<el-option label="超声科" value="ultrasound" />
|
||
<el-option label="病理科" value="pathology" />
|
||
<el-option label="核医学科" value="nuclear_medicine" />
|
||
</el-select>
|
||
<div v-if="validationErrors.executeDepartment" class="error-message">请选择执行科室</div>
|
||
</div>
|
||
|
||
<!-- 诊断相关字段 -->
|
||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 20px">
|
||
<div :class="{ 'form-item-error': validationErrors.diagnosisDesc }">
|
||
<label style="display: block; margin-bottom: 5px; font-weight: bold">诊断描述 <span style="color: #f56c6c">*</span></label>
|
||
<el-input
|
||
v-model="formData.diagnosisDesc"
|
||
type="textarea"
|
||
:rows="2"
|
||
size="small"
|
||
:class="{ 'is-error': validationErrors.diagnosisDesc }"
|
||
/>
|
||
<div v-if="validationErrors.diagnosisDesc" class="error-message">请输入诊断描述</div>
|
||
</div>
|
||
<div :class="{ 'form-item-error': validationErrors.clinicalDiagnosis }">
|
||
<label style="display: block; margin-bottom: 5px; font-weight: bold">临床诊断 <span style="color: #f56c6c">*</span></label>
|
||
<el-input
|
||
v-model="formData.clinicalDiagnosis"
|
||
type="textarea"
|
||
:rows="2"
|
||
size="small"
|
||
:class="{ 'is-error': validationErrors.clinicalDiagnosis }"
|
||
/>
|
||
<div v-if="validationErrors.clinicalDiagnosis" class="error-message">请输入临床诊断</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 禁忌症、病史摘要、检验目的、体格检查 -->
|
||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 20px">
|
||
<div>
|
||
<label style="display: block; margin-bottom: 5px; font-weight: bold">禁忌症</label>
|
||
<el-input v-model="formData.contraindications" type="textarea" :rows="2" size="small" />
|
||
</div>
|
||
<div :class="{ 'form-item-error': validationErrors.medicalHistory }">
|
||
<label style="display: block; margin-bottom: 5px; font-weight: bold">病史摘要 <span style="color: #f56c6c">*</span></label>
|
||
<el-input
|
||
v-model="formData.medicalHistory"
|
||
type="textarea"
|
||
:rows="2"
|
||
size="small"
|
||
:class="{ 'is-error': validationErrors.medicalHistory }"
|
||
/>
|
||
<div v-if="validationErrors.medicalHistory" class="error-message">请输入病史摘要</div>
|
||
</div>
|
||
<div :class="{ 'form-item-error': validationErrors.inspectionPurpose }">
|
||
<label style="display: block; margin-bottom: 5px; font-weight: bold">检验目的 <span style="color: #f56c6c">*</span></label>
|
||
<el-input
|
||
v-model="formData.inspectionPurpose"
|
||
type="textarea"
|
||
:rows="2"
|
||
size="small"
|
||
:class="{ 'is-error': validationErrors.inspectionPurpose }"
|
||
/>
|
||
<div v-if="validationErrors.inspectionPurpose" class="error-message">请输入检验目的</div>
|
||
</div>
|
||
<div>
|
||
<label style="display: block; margin-bottom: 5px; font-weight: bold">体格检查</label>
|
||
<el-input v-model="formData.physicalExam" type="textarea" :rows="2" size="small" />
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 检验项目和备注 -->
|
||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 20px">
|
||
<div>
|
||
<label style="display: block; margin-bottom: 5px; font-weight: bold">检验项目</label>
|
||
<el-input v-model="formData.inspectionItemsText" type="textarea" :rows="2" size="small" readonly />
|
||
</div>
|
||
<div>
|
||
<label style="display: block; margin-bottom: 5px; font-weight: bold">备注</label>
|
||
<el-input v-model="formData.remark" type="textarea" :rows="2" size="small" />
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 状态复选框组 -->
|
||
<div style="margin-bottom: 20px; padding: 15px; background: #f8f9fa; border-radius: 4px; border: 1px solid #e9ecef">
|
||
<label style="display: block; margin-bottom: 10px; font-weight: bold; color: #1a2b6d">状态设置</label>
|
||
<div style="display: flex; gap: 30px; flex-wrap: wrap">
|
||
<el-checkbox v-model="formData.isUrgent">急</el-checkbox>
|
||
<el-checkbox v-model="formData.needCharge" checked>收费</el-checkbox>
|
||
<el-checkbox v-model="formData.needRefund">退费</el-checkbox>
|
||
<el-checkbox v-model="formData.needExecute">执行</el-checkbox>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</el-tab-pane>
|
||
|
||
<el-tab-pane label="检验信息" name="inspectionInfo">
|
||
<div style="padding: 20px; height: 700px; overflow-y: auto; border: 1px solid #e4e7ed; border-radius: 4px; margin: 10px;">
|
||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 20px">
|
||
<div>
|
||
<label style="display: block; margin-bottom: 5px; font-weight: bold">检验医生</label>
|
||
<el-input v-model="formData.inspectionDoctor" size="small" />
|
||
</div>
|
||
<div>
|
||
<label style="display: block; margin-bottom: 5px; font-weight: bold">检验时间</label>
|
||
<el-date-picker
|
||
v-model="formData.inspectionTime"
|
||
type="datetime"
|
||
placeholder="选择时间"
|
||
size="small"
|
||
format="YYYY-MM-DD HH:mm:ss"
|
||
value-format="YYYY-MM-DD HH:mm:ss"
|
||
style="width: 100%"
|
||
/>
|
||
</div>
|
||
<div>
|
||
<label style="display: block; margin-bottom: 5px; font-weight: bold">审核医生</label>
|
||
<el-input v-model="formData.auditDoctor" size="small" />
|
||
</div>
|
||
<div>
|
||
<label style="display: block; margin-bottom: 5px; font-weight: bold">审核时间</label>
|
||
<el-date-picker
|
||
v-model="formData.auditTime"
|
||
type="datetime"
|
||
placeholder="选择时间"
|
||
size="small"
|
||
format="YYYY-MM-DD HH:mm:ss"
|
||
value-format="YYYY-MM-DD HH:mm:ss"
|
||
style="width: 100%"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 检验信息详情表格 -->
|
||
<div style="margin-top: 20px">
|
||
<h4 style="margin-bottom: 10px; font-weight: bold">检验信息详情</h4>
|
||
<el-table :data="selectedInspectionItems" border size="small" style="width: 100%" max-height="300">
|
||
<el-table-column label="检验信息" prop="name" width="200" />
|
||
<el-table-column label="样本类型" prop="sampleType" width="80" align="center" />
|
||
<el-table-column label="单位" prop="unit" width="60" align="center" />
|
||
<el-table-column label="总量" width="60" align="center">
|
||
<template #default="scope">
|
||
<span>{{ scope.row.quantity || 1 }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="单价" width="70" align="right">
|
||
<template #default="scope">
|
||
¥{{ scope.row.price }}
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="金额" width="70" align="right">
|
||
<template #default="scope">
|
||
¥{{ (scope.row.quantity || 1) * scope.row.price }}
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="服务费" width="70" align="right">
|
||
<template #default="scope">
|
||
¥{{ scope.row.serviceFee || 0 }}
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="类型" prop="type" width="60" align="center" />
|
||
<el-table-column label="自费" width="50" align="center">
|
||
<template #default="scope">
|
||
<el-checkbox :model-value="scope.row.isSelfPay" disabled />
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</div>
|
||
</div>
|
||
</el-tab-pane>
|
||
</el-tabs>
|
||
</div>
|
||
|
||
<!-- 右侧:检验项目选择和已选项目 -->
|
||
<div style="width: 42%; display: flex; flex-direction: column; gap: 20px">
|
||
<!-- 上部:检验项目选择区 -->
|
||
<div class="inspection-selector" style="height: 350px; border: 1px solid #ddd; border-radius: 4px; padding: 15px; background: white;">
|
||
<h4 style="margin-bottom: 10px; font-weight: bold">检验项目选择</h4>
|
||
|
||
<!-- 搜索框 -->
|
||
<div style="margin-bottom: 15px">
|
||
<el-input
|
||
v-model="searchKeyword"
|
||
placeholder="搜索检验项目..."
|
||
size="small"
|
||
clearable
|
||
prefix-icon="Search"
|
||
@input="handleSearch"
|
||
/>
|
||
</div>
|
||
|
||
<!-- 分类树 -->
|
||
<div class="category-tree" style="max-height: 250px; overflow-y: auto">
|
||
<div
|
||
v-for="category in inspectionCategories"
|
||
:key="category.key"
|
||
class="category-tree-item"
|
||
>
|
||
<div
|
||
:class="['category-tree-header', { active: activeCategory === category.key }]"
|
||
@click="switchCategory(category.key)"
|
||
>
|
||
<span class="category-tree-icon">{{ category.expanded ? '▼' : '▶' }}</span>
|
||
<span>{{ category.label }}</span>
|
||
<span class="category-count">({{ category.items.length }})</span>
|
||
</div>
|
||
<div v-if="category.expanded" class="category-tree-children">
|
||
<div
|
||
v-for="item in getFilteredItems(category.key)"
|
||
:key="item.id"
|
||
:class="['inspection-tree-item', { selected: isItemSelected(item) }]"
|
||
@click="handleItemClick(item)"
|
||
>
|
||
<el-checkbox
|
||
:model-value="isItemSelected(item)"
|
||
@change="toggleInspectionItem(item)"
|
||
@click.stop
|
||
/>
|
||
<span class="item-name">{{ item.name }}</span>
|
||
<span class="item-price">¥{{ item.price }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 下部:已选项目区 -->
|
||
<div class="selected-items-area" style="height: 350px; border: 1px solid #ddd; border-radius: 4px; padding: 15px; background: white;">
|
||
<!-- 标题栏 -->
|
||
<div class="selected-header" style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; padding-bottom: 10px; border-bottom: 1px solid #eee;">
|
||
<span style="font-weight: bold; color: #1a2b6d">已选择</span>
|
||
<el-button type="text" @click="clearAllSelected" style="color: #f56c6c">清空</el-button>
|
||
</div>
|
||
|
||
<!-- 已选项目列表 -->
|
||
<div class="selected-tree" style="max-height: 270px; overflow-y: auto">
|
||
<div
|
||
v-for="item in selectedInspectionItems"
|
||
:key="item.id"
|
||
class="selected-tree-item"
|
||
>
|
||
<div class="selected-item-content">
|
||
<span class="item-name">{{ item.name }}</span>
|
||
<span class="item-price">¥{{ item.price }}</span>
|
||
<el-button
|
||
type="text"
|
||
size="small"
|
||
style="color: #f56c6c; margin-left: auto"
|
||
@click="removeInspectionItem(item)"
|
||
>
|
||
删除
|
||
</el-button>
|
||
</div>
|
||
</div>
|
||
<div v-if="selectedInspectionItems.length === 0" class="no-selection">
|
||
<span style="color: #999">暂无选择项目</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import {onMounted, reactive, ref, watch} from 'vue'
|
||
import {ElMessage, ElMessageBox} from 'element-plus'
|
||
import {deleteInspectionApplication, getInspectionApplicationList, saveInspectionApplication} from '../api'
|
||
|
||
// Props
|
||
const props = defineProps({
|
||
patientInfo: {
|
||
type: Object,
|
||
required: true
|
||
},
|
||
activeTab: {
|
||
type: String
|
||
}
|
||
})
|
||
|
||
// Emits
|
||
const emit = defineEmits(['save'])
|
||
|
||
// 响应式数据
|
||
const showForm = ref(false)
|
||
const loading = ref(false)
|
||
const total = ref(0)
|
||
const leftActiveTab = ref('application')
|
||
|
||
// 查询参数
|
||
const queryParams = reactive({
|
||
pageNo: 1,
|
||
pageSize: 10,
|
||
encounterId: ''
|
||
})
|
||
|
||
// 检验申请单列表
|
||
const inspectionList = ref([])
|
||
|
||
// 表单数据
|
||
const formData = reactive({
|
||
applicationId: null,
|
||
applicationNo: '202511210001',
|
||
patientName: '',
|
||
cardNo: '',
|
||
feeType: 'self',
|
||
applicationDate: new Date(),
|
||
departmentName: '',
|
||
doctorName: '',
|
||
executeDepartment: 'medical_lab',
|
||
diagnosisDesc: '',
|
||
contraindications: '',
|
||
clinicalDiagnosis: '',
|
||
medicalHistory: '',
|
||
inspectionPurpose: '',
|
||
physicalExam: '',
|
||
inspectionItems: [],
|
||
inspectionItemsText: '',
|
||
remark: '',
|
||
isUrgent: false,
|
||
needCharge: true,
|
||
needRefund: false,
|
||
needExecute: false,
|
||
inspectionDoctor: '',
|
||
inspectionTime: null,
|
||
auditDoctor: '',
|
||
auditTime: null
|
||
})
|
||
|
||
// 表单验证规则
|
||
const formRules = {
|
||
feeType: [{ required: true, message: '请选择费用性质', trigger: 'change' }],
|
||
applicationDate: [{ required: true, message: '请选择申请日期', trigger: 'change' }],
|
||
executeDepartment: [{ required: true, message: '请选择执行科室', trigger: 'change' }],
|
||
diagnosisDesc: [{ required: true, message: '请输入诊断描述', trigger: 'blur' }],
|
||
clinicalDiagnosis: [{ required: true, message: '请输入临床诊断', trigger: 'blur' }],
|
||
medicalHistory: [{ required: true, message: '请输入病史摘要', trigger: 'blur' }],
|
||
inspectionPurpose: [{ required: true, message: '请输入检验目的', trigger: 'blur' }],
|
||
inspectionItems: [{ required: true, message: '请至少选择一个检验项目', trigger: 'change' }]
|
||
}
|
||
|
||
// 表单引用
|
||
const formRef = ref()
|
||
|
||
// 表格引用
|
||
const inspectionTableRef = ref()
|
||
|
||
// 验证错误状态
|
||
const validationErrors = reactive({
|
||
executeDepartment: false,
|
||
diagnosisDesc: false,
|
||
clinicalDiagnosis: false,
|
||
medicalHistory: false,
|
||
inspectionPurpose: false,
|
||
inspectionItems: false
|
||
})
|
||
|
||
// 已选择的表格行
|
||
const selectedRows = ref([])
|
||
|
||
// 已选择的检验项目
|
||
const selectedInspectionItems = ref([])
|
||
|
||
// 搜索关键词
|
||
const searchKeyword = ref('')
|
||
|
||
// 活动分类
|
||
const activeCategory = ref('biochemical')
|
||
|
||
// 检验项目分类(树形结构)
|
||
const inspectionCategories = ref([
|
||
{
|
||
key: 'biochemical',
|
||
label: '生化',
|
||
expanded: true,
|
||
items: [
|
||
{ id: 1, name: '肝功能', price: 31, sampleType: '血清', unit: 'U/L', quantity: 1, serviceFee: 0, type: '生化', isSelfPay: false },
|
||
{ id: 2, name: '肾功能', price: 28, sampleType: '血清', unit: 'U/L', quantity: 1, serviceFee: 0, type: '生化', isSelfPay: false },
|
||
{ id: 3, name: '血糖', price: 15, sampleType: '血清', unit: 'mmol/L', quantity: 1, serviceFee: 0, type: '生化', isSelfPay: false }
|
||
]
|
||
},
|
||
{
|
||
key: 'blood',
|
||
label: '临检',
|
||
expanded: false,
|
||
items: [
|
||
{ id: 4, name: '血常规+crp', price: 50, sampleType: '全血', unit: '×10^9/L', quantity: 1, serviceFee: 0, type: '血液', isSelfPay: false },
|
||
{ id: 5, name: '血常规(五分类)', price: 15, sampleType: '全血', unit: '×10^9/L', quantity: 1, serviceFee: 0, type: '血液', isSelfPay: false }
|
||
]
|
||
},
|
||
{
|
||
key: 'urine',
|
||
label: '尿液',
|
||
expanded: false,
|
||
items: [
|
||
{ id: 6, name: '尿常规', price: 20, sampleType: '尿液', unit: '细胞/μl', quantity: 1, serviceFee: 0, type: '尿液', isSelfPay: false }
|
||
]
|
||
},
|
||
{
|
||
key: 'immunity',
|
||
label: '免疫',
|
||
expanded: false,
|
||
items: [
|
||
{ id: 7, name: '总IgE测定', price: 30, sampleType: '血清', unit: 'IU/ml', quantity: 1, serviceFee: 0, type: '免疫', isSelfPay: false },
|
||
{ id: 8, name: '风湿', price: 119, sampleType: '血清', unit: 'U/ml', quantity: 1, serviceFee: 0, type: '免疫', isSelfPay: false }
|
||
]
|
||
}
|
||
])
|
||
|
||
// 获取过滤后的项目
|
||
const getFilteredItems = (categoryKey) => {
|
||
const category = inspectionCategories.value.find(cat => cat.key === categoryKey)
|
||
if (!category) return []
|
||
|
||
if (!searchKeyword.value) {
|
||
return category.items
|
||
}
|
||
|
||
return category.items.filter(item =>
|
||
item.name.toLowerCase().includes(searchKeyword.value.toLowerCase())
|
||
)
|
||
}
|
||
|
||
// 初始化数据
|
||
function initData() {
|
||
console.log('检验组件初始化,patientInfo:', props.patientInfo)
|
||
if (props.patientInfo) {
|
||
// 确保 encounterId 存在且有效,优先使用 encounterId,其次尝试 id,最后尝试 patientId
|
||
queryParams.encounterId = props.patientInfo.encounterId || props.patientInfo.id || props.patientInfo.patientId
|
||
formData.patientName = props.patientInfo.patientName || ''
|
||
formData.cardNo = props.patientInfo.cardNo || ''
|
||
formData.departmentName = props.patientInfo.departmentName || ''
|
||
formData.doctorName = props.patientInfo.doctorName || ''
|
||
}
|
||
|
||
// 只有在存在有效的 encounterId 时才调用接口
|
||
if (queryParams.encounterId && queryParams.encounterId !== 'undefined' && queryParams.encounterId !== 'null' && queryParams.encounterId !== '') {
|
||
getInspectionList()
|
||
} else {
|
||
console.warn('缺少有效的就诊ID,无法获取检验申请单列表')
|
||
inspectionList.value = []
|
||
total.value = 0
|
||
}
|
||
}
|
||
|
||
// 获取检验申请单列表
|
||
function getInspectionList() {
|
||
// 先检查是否有有效的encounterId
|
||
if (!queryParams.encounterId || queryParams.encounterId === 'undefined' || queryParams.encounterId === 'null') {
|
||
console.warn('缺少有效的就诊ID,无法获取检验申请单列表')
|
||
inspectionList.value = []
|
||
total.value = 0
|
||
loading.value = false
|
||
return
|
||
}
|
||
|
||
loading.value = true
|
||
|
||
// 调用真实的API,只传递 encounterId 参数
|
||
getInspectionApplicationList({ encounterId: queryParams.encounterId }).then((res) => {
|
||
if (res.code === 200) {
|
||
inspectionList.value = res.data || []
|
||
total.value = res.data?.length || 0
|
||
} else {
|
||
inspectionList.value = []
|
||
total.value = 0
|
||
console.error('获取检验申请单列表失败:', res.message || res.msg)
|
||
ElMessage.error(res.message || res.msg || '获取检验申请单列表失败')
|
||
}
|
||
}).catch((error) => {
|
||
console.error('获取检验申请单列表异常:', error)
|
||
inspectionList.value = []
|
||
total.value = 0
|
||
// 提供更友好的错误信息
|
||
let errorMessage = '获取检验申请单列表异常'
|
||
if (error.response) {
|
||
errorMessage += ` (${error.response.status}): ${error.response.data.message || error.response.statusText}`
|
||
} else if (error.request) {
|
||
errorMessage += ': 网络请求失败,请检查网络连接'
|
||
} else {
|
||
errorMessage += `: ${error.message}`
|
||
}
|
||
ElMessage.error(errorMessage)
|
||
}).finally(() => {
|
||
loading.value = false
|
||
})
|
||
}
|
||
|
||
// 新增申请单
|
||
function handleNewApplication() {
|
||
console.log('点击新增按钮')
|
||
resetForm()
|
||
// 生成申请单号
|
||
formData.applicationNo = generateApplicationNo()
|
||
leftActiveTab.value = 'application'
|
||
}
|
||
|
||
// 生成申请单号
|
||
function generateApplicationNo() {
|
||
const now = new Date()
|
||
const year = now.getFullYear()
|
||
const month = String(now.getMonth() + 1).padStart(2, '0')
|
||
const day = String(now.getDate()).padStart(2, '0')
|
||
const timestamp = now.getTime()
|
||
return `${year}${month}${day}${String(timestamp).slice(-3)}`
|
||
}
|
||
|
||
// 重置表单
|
||
function resetForm() {
|
||
Object.assign(formData, {
|
||
applicationId: null,
|
||
applicationNo: '',
|
||
patientName: props.patientInfo.patientName || '',
|
||
cardNo: props.patientInfo.cardNo || '',
|
||
feeType: 'self',
|
||
applicationDate: new Date(),
|
||
departmentName: props.patientInfo.departmentName || '',
|
||
doctorName: props.patientInfo.doctorName || '',
|
||
executeDepartment: 'medical_lab',
|
||
diagnosisDesc: '',
|
||
contraindications: '',
|
||
clinicalDiagnosis: '',
|
||
medicalHistory: '',
|
||
inspectionPurpose: '',
|
||
physicalExam: '',
|
||
inspectionItems: [],
|
||
remark: '',
|
||
isUrgent: false,
|
||
needCharge: true,
|
||
needRefund: false,
|
||
needExecute: false
|
||
})
|
||
selectedInspectionItems.value = []
|
||
|
||
// 重置验证错误状态
|
||
Object.keys(validationErrors).forEach(key => {
|
||
validationErrors[key] = false
|
||
})
|
||
|
||
formRef.value?.clearValidate()
|
||
}
|
||
|
||
// 返回列表
|
||
function handleBack() {
|
||
showForm.value = false
|
||
getInspectionList()
|
||
}
|
||
|
||
// 保存
|
||
function handleSave() {
|
||
// 重置验证错误状态
|
||
Object.keys(validationErrors).forEach(key => {
|
||
validationErrors[key] = false
|
||
})
|
||
|
||
let hasErrors = false
|
||
|
||
// 检查必填字段
|
||
if (!formData.executeDepartment) {
|
||
validationErrors.executeDepartment = true
|
||
hasErrors = true
|
||
}
|
||
if (!formData.diagnosisDesc.trim()) {
|
||
validationErrors.diagnosisDesc = true
|
||
hasErrors = true
|
||
}
|
||
if (!formData.clinicalDiagnosis.trim()) {
|
||
validationErrors.clinicalDiagnosis = true
|
||
hasErrors = true
|
||
}
|
||
if (!formData.medicalHistory.trim()) {
|
||
validationErrors.medicalHistory = true
|
||
hasErrors = true
|
||
}
|
||
if (!formData.inspectionPurpose.trim()) {
|
||
validationErrors.inspectionPurpose = true
|
||
hasErrors = true
|
||
}
|
||
if (selectedInspectionItems.value.length === 0) {
|
||
validationErrors.inspectionItems = true
|
||
hasErrors = true
|
||
ElMessage.error('请至少选择一项检验项目')
|
||
return
|
||
}
|
||
|
||
if (hasErrors) {
|
||
ElMessage.error('请填写所有必填字段')
|
||
return
|
||
}
|
||
|
||
// 准备保存数据
|
||
const saveData = {
|
||
...formData,
|
||
inspectionItems: selectedInspectionItems.value,
|
||
inspectionItemsText: selectedInspectionItems.value.map(item => item.name).join('、'),
|
||
amount: selectedInspectionItems.value.reduce((sum, item) => sum + item.price, 0),
|
||
serviceFee: selectedInspectionItems.value.reduce((sum, item) => sum + (item.serviceFee || 0), 0),
|
||
totalAmount: selectedInspectionItems.value.reduce((sum, item) => sum + item.price + (item.serviceFee || 0), 0)
|
||
}
|
||
|
||
console.log('保存检验申请单数据:', saveData)
|
||
|
||
// 调用真实的API保存
|
||
saveInspectionApplication(saveData).then((res) => {
|
||
if (res.code === 200) {
|
||
ElMessage.success('保存成功')
|
||
resetForm()
|
||
leftActiveTab.value = 'application'
|
||
// 刷新列表
|
||
getInspectionList()
|
||
} else {
|
||
ElMessage.error(res.message || '保存失败')
|
||
}
|
||
}).catch((error) => {
|
||
console.error('保存检验申请单异常:', error)
|
||
ElMessage.error('保存异常')
|
||
})
|
||
}
|
||
|
||
// 表单保存
|
||
function handleFormSave() {
|
||
formRef.value?.validate((valid) => {
|
||
if (valid) {
|
||
formData.inspectionItems = selectedInspectionItems.value.map(item => item.id)
|
||
console.log('保存检验申请单表单数据:', formData)
|
||
ElMessage.success('保存成功')
|
||
showForm.value = false
|
||
getInspectionList()
|
||
}
|
||
})
|
||
}
|
||
|
||
// 查看详情
|
||
function handleView(row) {
|
||
console.log('点击查看按钮,数据:', row)
|
||
// 加载表单数据
|
||
Object.assign(formData, row)
|
||
|
||
// 根据检验项目名称找到对应的项目数据
|
||
selectedInspectionItems.value = []
|
||
const itemNames = row.inspectionItem.split('、')
|
||
inspectionCategories.value.forEach(category => {
|
||
category.items.forEach(item => {
|
||
if (itemNames.includes(item.name)) {
|
||
selectedInspectionItems.value.push(item)
|
||
}
|
||
})
|
||
})
|
||
|
||
leftActiveTab.value = 'application'
|
||
}
|
||
|
||
// 切换分类
|
||
function switchCategory(category) {
|
||
if (activeCategory.value === category) {
|
||
// 如果点击的是当前激活的分类,则收起
|
||
activeCategory.value = ''
|
||
inspectionCategories.value.forEach(cat => {
|
||
if (cat.key === category) {
|
||
cat.expanded = false
|
||
}
|
||
})
|
||
} else {
|
||
// 否则切换到新的分类并展开
|
||
activeCategory.value = category
|
||
inspectionCategories.value.forEach(cat => {
|
||
cat.expanded = cat.key === category
|
||
})
|
||
}
|
||
}
|
||
|
||
// 处理搜索
|
||
function handleSearch() {
|
||
// 搜索逻辑已在getFilteredItems中实现,这里可以添加额外的搜索逻辑
|
||
console.log('搜索关键词:', searchKeyword.value)
|
||
}
|
||
|
||
// 处理项目项点击(排除勾选框点击)
|
||
function handleItemClick(item) {
|
||
toggleInspectionItem(item)
|
||
}
|
||
|
||
// 判断项目是否已选择
|
||
function isItemSelected(item) {
|
||
return selectedInspectionItems.value.some(selected => selected.id === item.id)
|
||
}
|
||
|
||
// 切换检验项目选择
|
||
function toggleInspectionItem(item) {
|
||
const index = selectedInspectionItems.value.findIndex(selected => selected.id === item.id)
|
||
if (index > -1) {
|
||
selectedInspectionItems.value.splice(index, 1)
|
||
} else {
|
||
selectedInspectionItems.value.push({ ...item })
|
||
}
|
||
}
|
||
|
||
// 移除检验项目
|
||
function removeInspectionItem(item) {
|
||
const index = selectedInspectionItems.value.findIndex(selected => selected.id === item.id)
|
||
if (index > -1) {
|
||
selectedInspectionItems.value.splice(index, 1)
|
||
}
|
||
}
|
||
|
||
// 清空所有选择
|
||
function clearAllSelected() {
|
||
selectedInspectionItems.value = []
|
||
}
|
||
|
||
// 分页大小改变
|
||
function handleSizeChange(size) {
|
||
queryParams.pageSize = size
|
||
getInspectionList()
|
||
}
|
||
|
||
// 分页页码改变
|
||
function handleCurrentChange(page) {
|
||
queryParams.pageNo = page
|
||
getInspectionList()
|
||
}
|
||
|
||
// 选择框变化
|
||
function handleSelectionChange(selection) {
|
||
selectedRows.value = selection
|
||
}
|
||
|
||
// 打印申请单
|
||
function handlePrint(row) {
|
||
console.log('打印申请单:', row)
|
||
|
||
// 切换到申请单TAB
|
||
leftActiveTab.value = 'application'
|
||
|
||
// 加载要打印的数据
|
||
handleView(row)
|
||
|
||
// 等待DOM更新后执行打印
|
||
setTimeout(() => {
|
||
// 添加打印样式
|
||
const printStyle = document.createElement('style')
|
||
printStyle.innerHTML = `
|
||
@media print {
|
||
body * {
|
||
visibility: hidden;
|
||
}
|
||
.application-form,
|
||
.application-form * {
|
||
visibility: visible;
|
||
}
|
||
.application-form {
|
||
position: absolute;
|
||
left: 0;
|
||
top: 0;
|
||
width: 100%;
|
||
max-width: none;
|
||
box-shadow: none;
|
||
border: none;
|
||
margin: 0;
|
||
padding: 20px;
|
||
}
|
||
.el-tabs__header {
|
||
display: none;
|
||
}
|
||
.el-tabs__content {
|
||
padding: 0;
|
||
}
|
||
.section-header,
|
||
.pagination-container,
|
||
.inspection-selector,
|
||
.selected-items-area,
|
||
.actions {
|
||
display: none !important;
|
||
}
|
||
.application-form .el-input__inner,
|
||
.application-form .el-select .el-input__inner,
|
||
.application-form .el-textarea__inner {
|
||
border: 1px solid #ddd !important;
|
||
background: white !important;
|
||
}
|
||
.application-form .el-checkbox__input.is-checked .el-checkbox__inner {
|
||
background-color: #409eff;
|
||
border-color: #409eff;
|
||
}
|
||
}
|
||
`
|
||
document.head.appendChild(printStyle)
|
||
|
||
// 执行打印
|
||
window.print()
|
||
|
||
// 移除打印样式
|
||
setTimeout(() => {
|
||
document.head.removeChild(printStyle)
|
||
}, 1000)
|
||
|
||
ElMessage.success('正在准备打印...')
|
||
}, 100)
|
||
}
|
||
|
||
// 删除申请单
|
||
function handleDelete(row) {
|
||
ElMessageBox.confirm(
|
||
`确定要删除申请单 "${row.applicationNo}" 吗?此操作不可撤销。`,
|
||
'删除确认',
|
||
{
|
||
confirmButtonText: '确定删除',
|
||
cancelButtonText: '取消',
|
||
type: 'warning',
|
||
confirmButtonClass: 'el-button--danger'
|
||
}
|
||
).then(() => {
|
||
console.log('删除申请单:', row)
|
||
// 调用真实的API删除
|
||
deleteInspectionApplication(row.applicationId).then((res) => {
|
||
if (res.code === 200) {
|
||
ElMessage.success('删除成功')
|
||
// 刷新列表
|
||
getInspectionList()
|
||
} else {
|
||
ElMessage.error(res.message || '删除失败')
|
||
}
|
||
}).catch((error) => {
|
||
console.error('删除检验申请单异常:', error)
|
||
ElMessage.error('删除异常')
|
||
})
|
||
}).catch(() => {
|
||
// 用户取消删除
|
||
})
|
||
}
|
||
|
||
// 单元格点击
|
||
function handleCellClick(row, column) {
|
||
// 可以添加更多的交互逻辑
|
||
}
|
||
|
||
// 监听activeTab变化
|
||
watch(() => props.activeTab, (newVal) => {
|
||
if (newVal === 'inspection') {
|
||
initData()
|
||
// 默认展开生化分类
|
||
activeCategory.value = 'biochemical'
|
||
inspectionCategories.value.forEach(cat => {
|
||
cat.expanded = cat.key === 'biochemical'
|
||
})
|
||
}
|
||
})
|
||
|
||
// 监听patientInfo变化,确保在患者信息更新时也更新检验申请单列表
|
||
watch(() => props.patientInfo, (newPatientInfo) => {
|
||
if (newPatientInfo && Object.keys(newPatientInfo).length > 0) {
|
||
// 更新encounterId
|
||
queryParams.encounterId = newPatientInfo.encounterId || newPatientInfo.id || newPatientInfo.patientId
|
||
// 如果有有效的encounterId,则获取检验申请单列表
|
||
if (queryParams.encounterId && queryParams.encounterId !== 'undefined' && queryParams.encounterId !== 'null' && queryParams.encounterId !== '') {
|
||
getInspectionList()
|
||
}
|
||
}
|
||
}, { deep: true })
|
||
|
||
// 初始化
|
||
onMounted(() => {
|
||
initData()
|
||
})
|
||
|
||
// 暴露方法
|
||
defineExpose({
|
||
getList() {
|
||
// 在调用getList时,先检查是否有有效的patientInfo,如果有则更新encounterId
|
||
if (props.patientInfo && Object.keys(props.patientInfo).length > 0) {
|
||
queryParams.encounterId = props.patientInfo.encounterId || props.patientInfo.id || props.patientInfo.patientId;
|
||
}
|
||
getInspectionList();
|
||
}
|
||
})
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.inspection-section {
|
||
background: white;
|
||
padding: 0 10px 10px 10px;
|
||
margin-bottom: 20px;
|
||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||
}
|
||
|
||
.section-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
border-bottom: 1px solid #eee;
|
||
padding: 15px 0;
|
||
margin-bottom: 15px;
|
||
}
|
||
|
||
.section-header .title {
|
||
display: flex;
|
||
align-items: center;
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
color: #1a2b6d;
|
||
}
|
||
|
||
.section-header .title i {
|
||
margin-right: 10px;
|
||
font-size: 24px;
|
||
}
|
||
|
||
.actions {
|
||
display: flex;
|
||
gap: 10px;
|
||
}
|
||
|
||
.pagination-container {
|
||
display: flex;
|
||
justify-content: center;
|
||
margin-top: 20px;
|
||
}
|
||
|
||
:deep(.el-pagination) {
|
||
.el-pager li {
|
||
border-radius: 4px;
|
||
margin: 0 2px;
|
||
min-width: 32px;
|
||
height: 32px;
|
||
line-height: 30px;
|
||
border: 1px solid #dcdfe6;
|
||
background-color: #fff;
|
||
color: #606266;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.el-pager li:hover {
|
||
border-color: #409eff;
|
||
color: #409eff;
|
||
}
|
||
|
||
.el-pager li.is-active {
|
||
border-color: #409eff;
|
||
background-color: #409eff;
|
||
color: #fff;
|
||
}
|
||
|
||
.el-pagination__jump {
|
||
margin-left: 10px;
|
||
}
|
||
}
|
||
|
||
.inspection-form {
|
||
background: white;
|
||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||
}
|
||
|
||
.form-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
border-bottom: 1px solid #eee;
|
||
padding: 15px 20px;
|
||
margin-bottom: 15px;
|
||
}
|
||
|
||
.form-header .title {
|
||
display: flex;
|
||
align-items: center;
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
color: #1a2b6d;
|
||
}
|
||
|
||
.form-header .title i {
|
||
margin-right: 10px;
|
||
font-size: 24px;
|
||
}
|
||
|
||
.inspection-items-section {
|
||
border: 1px solid #ebeef5;
|
||
border-radius: 4px;
|
||
padding: 15px;
|
||
}
|
||
|
||
.selected-items {
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.item-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 10px;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.selected-list {
|
||
min-height: 40px;
|
||
border: 1px solid #ebeef5;
|
||
border-radius: 4px;
|
||
padding: 10px;
|
||
}
|
||
|
||
.item-selector {
|
||
margin-top: 20px;
|
||
}
|
||
|
||
.category-tabs {
|
||
display: flex;
|
||
border-bottom: 1px solid #ebeef5;
|
||
margin-bottom: 15px;
|
||
}
|
||
|
||
.category-tab {
|
||
padding: 10px 20px;
|
||
cursor: pointer;
|
||
border-bottom: 2px solid transparent;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.category-tab:hover {
|
||
color: #409eff;
|
||
}
|
||
|
||
.category-tab.active {
|
||
color: #409eff;
|
||
border-bottom-color: #409eff;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.items-list {
|
||
max-height: 300px;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.inspection-item {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 10px 15px;
|
||
margin-bottom: 5px;
|
||
border: 1px solid #ebeef5;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.inspection-item:hover {
|
||
border-color: #409eff;
|
||
background-color: #ecf5ff;
|
||
}
|
||
|
||
.inspection-item.selected {
|
||
border-color: #409eff;
|
||
background-color: #ecf5ff;
|
||
}
|
||
|
||
.item-name {
|
||
font-weight: 500;
|
||
}
|
||
|
||
.item-price {
|
||
color: #e6a23c;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.inspection-details {
|
||
margin-top: 30px;
|
||
padding: 20px;
|
||
border: 1px solid #ebeef5;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
.details-header {
|
||
margin-bottom: 15px;
|
||
}
|
||
|
||
.details-header h3 {
|
||
margin: 0;
|
||
color: #1a2b6d;
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.inspection-selector {
|
||
border: 1px solid #ddd;
|
||
border-radius: 4px;
|
||
padding: 15px;
|
||
background: white;
|
||
}
|
||
|
||
.category-list {
|
||
margin-bottom: 15px;
|
||
}
|
||
|
||
.category-item {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 8px 12px;
|
||
cursor: pointer;
|
||
border-radius: 4px;
|
||
transition: all 0.3s ease;
|
||
margin-bottom: 2px;
|
||
}
|
||
|
||
.category-item:hover {
|
||
background-color: #f5f5f5;
|
||
}
|
||
|
||
.category-item.active {
|
||
background-color: #e6f7ff;
|
||
color: #409eff;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.category-icon {
|
||
margin-right: 8px;
|
||
font-weight: bold;
|
||
width: 12px;
|
||
text-align: center;
|
||
}
|
||
|
||
.selected-summary {
|
||
margin: 10px 0;
|
||
padding: 10px;
|
||
background: #f5f5f5;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
.selected-items {
|
||
margin-top: 5px;
|
||
}
|
||
|
||
.inspection-selector .items-list {
|
||
max-height: 200px;
|
||
overflow-y: auto;
|
||
border: 1px solid #ebeef5;
|
||
border-radius: 4px;
|
||
padding: 10px;
|
||
}
|
||
|
||
.inspection-selector .inspection-item {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 8px 12px;
|
||
margin-bottom: 5px;
|
||
border: 1px solid #f0f0f0;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
background: #fafafa;
|
||
}
|
||
|
||
.inspection-selector .inspection-item:hover {
|
||
border-color: #409eff;
|
||
background-color: #ecf5ff;
|
||
}
|
||
|
||
.inspection-selector .inspection-item.selected {
|
||
border-color: #409eff;
|
||
background-color: #ecf5ff;
|
||
font-weight: bold;
|
||
}
|
||
|
||
/* 新的树形结构样式 */
|
||
.category-tree {
|
||
border: 1px solid #ebeef5;
|
||
border-radius: 4px;
|
||
background: #fafafa;
|
||
}
|
||
|
||
.category-tree-item {
|
||
border-bottom: 1px solid #ebeef5;
|
||
}
|
||
|
||
.category-tree-item:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.category-tree-header {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 12px 15px;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
background: #fff;
|
||
border-radius: 4px;
|
||
margin: 2px;
|
||
}
|
||
|
||
.category-tree-header:hover {
|
||
background-color: #f5f5f5;
|
||
}
|
||
|
||
.category-tree-header.active {
|
||
background-color: #e6f7ff;
|
||
color: #409eff;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.category-tree-icon {
|
||
margin-right: 8px;
|
||
font-size: 12px;
|
||
width: 12px;
|
||
text-align: center;
|
||
color: #409eff;
|
||
}
|
||
|
||
.category-count {
|
||
margin-left: auto;
|
||
color: #999;
|
||
font-size: 12px;
|
||
}
|
||
|
||
.category-tree-children {
|
||
background: #fff;
|
||
border-top: 1px solid #ebeef5;
|
||
}
|
||
|
||
.inspection-tree-item {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 8px 15px 8px 35px;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
border-bottom: 1px solid #f0f0f0;
|
||
}
|
||
|
||
.inspection-tree-item:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.inspection-tree-item:hover {
|
||
background-color: #f5f5f5;
|
||
}
|
||
|
||
.inspection-tree-item.selected {
|
||
background-color: #ecf5ff;
|
||
border-left: 3px solid #409eff;
|
||
}
|
||
|
||
.inspection-tree-item .item-name {
|
||
flex: 1;
|
||
margin-left: 10px;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.inspection-tree-item .item-price {
|
||
color: #e6a23c;
|
||
font-weight: bold;
|
||
margin-left: 10px;
|
||
}
|
||
|
||
/* 已选项目区样式 */
|
||
.selected-items-area {
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.selected-header {
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.selected-tree {
|
||
flex: 1;
|
||
}
|
||
|
||
.selected-tree-item {
|
||
padding: 8px 0;
|
||
border-bottom: 1px solid #f0f0f0;
|
||
}
|
||
|
||
.selected-tree-item:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.selected-item-content {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 8px 12px;
|
||
background: #f8f9fa;
|
||
border-radius: 4px;
|
||
margin: 2px 0;
|
||
}
|
||
|
||
.selected-item-content .item-name {
|
||
flex: 1;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.selected-item-content .item-price {
|
||
color: #e6a23c;
|
||
font-weight: bold;
|
||
margin-right: 10px;
|
||
}
|
||
|
||
.no-selection {
|
||
text-align: center;
|
||
padding: 40px 20px;
|
||
color: #999;
|
||
}
|
||
|
||
/* 表单验证错误样式 */
|
||
.form-item-error .el-input__inner,
|
||
.form-item-error .el-textarea__inner {
|
||
border-color: #f56c6c !important;
|
||
}
|
||
|
||
.form-item-error .el-select .el-input__inner {
|
||
border-color: #f56c6c !important;
|
||
}
|
||
|
||
.is-error.el-input .el-input__inner,
|
||
.is-error.el-textarea .el-textarea__inner {
|
||
border-color: #f56c6c !important;
|
||
}
|
||
|
||
.error-message {
|
||
color: #f56c6c;
|
||
font-size: 12px;
|
||
margin-top: 4px;
|
||
line-height: 1;
|
||
}
|
||
</style>
|