This commit is contained in:
Your Name
2026-08-06 12:03:58 +08:00
parent 079e50006d
commit d5b0ab4709
335 changed files with 428 additions and 304 deletions
@@ -146,12 +146,20 @@
<el-table-column label="诊单日期" width="118">
<template #default="{ row }">{{ row.diagnosis_date_text || '—' }}</template>
</el-table-column>
<el-table-column label="操作" min-width="205" fixed="right">
<el-table-column label="操作" min-width="285" fixed="right">
<template #default="{ row }">
<div class="row-actions">
<el-button v-if="canEditDiagnosis" type="primary" link @click="openDiagnosis(row)">诊单</el-button>
<el-button v-else-if="canReadDiagnosis" type="primary" link @click="openReadonlyDiagnosis(row)">查看</el-button>
<el-button v-if="canBookAppointment" type="primary" link @click="openAppointment(row)">预约</el-button>
<el-button
v-if="canShowDiagnosisQRCode(row)"
type="primary"
link
@click="openDiagnosisQRCode(row)"
>
诊单二维码
</el-button>
<el-button
v-if="canBookAppointment && canCancelAppointment(row)"
type="danger"
@@ -187,6 +195,33 @@
<edit-popup ref="editRef" @success="refreshPage" />
<appointment-popup ref="appointmentRef" api-scene="my_patient" @success="refreshPage" />
<el-dialog
v-model="qrcodeDialogVisible"
title="诊单二维码"
width="400px"
:close-on-click-modal="false"
>
<div class="qrcode-body">
<template v-if="qrcodeLoading">
<el-icon class="is-loading" :size="40"><Loading /></el-icon>
<span>二维码生成中...</span>
</template>
<template v-else-if="qrcodeUrl">
<img :src="qrcodeUrl" alt="诊单二维码" class="qrcode-image" />
<div class="qrcode-meta">
<div>患者{{ currentQRCodePatient?.patient_name || '—' }}</div>
<div>挂号时间{{ currentQRCodePatient?.appointment_time_text || '—' }}</div>
<div>请使用企业微信扫描二维码然后转发给患者</div>
</div>
</template>
<span v-else class="qrcode-error">生成失败请重试</span>
</div>
<template #footer>
<el-button @click="qrcodeDialogVisible = false">关闭</el-button>
<el-button v-if="!qrcodeLoading" type="primary" @click="regenerateDiagnosisQRCode">重新生成</el-button>
</template>
</el-dialog>
</div>
</template>
@@ -194,11 +229,14 @@
import { computed, defineAsyncComponent, onMounted, reactive, ref } from 'vue'
import { useRouter } from 'vue-router'
import dayjs from 'dayjs'
import { Calendar, Clock, Lock, Refresh, Search } from '@element-plus/icons-vue'
import { Calendar, Clock, Loading, Lock, Refresh, Search } from '@element-plus/icons-vue'
import { usePaging } from '@/hooks/usePaging'
import { hasPermission } from '@/utils/perm'
import feedback from '@/utils/feedback'
import { myPatientCancelAppointment, myPatientLists } from '@/api/first_visit'
import { generateMiniProgramQrcode } from '@/api/tcm'
import { getWeappConfig } from '@/api/channel/weapp'
import useUserStore from '@/stores/modules/user'
const EditPopup = defineAsyncComponent(() => import('@/views/tcm/diagnosis/edit.vue'))
const AppointmentPopup = defineAsyncComponent(() => import('@/views/tcm/diagnosis/appointment.vue'))
@@ -209,6 +247,7 @@ type StatusFilter = '' | 'unconfirmed' | 'booked' | 'completed' | 'missed'
type DateType = 'all' | 'today' | 'tomorrow' | 'day_after' | 'last7' | 'last30' | 'custom'
const router = useRouter()
const userStore = useUserStore()
const activeWorkspace = ref('patients')
const activeDateType = ref<DateType>('all')
const customDateRange = ref<string[]>([])
@@ -216,6 +255,10 @@ const editRef = ref<any>()
const appointmentRef = ref<any>()
const orderPanelRef = ref<any>()
const progressPanelRef = ref<any>()
const qrcodeDialogVisible = ref(false)
const qrcodeLoading = ref(false)
const qrcodeUrl = ref('')
const currentQRCodePatient = ref<any>(null)
const formData = reactive({
keyword: '',
@@ -356,6 +399,57 @@ function openAppointment(row: any) {
})
}
function canShowDiagnosisQRCode(row: any) {
return canBookAppointment.value
&& Number(row.appointment_id) > 0
&& Number(row.appointment_status) === 1
&& Number(row.appointment_doctor_id) > 0
}
async function openDiagnosisQRCode(row: any) {
if (!canShowDiagnosisQRCode(row)) {
feedback.msgWarning('仅已挂号患者可以生成诊单二维码')
return
}
const diagnosisId = Number(row.diagnosis_id || row.id)
const patientId = Number(row.source_patient_id || row.diagnosis_id || row.id)
if (diagnosisId <= 0 || patientId <= 0) {
feedback.msgWarning('患者诊单信息不完整')
return
}
currentQRCodePatient.value = row
qrcodeDialogVisible.value = true
qrcodeLoading.value = true
qrcodeUrl.value = ''
try {
const config = await getWeappConfig()
if (!config?.app_id) {
throw new Error('小程序未配置,请先配置小程序信息')
}
const result = await generateMiniProgramQrcode({
diagnosis_id: diagnosisId,
doctor_id: Number(row.appointment_doctor_id),
patient_id: patientId,
share_user_id: userStore.userInfo?.id || ''
})
if (!result?.qrcode_url) {
throw new Error('二维码生成失败')
}
qrcodeUrl.value = result.qrcode_url
} catch (error: any) {
feedback.msgError(error?.msg || error?.message || '生成二维码失败,请重试')
} finally {
qrcodeLoading.value = false
}
}
function regenerateDiagnosisQRCode() {
if (currentQRCodePatient.value) {
openDiagnosisQRCode(currentQRCodePatient.value)
}
}
function canCancelAppointment(row: any) {
return Number(row.appointment_id) > 0 && [1, 4].includes(Number(row.appointment_status))
}
@@ -402,6 +496,36 @@ onMounted(() => {
color: #172033;
}
.qrcode-body {
display: flex;
min-height: 320px;
align-items: center;
justify-content: center;
flex-direction: column;
gap: 16px;
color: #7b8798;
}
.qrcode-image {
width: 256px;
height: 256px;
border: 1px solid #e1e7ed;
border-radius: 10px;
object-fit: contain;
}
.qrcode-meta {
display: grid;
gap: 6px;
color: #697587;
text-align: center;
font-size: 12px;
}
.qrcode-error {
color: var(--el-color-danger);
}
.page-heading {
display: flex;
align-items: center;