Files
his/openhis-ui-vue3/src/views/outpatient/lab-request/index.vue
2026-05-26 23:03:00 +08:00

163 lines
5.4 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="outpatient-lab-container">
<el-card>
<template #header>
<div class="card-header">
<span>门诊检验申请</span>
<el-button type="primary" @click="handleOpenDialog">+新增</el-button>
</div>
</template>
<!-- 申请单列表区域 (省略) -->
<el-table :data="requestList" border style="width: 100%">
<el-table-column prop="requestNo" label="申请单号" width="180" />
<el-table-column prop="patientName" label="患者姓名" width="120" />
<el-table-column prop="executeTime" label="执行时间" width="160" />
<el-table-column prop="status" label="状态" width="100" />
</el-table>
</el-card>
<!-- 新增检验申请单弹窗 -->
<el-dialog
v-model="dialogVisible"
title="新增检验申请单"
width="850px"
class="lab-request-dialog"
destroy-on-close
>
<el-form :model="form" label-width="100px" class="lab-request-form">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="就诊卡号">
<!-- 修复1: 绑定患者上下文中的卡号禁用手动修改 -->
<el-input v-model="form.patientCardNo" name="patientCardNo" disabled placeholder="自动带出" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="执行时间">
<!-- 修复2: 默认值由 JS 初始化格式严格匹配 YYYY-MM-DD HH:mm -->
<el-date-picker
v-model="form.executeTime"
name="executeTime"
type="datetime"
placeholder="选择执行时间"
format="YYYY-MM-DD HH:mm"
value-format="YYYY-MM-DD HH:mm"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div class="item-selection-panel">
<h4>检验项目选择</h4>
<el-tree
:data="categoryTree"
:props="{ children: 'items', label: 'name' }"
node-key="id"
@node-click="handleNodeClick"
>
<template #default="{ node, data }">
<span v-if="data.isCategory" class="category-node">{{ node.label }}</span>
<div v-else class="lab-item-row">
<!-- 修复3: 移除原模板中硬编码的 <el-tag>套餐</el-tag> type 字段渲染 -->
<span class="item-name">{{ data.name }}</span>
<span class="item-price">¥{{ data.price.toFixed(2) }}</span>
</div>
</template>
</el-tree>
</div>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleSubmit">提交申请</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import dayjs from 'dayjs'
import { useCurrentPatient } from '@/composables/useCurrentPatient'
import { getLabCategoriesApi, submitLabRequestApi } from '@/api/outpatient/lab'
const { currentPatient } = useCurrentPatient()
const dialogVisible = ref(false)
const requestList = ref([])
const categoryTree = ref([])
const form = reactive({
patientCardNo: '',
executeTime: '',
selectedItems: []
})
const handleOpenDialog = () => {
// 修复1: 打开弹窗时立即从全局患者状态同步就诊卡号
form.patientCardNo = currentPatient.value?.cardNo || ''
// 修复2: 初始化执行时间为当前系统时间,精确到分钟
form.executeTime = dayjs().format('YYYY-MM-DD HH:mm')
dialogVisible.value = true
}
const handleNodeClick = (data) => {
if (!data.isCategory) {
// 处理项目勾选逻辑
const exists = form.selectedItems.find(i => i.id === data.id)
if (!exists) {
form.selectedItems.push(data)
}
}
}
const handleSubmit = async () => {
if (!form.patientCardNo) {
ElMessage.warning('未获取到患者就诊卡号,请重新选择患者')
return
}
if (form.selectedItems.length === 0) {
ElMessage.warning('请至少选择一项检验项目')
return
}
try {
await submitLabRequestApi({
patientId: currentPatient.value.id,
cardNo: form.patientCardNo,
executeTime: form.executeTime,
items: form.selectedItems.map(i => ({ id: i.id, name: i.name, price: i.price }))
})
ElMessage.success('检验申请单开立成功')
dialogVisible.value = false
form.selectedItems = []
// 刷新列表逻辑...
} catch (error) {
console.error('提交检验申请失败:', error)
ElMessage.error('提交失败,请重试')
}
}
onMounted(async () => {
try {
const res = await getLabCategoriesApi()
categoryTree.value = res.data || []
} catch (e) {
console.error('加载检验分类失败:', e)
}
})
</script>
<style scoped>
.outpatient-lab-container { padding: 16px; }
.card-header { display: flex; justify-content: space-between; align-items: center; }
.lab-request-form { margin-bottom: 20px; }
.item-selection-panel { border: 1px solid #ebeef5; padding: 12px; border-radius: 4px; max-height: 400px; overflow-y: auto; }
.category-node { font-weight: bold; color: #409eff; }
.lab-item-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px dashed #eee; }
.item-name { flex: 1; }
.item-price { color: #f56c6c; font-weight: 500; }
</style>