更新
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
<el-drawer
|
||||
v-model="visible"
|
||||
title="中医处方单"
|
||||
size="900px"
|
||||
size="1200px"
|
||||
:close-on-click-modal="false"
|
||||
@close="handleClose"
|
||||
>
|
||||
@@ -52,6 +52,16 @@
|
||||
<el-input v-model="formData.tongue" placeholder="舌象" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="舌象详情" prop="tongue_image">
|
||||
<el-input v-model="formData.tongue_image" placeholder="舌象详情" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="脉象详情" prop="pulse_condition">
|
||||
<el-input v-model="formData.pulse_condition" placeholder="脉象详情" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="临床诊断" prop="clinical_diagnosis">
|
||||
<el-input
|
||||
@@ -69,6 +79,7 @@
|
||||
<div class="section-title">
|
||||
中药处方 (RP)
|
||||
<el-button type="primary" size="small" @click="handleAddHerb">添加中药</el-button>
|
||||
<el-button type="success" size="small" @click="showLibraryDialog = true">从处方库导入</el-button>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<el-form-item label="处方价格" prop="amount" class="!mb-0">
|
||||
@@ -109,32 +120,113 @@
|
||||
|
||||
<div class="info-section">
|
||||
<el-row :gutter="16">
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item label="处方类型" prop="prescription_type">
|
||||
<el-select v-model="formData.prescription_type" placeholder="请选择处方类型" class="!w-full">
|
||||
<el-option label="浓缩水丸" value="浓缩水丸" />
|
||||
<el-option label="饮片" value="饮片" />
|
||||
<el-option label="颗粒" value="颗粒" />
|
||||
<el-option label="丸剂" value="丸剂" />
|
||||
<el-option label="散剂" value="散剂" />
|
||||
<el-option label="膏方" value="膏方" />
|
||||
<el-option label="汤剂" value="汤剂" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="服用天数" prop="dose_count">
|
||||
<el-form-item label="服用天数" prop="usage_days">
|
||||
<el-input-number v-model="formData.usage_days" :min="1" :max="365" class="!w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- <el-col :span="8">
|
||||
<el-form-item label="剂数" prop="dose_count">
|
||||
<el-input-number v-model="formData.dose_count" :min="1" :max="999" class="!w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="类型" prop="dose_unit">
|
||||
<el-select v-model="formData.dose_unit" placeholder="请选择类型" class="!w-full">
|
||||
<el-option label="浓缩水丸" value="浓缩水丸" />
|
||||
<el-option label="饮片" value="饮片" />
|
||||
<el-form-item label="剂量单位" prop="dose_unit">
|
||||
<el-select v-model="formData.dose_unit" placeholder="请选择" class="!w-full">
|
||||
<el-option label="剂" value="剂" />
|
||||
<el-option label="丸" value="丸" />
|
||||
<el-option label="袋" value="袋" />
|
||||
<el-option label="盒" value="盒" />
|
||||
<el-option label="瓶" value="瓶" />
|
||||
<el-option label="膏" value="膏" />
|
||||
<el-option label="贴" value="贴" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
<el-col :span="24">
|
||||
<el-form-item label="用法" prop="usage_instruction">
|
||||
<el-input v-model="formData.usage_instruction" placeholder="例如:水煎服,一日二次" maxlength="200" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="服用时间" prop="usage_time">
|
||||
<el-select v-model="formData.usage_time" placeholder="请选择服用时间" class="!w-full">
|
||||
<el-option label="饭前" value="饭前" />
|
||||
<el-option label="饭后" value="饭后" />
|
||||
<el-option label="饭中" value="饭中" />
|
||||
<el-option label="空腹" value="空腹" />
|
||||
<el-option label="睡前" value="睡前" />
|
||||
<el-option label="晨起" value="晨起" />
|
||||
<el-option label="随时" value="随时" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="服用说明" prop="usage_instruction">
|
||||
<el-select v-model="formData.usage_instruction" placeholder="请选择服用说明" class="!w-full">
|
||||
<el-option label="饭前" value="饭前" />
|
||||
<el-option label="饭后" value="饭后" />
|
||||
<el-col :span="12">
|
||||
<el-form-item label="服用方式" prop="usage_way">
|
||||
<el-select v-model="formData.usage_way" placeholder="请选择服用方式" class="!w-full">
|
||||
<el-option label="温水送服" value="温水送服" />
|
||||
<el-option label="开水冲服" value="开水冲服" />
|
||||
<el-option label="黄酒送服" value="黄酒送服" />
|
||||
<el-option label="淡盐水送服" value="淡盐水送服" />
|
||||
<el-option label="米汤送服" value="米汤送服" />
|
||||
<el-option label="嚼服" value="嚼服" />
|
||||
<el-option label="含化" value="含化" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="忌口" prop="dietary_taboo">
|
||||
<el-select v-model="formData.dietary_taboo" multiple placeholder="请选择忌口内容(可多选)" class="!w-full">
|
||||
<el-option label="辛辣食物" value="辛辣食物" />
|
||||
<el-option label="生冷食物" value="生冷食物" />
|
||||
<el-option label="油腻食物" value="油腻食物" />
|
||||
<el-option label="海鲜" value="海鲜" />
|
||||
<el-option label="牛羊肉" value="牛羊肉" />
|
||||
<el-option label="鸡蛋" value="鸡蛋" />
|
||||
<el-option label="豆制品" value="豆制品" />
|
||||
<el-option label="酒类" value="酒类" />
|
||||
<el-option label="浓茶" value="浓茶" />
|
||||
<el-option label="咖啡" value="咖啡" />
|
||||
<el-option label="烟草" value="烟草" />
|
||||
<el-option label="萝卜" value="萝卜" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="其他说明" prop="usage_notes">
|
||||
<el-input v-model="formData.usage_notes" type="textarea" :rows="2" placeholder="其他服用注意事项" maxlength="200" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="医师" prop="doctor_name">
|
||||
<el-input v-model="formData.doctor_name" placeholder="医师姓名" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="是否共享" prop="is_shared">
|
||||
<el-switch
|
||||
v-model="formData.is_shared"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
active-text="所有人可见"
|
||||
inactive-text="仅自己可见"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="医师签名" prop="doctor_signature" required>
|
||||
<div class="signature-pad-wrap">
|
||||
@@ -219,7 +311,20 @@
|
||||
<div class="prescription-footer">
|
||||
<div class="footer-left">
|
||||
<div class="footer-dosage">
|
||||
服用{{ savedPrescription.dose_count }}天, {{ savedPrescription.dose_unit || '浓缩水丸' }}, {{ savedPrescription.usage_instruction }}
|
||||
服用{{ savedPrescription.usage_days || savedPrescription.dose_count }}天, {{ savedPrescription.prescription_type }}
|
||||
{{ savedPrescription.usage_instruction }}
|
||||
|
||||
</div>
|
||||
<div class="footer-dosage">
|
||||
服用时间: {{ savedPrescription.usage_time ?' ' + savedPrescription.usage_time : '' }}
|
||||
<text style="margin-left: 20px;"></text>服用方式: {{ savedPrescription.usage_way ? ' ' + savedPrescription.usage_way : '' }}
|
||||
</div>
|
||||
|
||||
<div v-if="savedPrescription.dietary_taboo && savedPrescription.dietary_taboo.length" class="footer-dietary">
|
||||
忌口:{{ Array.isArray(savedPrescription.dietary_taboo) ? savedPrescription.dietary_taboo.join('、') : savedPrescription.dietary_taboo }}
|
||||
</div>
|
||||
<div v-if="savedPrescription.usage_notes" class="footer-notes">
|
||||
{{ savedPrescription.usage_notes }}
|
||||
</div>
|
||||
<!-- <div class="footer-amount">金额 {{ savedPrescription.amount }}</div> -->
|
||||
</div>
|
||||
@@ -374,17 +479,83 @@
|
||||
</div>
|
||||
</template>
|
||||
</el-drawer>
|
||||
|
||||
<!-- 处方库选择弹窗 -->
|
||||
<el-dialog
|
||||
v-model="showLibraryDialog"
|
||||
title="从处方库导入"
|
||||
width="800px"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<div class="mb-4">
|
||||
<el-input
|
||||
v-model="librarySearchName"
|
||||
placeholder="请输入处方名称搜索"
|
||||
clearable
|
||||
@keyup.enter="searchLibrary"
|
||||
@clear="searchLibrary"
|
||||
>
|
||||
<template #append>
|
||||
<el-button :icon="Search" @click="searchLibrary" />
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
v-loading="libraryLoading"
|
||||
:data="libraryList"
|
||||
height="400"
|
||||
@row-click="handleSelectLibrary"
|
||||
style="cursor: pointer"
|
||||
>
|
||||
<el-table-column label="处方名称" prop="prescription_name" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column label="药材数量" width="100">
|
||||
<template #default="{ row }">
|
||||
{{ row.herbs?.length || 0 }}味
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="药材明细" min-width="300" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.herbs && row.herbs.length > 0">
|
||||
{{ row.herbs.map((h: any) => `${h.name} ${h.dosage}g`).join('、') }}
|
||||
</span>
|
||||
<span v-else class="text-gray-400">暂无药材</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建人" prop="creator_name" width="100" />
|
||||
<el-table-column label="操作" width="100" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click.stop="handleImportLibrary(row)">
|
||||
导入
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div class="flex justify-end mt-4">
|
||||
<el-pagination
|
||||
v-model:current-page="libraryPage"
|
||||
v-model:page-size="libraryPageSize"
|
||||
:total="libraryTotal"
|
||||
:page-sizes="[10, 15, 20, 50]"
|
||||
layout="total, sizes, prev, pager, next"
|
||||
@current-change="loadLibraryList"
|
||||
@size-change="loadLibraryList"
|
||||
/>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import feedback from '@/utils/feedback'
|
||||
import { prescriptionAdd, prescriptionDetail, prescriptionGetByAppointment, prescriptionVoid, tcmDiagnosisDetail } from '@/api/tcm'
|
||||
import { prescriptionAdd, prescriptionDetail, prescriptionGetByAppointment, prescriptionVoid, tcmDiagnosisDetail, prescriptionLibraryLists } from '@/api/tcm'
|
||||
import { getDictData } from '@/api/app'
|
||||
import html2canvas from 'html2canvas'
|
||||
import { jsPDF } from 'jspdf'
|
||||
import useUserStore from '@/stores/modules/user'
|
||||
import useAppStore from '@/stores/modules/app'
|
||||
import { Download, Document } from '@element-plus/icons-vue'
|
||||
import { Search } from '@element-plus/icons-vue'
|
||||
|
||||
interface Herb {
|
||||
name: string
|
||||
@@ -394,6 +565,8 @@ interface Herb {
|
||||
interface PrescriptionForm {
|
||||
diagnosis_id: number
|
||||
appointment_id: number
|
||||
prescription_name: string
|
||||
prescription_type: string
|
||||
patient_name: string
|
||||
gender: number
|
||||
gender_desc: string
|
||||
@@ -403,15 +576,23 @@ interface PrescriptionForm {
|
||||
prescription_date: string
|
||||
pulse: string
|
||||
tongue: string
|
||||
tongue_image: string
|
||||
pulse_condition: string
|
||||
clinical_diagnosis: string
|
||||
case_record: any
|
||||
herbs: Herb[]
|
||||
dose_count: number
|
||||
dose_unit: string
|
||||
usage_days: number
|
||||
usage_instruction: string
|
||||
usage_time: string
|
||||
usage_way: string
|
||||
dietary_taboo: string[]
|
||||
usage_notes: string
|
||||
amount: number
|
||||
doctor_name: string
|
||||
doctor_signature: string
|
||||
is_shared: number
|
||||
}
|
||||
|
||||
const emit = defineEmits(['success'])
|
||||
@@ -426,6 +607,15 @@ const signatureCanvasRef = ref<HTMLCanvasElement>()
|
||||
const isDrawing = ref(false)
|
||||
const savedPrescription = ref<any>(null)
|
||||
|
||||
// 处方库相关
|
||||
const showLibraryDialog = ref(false)
|
||||
const libraryLoading = ref(false)
|
||||
const libraryList = ref<any[]>([])
|
||||
const librarySearchName = ref('')
|
||||
const libraryPage = ref(1)
|
||||
const libraryPageSize = ref(15)
|
||||
const libraryTotal = ref(0)
|
||||
|
||||
const templateConfig = reactive({
|
||||
stationName: '成都双流甄养堂互联网医院',
|
||||
showDisclaimer: true,
|
||||
@@ -435,6 +625,8 @@ const templateConfig = reactive({
|
||||
const formData = reactive<PrescriptionForm>({
|
||||
diagnosis_id: 0,
|
||||
appointment_id: 0,
|
||||
prescription_name: '',
|
||||
prescription_type: '浓缩水丸',
|
||||
patient_name: '',
|
||||
gender: 0,
|
||||
gender_desc: '女',
|
||||
@@ -444,15 +636,23 @@ const formData = reactive<PrescriptionForm>({
|
||||
prescription_date: '',
|
||||
pulse: '',
|
||||
tongue: '',
|
||||
tongue_image: '',
|
||||
pulse_condition: '',
|
||||
clinical_diagnosis: '',
|
||||
case_record: null as any,
|
||||
herbs: [],
|
||||
dose_count: 1,
|
||||
dose_unit: '浓缩水丸',
|
||||
usage_instruction: '饭前',
|
||||
dose_unit: '剂',
|
||||
usage_days: 7,
|
||||
usage_instruction: '水煎服,一日二次',
|
||||
usage_time: '饭前',
|
||||
usage_way: '温水送服',
|
||||
dietary_taboo: [],
|
||||
usage_notes: '',
|
||||
amount: 0,
|
||||
doctor_name: '',
|
||||
doctor_signature: ''
|
||||
doctor_signature: '',
|
||||
is_shared: 0
|
||||
})
|
||||
|
||||
const userStore = useUserStore()
|
||||
@@ -599,6 +799,8 @@ const open = async (data: any, options?: { templateId?: number; stationName?: st
|
||||
|
||||
formData.diagnosis_id = Number(diagnosisId)
|
||||
formData.appointment_id = appointmentId
|
||||
formData.prescription_name = ''
|
||||
formData.prescription_type = '浓缩水丸'
|
||||
formData.patient_name = data.patient_name || diagnosis.patient_name || ''
|
||||
formData.gender = data.patient_gender ?? diagnosis.gender ?? 0
|
||||
formData.gender_desc = formData.gender === 1 ? '男' : '女'
|
||||
@@ -608,15 +810,23 @@ const open = async (data: any, options?: { templateId?: number; stationName?: st
|
||||
formData.prescription_date = new Date().toISOString().slice(0, 10)
|
||||
formData.pulse = diagnosis.pulse || ''
|
||||
formData.tongue = diagnosis.tongue_coating || diagnosis.tongue || ''
|
||||
formData.tongue_image = ''
|
||||
formData.pulse_condition = ''
|
||||
formData.clinical_diagnosis = buildClinicalDiagnosis(diagnosis)
|
||||
formData.case_record = caseRecord
|
||||
formData.herbs = []
|
||||
formData.dose_count = 1
|
||||
formData.dose_unit = '浓缩水丸'
|
||||
formData.usage_instruction = '饭前'
|
||||
formData.dose_unit = '剂'
|
||||
formData.usage_days = 7
|
||||
formData.usage_instruction = '水煎服,一日二次'
|
||||
formData.usage_time = '饭前'
|
||||
formData.usage_way = '温水送服'
|
||||
formData.dietary_taboo = []
|
||||
formData.usage_notes = ''
|
||||
formData.amount = 0
|
||||
formData.doctor_name = userStore.userInfo?.name || ''
|
||||
formData.doctor_signature = ''
|
||||
formData.is_shared = 0
|
||||
|
||||
savedPrescription.value = null
|
||||
visible.value = true
|
||||
@@ -721,6 +931,59 @@ const handleRemoveHerb = (index: number) => {
|
||||
formData.herbs.splice(index, 1)
|
||||
}
|
||||
|
||||
// 处方库相关方法
|
||||
const loadLibraryList = async () => {
|
||||
libraryLoading.value = true
|
||||
try {
|
||||
const res = await prescriptionLibraryLists({
|
||||
page_no: libraryPage.value,
|
||||
page_size: libraryPageSize.value,
|
||||
prescription_name: librarySearchName.value,
|
||||
is_public: ''
|
||||
})
|
||||
libraryList.value = res.lists || []
|
||||
libraryTotal.value = res.count || 0
|
||||
} catch (error) {
|
||||
console.error('加载处方库失败:', error)
|
||||
feedback.msgError('加载处方库失败')
|
||||
} finally {
|
||||
libraryLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const searchLibrary = () => {
|
||||
libraryPage.value = 1
|
||||
loadLibraryList()
|
||||
}
|
||||
|
||||
const handleSelectLibrary = (row: any) => {
|
||||
// 点击行也可以导入
|
||||
handleImportLibrary(row)
|
||||
}
|
||||
|
||||
const handleImportLibrary = (row: any) => {
|
||||
if (!row.herbs || row.herbs.length === 0) {
|
||||
feedback.msgWarning('该处方没有药材信息')
|
||||
return
|
||||
}
|
||||
|
||||
// 深拷贝药材数据并导入
|
||||
const importedHerbs = JSON.parse(JSON.stringify(row.herbs))
|
||||
formData.herbs = importedHerbs
|
||||
|
||||
feedback.msgSuccess(`已导入处方「${row.prescription_name}」,共${importedHerbs.length}味药材`)
|
||||
showLibraryDialog.value = false
|
||||
}
|
||||
|
||||
// 监听处方库弹窗打开,自动加载数据
|
||||
watch(showLibraryDialog, (newVal) => {
|
||||
if (newVal) {
|
||||
librarySearchName.value = ''
|
||||
libraryPage.value = 1
|
||||
loadLibraryList()
|
||||
}
|
||||
})
|
||||
|
||||
const handleSave = async () => {
|
||||
if (!formData.clinical_diagnosis?.trim()) {
|
||||
feedback.msgWarning('请输入临床诊断')
|
||||
@@ -751,6 +1014,8 @@ const handleSave = async () => {
|
||||
const res = await prescriptionAdd({
|
||||
diagnosis_id: formData.diagnosis_id,
|
||||
appointment_id: formData.appointment_id,
|
||||
prescription_name: formData.prescription_name,
|
||||
prescription_type: formData.prescription_type,
|
||||
patient_name: formData.patient_name,
|
||||
gender: formData.gender,
|
||||
age: formData.age,
|
||||
@@ -759,15 +1024,23 @@ const handleSave = async () => {
|
||||
prescription_date: formData.prescription_date,
|
||||
pulse: formData.pulse,
|
||||
tongue: formData.tongue,
|
||||
tongue_image: formData.tongue_image,
|
||||
pulse_condition: formData.pulse_condition,
|
||||
clinical_diagnosis: formData.clinical_diagnosis,
|
||||
case_record: formData.case_record,
|
||||
herbs: formData.herbs,
|
||||
dose_count: formData.dose_count,
|
||||
dose_unit: formData.dose_unit || '浓缩水丸',
|
||||
dose_unit: formData.dose_unit,
|
||||
usage_days: formData.usage_days,
|
||||
usage_instruction: formData.usage_instruction,
|
||||
usage_time: formData.usage_time,
|
||||
usage_way: formData.usage_way,
|
||||
dietary_taboo: formData.dietary_taboo,
|
||||
usage_notes: formData.usage_notes,
|
||||
amount: formData.amount,
|
||||
doctor_name: formData.doctor_name,
|
||||
doctor_signature: formData.doctor_signature
|
||||
doctor_signature: formData.doctor_signature,
|
||||
is_shared: formData.is_shared
|
||||
})
|
||||
const id = res?.id
|
||||
if (id) {
|
||||
@@ -825,6 +1098,8 @@ const handleNewPrescription = async () => {
|
||||
// 将患者信息、诊断信息填入表单,新建处方时保留
|
||||
formData.diagnosis_id = saved.diagnosis_id ?? formData.diagnosis_id
|
||||
formData.appointment_id = saved.appointment_id ?? formData.appointment_id
|
||||
formData.prescription_name = ''
|
||||
formData.prescription_type = saved.prescription_type || '浓缩水丸'
|
||||
formData.patient_name = saved.patient_name || ''
|
||||
formData.gender = saved.gender ?? 0
|
||||
formData.gender_desc = saved.gender === 1 ? '男' : '女'
|
||||
@@ -834,13 +1109,21 @@ const handleNewPrescription = async () => {
|
||||
formData.prescription_date = new Date().toISOString().slice(0, 10)
|
||||
formData.pulse = saved.pulse || ''
|
||||
formData.tongue = saved.tongue || ''
|
||||
formData.tongue_image = ''
|
||||
formData.pulse_condition = ''
|
||||
formData.clinical_diagnosis = saved.clinical_diagnosis || ''
|
||||
formData.dose_count = 1
|
||||
formData.dose_unit = saved.dose_unit || '浓缩水丸'
|
||||
formData.usage_instruction = '饭前'
|
||||
formData.dose_unit = saved.dose_unit || '剂'
|
||||
formData.usage_days = 7
|
||||
formData.usage_instruction = '水煎服,一日二次'
|
||||
formData.usage_time = '饭前'
|
||||
formData.usage_way = '温水送服'
|
||||
formData.dietary_taboo = []
|
||||
formData.usage_notes = ''
|
||||
formData.amount = 0
|
||||
formData.doctor_name = userStore.userInfo?.name || saved.doctor_name || ''
|
||||
formData.doctor_signature = ''
|
||||
formData.is_shared = 0
|
||||
formData.herbs = []
|
||||
// 新建处方时重新获取病历(旧处方可能没有 case_record)
|
||||
formData.case_record = saved.case_record && Object.keys(saved.case_record).length > 0
|
||||
|
||||
Reference in New Issue
Block a user