web/src/components/outpatient/MedicalQueue.vue

404 lines
9.8 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>
<Panel :title="'就诊队列'" style="height: 100%">
<template #tools>
<div @click="setDate" class="date-btn">
<span>{{ selectedDateStr }}</span>
<el-icon style="margin-left: 21px">
<Calendar/>
</el-icon>
</div>
<el-date-picker
v-model="selectedDate"
type="date"
placeholder="选择日期"
ref="datePickerRef"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
/>
</template>
<div class="panel-content" style="display: flex;flex-direction: column;height: 100%">
<div class="tabs">
<span v-for="(item,index) in statusList" :class="curStatus == item.status ? 'tabs-item' : ''"
@click="clickTab(item)">{{ item.label }}&nbsp;({{ item.num }})</span>
</div>
<div class="search">
<img src="/static/images/outpatient/search.png" class="search-icon" alt="搜索图标">
<input class="search-input" v-model="search" placeholder="搜索门诊单">
</div>
<div class="list">
<ul style="height: 100%">
<el-scrollbar style="height: 100%">
<li class="list-item" :class="curItem?.id == item.id ? 'active' : ''" v-for="(item, index) in list"
:key="index" @click="clickLi(item)">
<span class="item-avatar">
<img v-if="item.gender==1" class="avatar" src="/static/images/outpatient/man.png"
alt="头像"/>
<img v-if="item.gender==2" class="avatar" src="/static/images/outpatient/women.png"
alt="头像"/>
</span>
<span class="item-name">{{ item.name }}</span>
<span class="item-time">
{{ formatListTime(item.createDatetime) }}
</span>
<span class="item-type">{{ item.type == 2 ? '医保' : '自费' }}</span>
</li>
</el-scrollbar>
</ul>
</div>
</div>
</Panel>
</template>
<script setup lang="ts">
import {onMounted, ref, watch, onUnmounted} from "vue";
import Panel from "@/components/common/Panel.vue";
import {post} from "@/utils/request.ts";
import {formatListTime, getToday, getThisMonth, getCurrentDate, getEndOfDay} from "@/utils/dateUtils.ts";
import {apiConfig} from "@/assets/config/apiConfig.ts";
import {ElMessageBox} from "element-plus";
import {Calendar} from '@element-plus/icons-vue'
const curStatus = ref(1)
const search = ref('')
const curItem = ref<any>('')
const selectedDate: any = ref('')
const selectedDateStr: any = ref('')
const emit = defineEmits(['clickItem', 'changeTab'])
const datePickerRef = ref()
const clickTab = (item: any) => {
curStatus.value = item.status
emit('changeTab', item.status)
curItem.value = {}
}
const setDate = function () {
if (datePickerRef.value) {
datePickerRef.value.handleOpen()
}
}
const list = ref<any>([])
const statusList = ref<any>([
{
status: 1,
label: '候诊',
num: 0
},
{
status: 2,
label: '在诊',
num: 0
},
{
status: 3,
label: '已诊',
num: 0
}
])
const itemId = defineModel()
let refreshInterval: number | null = null; // 定义定时器变量
onMounted(() => {
selectedDate.value = getCurrentDate()
initStatusList()
if (curStatus.value == 1) {
init()
}
// 启动定时器,每秒更新一次
refreshInterval = setInterval(() => {
initList()
}, 60 * 1000); // 每1000毫秒即1秒执行一次
})
onUnmounted(() => {
// 组件卸载时清除定时器
if (refreshInterval !== null) {
clearInterval(refreshInterval);
refreshInterval = null;
}
});
const initList = async () => {
selectedDateStr.value = setDateTip()
try {
let data: any = await post(apiConfig.RegistrationList, {
query: {
status: curStatus.value,
beginTime: selectedDate.value,
endTime: getEndOfDay(new Date(selectedDate.value))
}
}, {catch_error: true});
list.value = data.list
if (itemId.value != null) {
list.value.forEach((item: any, index: any) => {
if (item.id == itemId.value && curStatus.value == 2) {
clickLi(item, false)
}
})
}
} catch (e) {
} finally {
}
initStatusList()
}
const loading = ref(true)
const init = async () => {
selectedDateStr.value = setDateTip()
clickLi(null)
loading.value = true
try {
let data: any = await post(apiConfig.RegistrationList, {
query: {
status: curStatus.value,
beginTime: selectedDate.value,
endTime: getEndOfDay(new Date(selectedDate.value))
}
}, {catch_error: true});
list.value = data.list
if (itemId.value != null) {
list.value.forEach((item: any, index: any) => {
if (item.id == itemId.value && curStatus.value == 2) {
clickLi(item, false)
}
})
}
} catch (e) {
} finally {
loading.value = false
}
initStatusList()
}
const initStatusList = () => {
post('statistics/getTipCount', {
beginTime: selectedDate.value,
endTime: getEndOfDay(new Date(selectedDate.value))
}).then((res: any) => {
statusList.value[0].num = res.waitDiagnosisCount
statusList.value[1].num = res.diagnosingCount
statusList.value[2].num = res.completeDiaCount
})
}
const clickLi = (item: any, showBox: any = true) => {
if (!item) {
return
}
curItem.value = item
if (item.status == 1 && showBox) {
ElMessageBox.confirm(`您将要接诊:${item.name}`, "提示", {
confirmButtonText: '确定',
cancelButtonText: '取消',
callback: (action: any) => {
if (action == "cancel") {
curItem.value = null
return
}
if (action == "confirm") {
post('registration/changeStatus', {id: item.id, status: 2}).then((res: any) => {
curStatus.value = 2
curItem.value = res
initStatusList()
emit('clickItem', curItem.value)
})
}
},
})
} else {
emit('clickItem', curItem.value)
}
}
const changeCurItemOrStatus = (item: any, status: any) => {
curStatus.value = status
init()
}
defineExpose({changeCurItemOrStatus})
watch(() => curStatus.value, () => {
init() // 重新初始化数据
})
const setDateTip = () => {
const seletctedDateObj = new Date(selectedDate.value);
//如果选择的日期是今天
if (seletctedDateObj.getFullYear() == new Date().getFullYear() && seletctedDateObj.getMonth() == new Date().getMonth() && seletctedDateObj.getDate() == new Date().getDate()) {
return '今天'
}
if (seletctedDateObj.getFullYear() == new Date().getFullYear() && seletctedDateObj.getMonth() == new Date().getMonth() && seletctedDateObj.getDate() == new Date().getDate() - 1) {
return '昨天'
}
//如果为今年
if (seletctedDateObj.getFullYear() == new Date().getFullYear()) {
return `${seletctedDateObj.getMonth() + 1}-${seletctedDateObj.getDate()}`
}
return seletctedDateObj.getFullYear();
}
watch(() => selectedDate.value, (newValue, oldValue) => {
curItem.value = null
emit('clickItem', curItem.value)
if (newValue == oldValue) {
init()
return;
}
if (newValue == null) {
return;
}
init()
})
</script>
<style scoped lang="scss">
.tabs {
height: 27px;
border-bottom: 1px solid #EAEAEC;
font-weight: 500;
color: #999999;
font-style: normal;
display: flex;
justify-content: space-between;
padding: 0 18px;
span {
cursor: pointer;
}
.tabs-item {
border-bottom: 2px solid #4D6DE4;
color: #4D6DE4;
padding-bottom: 10px;
}
}
.search {
position: relative;
margin: 16px 0;
padding: 0 16px;
.search-icon {
position: absolute;
left: 32px;
top: 50%;
transform: translateY(-50%);
width: 16px; // 调整图标大小
height: 16px; // 调整图标大小
z-index: 1;
}
.search-input {
width: 100%;
height: 42px;
background: #FFFFFF;
border-radius: 6px;
border: 1px solid #EAEAEC;
padding-left: 42px;
&:focus {
outline: none; // 移除默认的焦点轮廓
border-color: #5078c8; // 修改边框颜色
box-shadow: 0 0 5px rgba(#5078c8, 0.5); // 添加阴影效果
}
}
}
.list {
flex: 1;
display: flex;
min-height: 0;
flex-direction: column;
ul {
flex: 1;
min-height: 0;
.list-item {
height: 48px;
display: flex;
font-weight: 400;
padding: 0 16px;
font-size: 14px;
color: rgba(34, 42, 57, 0.7);
font-style: normal;
cursor: pointer;
span {
display: block;
line-height: 48px;
text-align: center;
}
.item-avatar {
width: 26px;
margin-right: 10px;
.avatar {
margin-top: 11px;
width: 26px;
height: 26px;
}
}
.item-name {
flex: 1;
min-width: 0;
text-align: left;
white-space: nowrap; // 防止文本换行
overflow: hidden; // 隐藏溢出的文本
text-overflow: ellipsis; // 显示省略号
}
.item-time {
width: 40px;
font-size: 12px;
}
.item-type {
width: 40px;
font-size: 12px;
}
&:hover {
background: rgba(#4D6DE4, 0.5);
}
.item_time {
white-space: nowrap; // 防止文本换行
overflow: hidden; // 隐藏溢出的文本
text-overflow: ellipsis; // 显示省略号
text-align: center;
}
}
.active {
color: #fff;
background: #4D6DE4;
&:hover {
background: #4D6DE4;
}
}
}
}
.date-btn {
width: 98px;
height: 32px;
background: #FFFFFF;
border-radius: 6px;
border: 1px solid #EAEAEC;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
:deep(.el-input) {
visibility: hidden;
width: 0;
height: 0;
position: absolute;
right: 0;
top: 50px;
}
</style>