This commit is contained in:
gr
2026-10-15 11:03:54 +08:00
parent 70ddc1a70a
commit bb28d93cec
64 changed files with 12747 additions and 420 deletions
+70 -9
View File
@@ -25,6 +25,7 @@
formData.pending_assign !== '1' &&
formData.pending_booking !== '1' &&
formData.completed_appointment !== '1' &&
formData.revisit_state === '' &&
formData.appointment_date === tab.value
}
]"
@@ -40,6 +41,13 @@
待预约
<em v-if="pendingBookingCount !== undefined">{{ pendingBookingCount }}</em>
</span>
<span
:class="['dh5-chip', 'dh5-chip--revisit', { active: formData.revisit_state === 'due' }]"
@click="handleRevisitDueTabClick"
>
复诊到期
<em v-if="revisitDueCount !== undefined">{{ revisitDueCount }}</em>
</span>
<span
:class="['dh5-chip', 'dh5-chip--done', { active: formData.completed_appointment === '1' }]"
@click="handleCompletedVisitTabClick"
@@ -170,13 +178,17 @@
</div>
</div>
<!-- 复诊块(仅已开方时显示) -->
<div v-if="row.has_prescription" class="dh5-row dh5-row--followup">
<!-- 复诊节点块(已开方或有复诊节点数据时显示;卡片头已有「已开方」标签,此处隐藏开方文案) -->
<div v-if="row.has_prescription || hasRevisitDue(revisitDueOf(row))" class="dh5-row dh5-row--followup">
<span class="dh5-row-key">复诊</span>
<div class="dh5-row-val">
<span>{{ row.followup_time_text || '—' }}</span>
<span class="dh5-meta-doctor">{{ row.followup_doctor_name || '—' }}</span>
<span v-if="row.followup_rx_voided" class="dh5-tag dh5-tag--gray">处方作废</span>
<div class="dh5-row-val dh5-row-val--revisit">
<revisit-node-cell
compact
:due="revisitDueOf(row)"
:has-prescription="!!row.has_prescription"
:followup-doctor-name="row.followup_doctor_name || ''"
:prescribed-text="row.followup_rx_voided ? '处方作废' : ''"
/>
</div>
</div>
@@ -625,6 +637,13 @@ import {
import useUserStore from '@/stores/modules/user'
import { defineAsyncComponent, computed, reactive, ref, onMounted, onUnmounted } from 'vue'
import dayjs from 'dayjs'
import RevisitNodeCell from './components/RevisitNodeCell.vue'
import {
hasRevisitDue,
isRevisitDueHighlight,
normalizeRevisitDue,
type RevisitDue
} from '@/utils/revisitDue'
const EditPopup = defineAsyncComponent(() => import('./edit.vue'))
const DetailPopup = defineAsyncComponent(() => import('./detail.vue'))
@@ -685,7 +704,9 @@ const formData = reactive({
has_appointment: '' as '' | '0' | '1',
pending_assign: '' as '' | '1',
pending_booking: '' as '' | '1',
completed_appointment: '' as '' | '1'
completed_appointment: '' as '' | '1',
/** 顶部「复诊到期」chip:due = 到期未挂号 ∪ 过号未面诊(后端 revisit_state) */
revisit_state: '' as '' | 'due'
})
const showMoreFilter = ref(false)
@@ -740,6 +761,7 @@ const handleReset = () => {
formData.pending_assign = ''
formData.pending_booking = ''
formData.completed_appointment = ''
formData.revisit_state = ''
pager.page = 1
getLists()
fetchDateCounts()
@@ -767,6 +789,7 @@ const handleDateTabClick = async (value: string) => {
formData.pending_assign = ''
formData.pending_booking = ''
formData.completed_appointment = ''
formData.revisit_state = ''
formData.has_appointment = ''
formData.appointment_date = value
pager.page = 1
@@ -778,6 +801,7 @@ const handlePendingBookingTabClick = async () => {
formData.pending_assign = ''
formData.pending_booking = '1'
formData.completed_appointment = ''
formData.revisit_state = ''
formData.appointment_date = ''
formData.has_appointment = '0'
pager.page = 1
@@ -789,6 +813,7 @@ const handleCompletedVisitTabClick = async () => {
formData.pending_assign = ''
formData.pending_booking = ''
formData.completed_appointment = '1'
formData.revisit_state = ''
formData.has_appointment = ''
formData.appointment_date = ''
pager.page = 1
@@ -800,6 +825,7 @@ const handlePendingAssignTabClick = async () => {
formData.pending_assign = '1'
formData.pending_booking = ''
formData.completed_appointment = ''
formData.revisit_state = ''
formData.has_appointment = ''
formData.appointment_date = ''
pager.page = 1
@@ -807,9 +833,27 @@ const handlePendingAssignTabClick = async () => {
fetchDateCounts()
}
/** 顶部「复诊到期」chip:到期未挂号 ∪ 过号未面诊;后端按 revisit_state=due 过滤,排序默认药尽日升序 */
const handleRevisitDueTabClick = async () => {
formData.pending_assign = ''
formData.pending_booking = ''
formData.completed_appointment = ''
formData.has_appointment = ''
formData.appointment_date = ''
formData.revisit_state = 'due'
pager.page = 1
await getLists()
fetchDateCounts()
}
const revisitDueCount = ref<number | undefined>(undefined)
/** 列表行 revisit_due → 规整对象(旧接口无字段时为 null,不渲染复诊块) */
const revisitDueOf = (row: any): RevisitDue | null => normalizeRevisitDue(row?.revisit_due)
const fetchDateCounts = async () => {
try {
const [yesterday, dayBefore, today, tomorrow, dayAfter, all, noApt, doneVisit, pending] = await Promise.all([
const [yesterday, dayBefore, today, tomorrow, dayAfter, all, noApt, doneVisit, pending, revisitDue] = await Promise.all([
tcmDiagnosisLists({ appointment_date: yesterdayStr.value, page_no: 1, page_size: 1 }),
tcmDiagnosisLists({ appointment_date: dayBeforeStr.value, page_no: 1, page_size: 1 }),
tcmDiagnosisLists({ appointment_date: todayStr.value, page_no: 1, page_size: 1 }),
@@ -818,7 +862,8 @@ const fetchDateCounts = async () => {
tcmDiagnosisLists({ page_no: 1, page_size: 1 }),
tcmDiagnosisLists({ has_appointment: 0, page_no: 1, page_size: 1 }),
tcmDiagnosisLists({ completed_appointment: 1, page_no: 1, page_size: 1 }),
tcmDiagnosisLists({ pending_assign: 1, page_no: 1, page_size: 1 })
tcmDiagnosisLists({ pending_assign: 1, page_no: 1, page_size: 1 }),
tcmDiagnosisLists({ revisit_state: 'due', page_no: 1, page_size: 1 })
])
dateCounts.value = {
[yesterdayStr.value]: yesterday?.count ?? 0,
@@ -831,6 +876,7 @@ const fetchDateCounts = async () => {
pendingBookingCount.value = noApt?.count ?? 0
completedVisitCount.value = doneVisit?.count ?? 0
pendingAssignCount.value = pending?.count ?? 0
revisitDueCount.value = revisitDue?.count ?? 0
} catch (e) {
console.error('获取日期数量失败', e)
}
@@ -898,7 +944,9 @@ const isDiagnosisConfirmed = (row: any) => {
return records.length > 0 && records.some((r: any) => r.is_confirmed == 1)
}
// 卡片左边条优先级(同 PC 行高亮):复诊超期/过号 > 未确认 > 未挂号
const getCardClass = (row: any) => {
if (isRevisitDueHighlight(revisitDueOf(row))) return 'dh5-card--overdue'
if (!isDiagnosisConfirmed(row)) return 'dh5-card--unconfirmed'
if (!row.has_appointment) return 'dh5-card--noapt'
return ''
@@ -1582,6 +1630,8 @@ $dh5-card-bg: #ffffff;
.dh5-chip--booking.active { background: $dh5-warn; }
.dh5-chip--done.active { background: $dh5-success; }
.dh5-chip--pending.active { background: $dh5-danger; }
.dh5-chip--revisit { color: #b91c1c; background: rgba(239, 68, 68, 0.10); }
.dh5-chip--revisit.active { color: #fff; background: $dh5-danger; }
.dh5-quick {
display: flex;
@@ -1675,6 +1725,12 @@ $dh5-card-bg: #ffffff;
.dh5-card--unconfirmed::before { background: $dh5-danger; }
.dh5-card--noapt::before { background: $dh5-warn; }
/* 复诊到期未挂号 / 过号未面诊:左边条同 danger,外框与底色轻微染红以区分「未确认」 */
.dh5-card--overdue::before { background: $dh5-danger; }
.dh5-card--overdue {
border-color: rgba(239, 68, 68, 0.35);
background: linear-gradient(90deg, rgba(239, 68, 68, 0.05) 0%, $dh5-card-bg 60%);
}
.dh5-card-head {
display: flex;
@@ -1800,6 +1856,11 @@ $dh5-card-bg: #ffffff;
font-size: 12px;
}
/* 复诊节点块:单元格组件自带多行布局,取消外层 flex 换行间距 */
.dh5-row-val--revisit {
display: block;
}
/* 挂号块 - 状态色 */
.dh5-row--apt {
background: #fafbfc;