Files
his/openhis-ui-vue3/src/views/triageandqueuemanage/cardiology/index.vue

379 lines
10 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="cardiology-queue">
<div class="app-container">
<el-card>
<template #header>
<div class="card-header">
<span class="title">心内科分诊排队管理</span>
<div class="header-actions">
<el-button type="primary" @click="refreshData" :loading="loading">
<el-icon><Refresh /></el-icon>
刷新
</el-button>
</div>
</div>
</template>
<!-- 当前呼叫区 -->
<div class="current-call-section">
<div class="call-box">
<div class="call-text">
<span class="highlight">{{ currentCall?.number || '-' }}</span>
<span class="highlight">{{ currentCall?.name || '-' }}</span>
<span class="highlight">{{ currentCall?.room || '-' }}</span> 诊室就诊
</div>
</div>
</div>
<!-- 候诊队列 -->
<div class="queue-section">
<h3 class="section-title">候诊队列</h3>
<el-table
:data="queueList"
v-loading="loading"
stripe
border
style="width: 100%"
:default-sort="{ prop: 'displayOrder', order: 'ascending' }"
>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="patientName" label="患者姓名" width="120" align="center">
<template #default="scope">
{{ formatPatientName(scope.row.patientName) }}
</template>
</el-table-column>
<el-table-column prop="practitionerName" label="医生" width="120" align="center" />
<el-table-column prop="room" label="诊室" width="100" align="center" />
<el-table-column prop="displayOrder" label="流水号" width="120" align="center">
<template #default="scope">
{{ formatSerialNo(scope.row) }}
</template>
</el-table-column>
<el-table-column prop="status" label="状态" width="100" align="center">
<template #default="scope">
<el-tag :type="getStatusType(scope.row.status)">
{{ getStatusText(scope.row.status) }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="registerTime" label="挂号时间" width="180" align="center">
<template #default="scope">
{{ formatTime(scope.row.registerTime) }}
</template>
</el-table-column>
<el-table-column label="操作" width="150" align="center" fixed="right">
<template #default="scope">
<el-button
type="primary"
size="small"
@click="handleCall(scope.row)"
:disabled="scope.row.status === 'CALLED'"
>
叫号
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div class="pagination-wrapper">
<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="handlePageChange"
/>
</div>
</div>
</el-card>
</div>
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Refresh } from '@element-plus/icons-vue'
import { parseTime } from '@/utils/his'
import { getOutpatientRegistrationCurrent } from '@/views/charge/outpatientregistration/components/outpatientregistration'
// 响应式数据
const loading = ref(false)
const queueList = ref([])
const total = ref(0)
const currentCall = ref({
number: '-',
name: '-',
room: '-'
})
// 查询参数
const queryParams = reactive({
pageNo: 1,
pageSize: 20,
searchKey: '',
organizationId: null // 心内科科室ID可以从路由参数或配置中获取
})
// 计算流水号直接使用挂号记录表的主键IDencounterId
function formatSerialNo(row) {
if (!row) return '-'
// 直接使用主键ID作为流水号
if (row.encounterId != null && row.encounterId !== undefined) {
return String(row.encounterId)
} else if (row.id != null && row.id !== undefined) {
// 兼容其他可能的ID字段名
return String(row.id)
} else {
return '-'
}
}
// 格式化患者姓名(脱敏)
function formatPatientName(name) {
if (!name || typeof name !== 'string') return '-'
if (name.length <= 2) return name.charAt(0) + '*'
return name.charAt(0) + '*' + name.slice(-1)
}
// 格式化时间
function formatTime(time) {
if (!time) return '-'
return parseTime(time, '{y}-{m}-{d} {h}:{i}:{s}')
}
// 获取状态类型
function getStatusType(status) {
const statusMap = {
'WAITING': 'info',
'CALLED': 'warning',
'IN_PROGRESS': 'success',
'COMPLETED': ''
}
return statusMap[status] || ''
}
// 获取状态文本
function getStatusText(status) {
const statusMap = {
'WAITING': '等待',
'CALLED': '已叫号',
'IN_PROGRESS': '就诊中',
'COMPLETED': '已完成'
}
return statusMap[status] || '未知'
}
// 获取队列数据
async function fetchQueueData() {
try {
loading.value = true
// 调用API获取当日就诊数据
const response = await getOutpatientRegistrationCurrent({
searchKey: queryParams.searchKey,
pageNo: queryParams.pageNo,
pageSize: queryParams.pageSize
})
if (response && response.code === 200) {
// 获取记录数据
const records = response.data?.records || response.data || []
// 过滤心内科的数据如果有organizationId
let filteredData = records
if (queryParams.organizationId) {
filteredData = records.filter(item => item.organizationId === queryParams.organizationId)
}
// 转换为队列数据格式
queueList.value = filteredData.map(item => ({
id: item.encounterId,
patientName: item.patientName,
practitionerName: item.practitionerName || '-',
organizationName: item.organizationName,
room: item.organizationName || '-', // 使用科室名称作为诊室
displayOrder: item.displayOrder,
registerTime: item.registerTime,
status: 'WAITING' // 默认状态,实际应该从后端获取
}))
total.value = response.data?.total || filteredData.length || 0
} else {
queueList.value = []
total.value = 0
if (response && response.msg) {
ElMessage.warning('获取数据失败: ' + response.msg)
}
}
} catch (error) {
console.error('获取队列数据失败:', error)
ElMessage.error('获取队列数据失败: ' + (error.message || '未知错误'))
queueList.value = []
total.value = 0
} finally {
loading.value = false
}
}
// 刷新数据
function refreshData() {
queryParams.pageNo = 1
fetchQueueData()
}
// 叫号
async function handleCall(row) {
try {
await ElMessageBox.confirm(
`确认叫号:${formatPatientName(row.patientName)}${formatSerialNo(row)}`,
'确认叫号',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
}
)
// TODO: 调用叫号API
// await callPatient(row.id)
// 更新当前呼叫信息
currentCall.value = {
number: row.displayOrder || '-',
name: formatPatientName(row.patientName),
room: row.room
}
// 更新状态
row.status = 'CALLED'
ElMessage.success('叫号成功')
// 刷新数据
await fetchQueueData()
} catch (error) {
if (error !== 'cancel') {
console.error('叫号失败:', error)
ElMessage.error('叫号失败: ' + (error.message || '未知错误'))
}
}
}
// 分页大小改变
function handleSizeChange(val) {
queryParams.pageSize = val
queryParams.pageNo = 1
fetchQueueData()
}
// 页码改变
function handlePageChange(val) {
queryParams.pageNo = val
fetchQueueData()
}
// 组件挂载时获取数据
onMounted(() => {
fetchQueueData()
// 定时刷新数据每30秒
const refreshInterval = setInterval(() => {
fetchQueueData()
}, 30000)
// 组件卸载时清理定时器
return () => {
clearInterval(refreshInterval)
}
})
</script>
<style lang="scss" scoped>
.cardiology-queue {
.app-container {
padding: 20px;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
.title {
font-size: 18px;
font-weight: bold;
color: #333;
}
.header-actions {
display: flex;
gap: 10px;
}
}
.current-call-section {
margin: 20px 0;
text-align: center;
.call-box {
display: inline-block;
padding: 20px 40px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 12px;
box-shadow: 0 8px 20px rgba(102, 126, 234, 0.3);
animation: pulse 2s infinite;
.call-text {
font-size: 24px;
font-weight: bold;
color: white;
letter-spacing: 2px;
.highlight {
color: #ffd700;
font-size: 28px;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
}
}
}
}
.queue-section {
margin-top: 20px;
.section-title {
font-size: 16px;
font-weight: bold;
color: #333;
margin-bottom: 15px;
padding-left: 10px;
border-left: 4px solid #667eea;
}
.pagination-wrapper {
margin-top: 20px;
display: flex;
justify-content: flex-end;
}
}
}
@keyframes pulse {
0% {
box-shadow: 0 0 0 0 rgba(102, 126, 234, 0.4);
}
70% {
box-shadow: 0 0 0 15px rgba(102, 126, 234, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(102, 126, 234, 0);
}
}
</style>