移除签名成功后自动关闭弹窗的 setTimeout,改为保留弹窗让用户查看已签发的医嘱状态。 新增 isSignedProp 传递给子组件,使重新打开弹窗时按钮名称保持为"提交医嘱"而非重置为"一键签名并生成医嘱"。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1196 lines
40 KiB
Vue
Executable File
1196 lines
40 KiB
Vue
Executable File
<template>
|
||
<div class="temporary-medical-container">
|
||
<!-- 顶部区域:标题 + 患者信息 + 操作按钮 -->
|
||
<div class="top-container">
|
||
<!-- 标题栏 -->
|
||
<div class="title-bar">
|
||
<h1 class="title-text">门诊术中临时医嘱</h1>
|
||
</div>
|
||
<!-- 患者信息卡 -->
|
||
<div class="patient-info-card">
|
||
<div class="info-item">
|
||
<span class="info-label">患者:</span>
|
||
<span class="info-value">{{ patientInfo.patientName || '-' }}</span>
|
||
</div>
|
||
<div class="info-item">
|
||
<span class="info-label">就诊卡号:</span>
|
||
<span class="info-value">{{ patientInfo.identifierNo || '-' }}</span>
|
||
</div>
|
||
<div class="info-item">
|
||
<span class="info-label">手术单号:</span>
|
||
<span class="info-value">{{ patientInfo.operCode || '-' }}</span>
|
||
</div>
|
||
<div class="info-item">
|
||
<span class="info-label">科室:</span>
|
||
<span class="info-value">{{ patientInfo.roomCode || '-' }}</span>
|
||
</div>
|
||
<div class="info-item">
|
||
<span class="info-label">医师:</span>
|
||
<span class="info-value">{{ patientInfo.doctorName || '-' }}</span>
|
||
</div>
|
||
<div class="info-item">
|
||
<span class="info-label">角色:</span>
|
||
<span class="info-value">{{ patientInfo.role || '-' }}</span>
|
||
</div>
|
||
</div>
|
||
<!-- 操作按钮组 -->
|
||
<div class="action-buttons">
|
||
<el-button class="refresh-btn" @click="handleRefresh">
|
||
<span>↻</span> 刷新
|
||
</el-button>
|
||
<el-button class="quote-btn" @click="handleQuoteBilling">
|
||
引用计费
|
||
</el-button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 已引用计费药品区域 -->
|
||
<div class="medicine-section">
|
||
<div class="section-title">
|
||
一、已引用计费药品(待生成医嘱)
|
||
</div>
|
||
<el-table
|
||
:data="billingMedicines"
|
||
stripe
|
||
border
|
||
style="width: 100%;"
|
||
fit
|
||
>
|
||
<el-table-column label="序号" type="index" width="60" align="center" />
|
||
<el-table-column label="药品名称" prop="medicineName" min-width="150" show-overflow-tooltip />
|
||
<el-table-column label="规格" prop="specification" min-width="100" align="center" />
|
||
<el-table-column label="数量" prop="quantity" width="80" align="center">
|
||
<template #default="{ row }">
|
||
{{ row.quantity || 0 }}
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="批号" prop="batchNumber" min-width="120" align="center" />
|
||
<el-table-column label="单价" prop="unitPrice" min-width="80" align="center">
|
||
<template #default="{ row }">
|
||
{{ row.unitPrice ? `¥${row.unitPrice}` : '-' }}
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="小计" prop="subtotal" min-width="100" align="center">
|
||
<template #default="{ row }">
|
||
{{ row.subtotal ? `¥${(row.unitPrice * row.quantity).toFixed(2)}` : '-' }}
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="医保" prop="insuranceType" width="80" align="center">
|
||
<template #default="{ row }">
|
||
<el-tag
|
||
:size="'small'"
|
||
:class="getInsuranceClass(row.insuranceType)"
|
||
>
|
||
{{ row.insuranceType || '-' }}
|
||
</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
|
||
<div class="medicine-summary">
|
||
<div class="summary-item insurance">医保内:¥{{ insuranceAmount.toFixed(2) }}</div>
|
||
<div class="summary-item self-pay">自费:¥{{ selfPayAmount.toFixed(2) }}</div>
|
||
<div class="summary-item total">总计:¥{{ totalAmount.toFixed(2) }}</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 临时医嘱预览区域 -->
|
||
<div class="advice-section">
|
||
<div class="section-title">
|
||
二、临时医嘱预览(已生成)
|
||
</div>
|
||
<el-table
|
||
:data="displayAdvices"
|
||
stripe
|
||
border
|
||
style="width: 100%;"
|
||
fit
|
||
>
|
||
<el-table-column label="序号" type="index" width="60" align="center" />
|
||
<el-table-column label="医嘱名称" prop="adviceName" min-width="150" show-overflow-tooltip />
|
||
<el-table-column label="剂量" prop="dosage" min-width="80" align="center" />
|
||
<el-table-column label="单位" prop="unit" min-width="80" align="center" />
|
||
<el-table-column label="用法" prop="usage" min-width="100" show-overflow-tooltip>
|
||
<template #default="{ row }">
|
||
{{ row.usageLabel || getUsageLabel(row.usage) }}
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="频次" prop="frequency" min-width="80" align="center" />
|
||
<el-table-column label="执行时间" prop="executeTime" min-width="160" align="center" />
|
||
<el-table-column label="操作" min-width="140" align="center">
|
||
<template #default="{ $index }">
|
||
<el-button link type="primary" @click="handleEditAdvice($index)">编辑</el-button>
|
||
<el-button link type="danger" @click="handleDeleteAdvice($index)">删除</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</div>
|
||
|
||
<!-- 医师电子签名区域 -->
|
||
<div class="signature-section">
|
||
<div class="section-title">
|
||
三、医师电子签名
|
||
</div>
|
||
<!-- 签名信息卡 -->
|
||
<div class="signature-card">
|
||
<div class="signature-info">
|
||
<span class="info-label">签名医师:</span>
|
||
<span class="info-value" :class="{ 'unsigned': !isSigned }">{{ isSigned ? currentUser.name : '未签名' }}</span>
|
||
</div>
|
||
<div class="signature-info">
|
||
<span class="info-label">签名时间:</span>
|
||
<span class="info-value">{{ signatureTime || '-' }}</span>
|
||
</div>
|
||
</div>
|
||
<!-- 底部操作按钮 -->
|
||
<div class="signature-actions">
|
||
<el-button class="cancel-btn" @click="handleCancel">取消</el-button>
|
||
<el-button
|
||
class="sign-btn"
|
||
@click="handleSignAndSubmit"
|
||
>
|
||
{{ isSigned ? '提交医嘱' : '一键签名并生成医嘱' }}
|
||
</el-button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 签名密码弹窗 -->
|
||
<el-dialog v-model="showSignDialog" title="弹窗-签名密码" width="400px" append-to-body>
|
||
<div class="sign-dialog-content">
|
||
<p>请输入账户密码:</p>
|
||
<el-input
|
||
v-model="signPassword"
|
||
type="password"
|
||
placeholder="请输入密码"
|
||
style="margin-bottom: 16px"
|
||
@keyup.enter="confirmSign"
|
||
/>
|
||
<div class="dialog-actions">
|
||
<el-button @click="showSignDialog = false">取消</el-button>
|
||
<el-button type="primary" @click="confirmSign">确认</el-button>
|
||
</div>
|
||
</div>
|
||
</el-dialog>
|
||
|
||
<!-- 编辑医嘱弹窗 -->
|
||
<el-dialog v-model="showEditDialog" title="编辑医嘱" width="500px" append-to-body>
|
||
<div class="edit-dialog-content">
|
||
<el-form :model="editForm" label-width="80px">
|
||
<el-form-item label="药品名称">
|
||
<el-input v-model="editForm.adviceName" disabled />
|
||
</el-form-item>
|
||
<el-form-item label="剂量" required>
|
||
<el-input v-model.number="editForm.dosage" placeholder="请输入剂量" />
|
||
</el-form-item>
|
||
<el-form-item label="单位">
|
||
<el-input v-model="editForm.unit" placeholder="请输入单位" />
|
||
</el-form-item>
|
||
<el-form-item label="用法" required>
|
||
<el-select
|
||
v-if="getMethodCodeDict.length > 0"
|
||
v-model="editForm.usage"
|
||
placeholder="请选择用法"
|
||
style="width: 100%"
|
||
filterable
|
||
>
|
||
<el-option
|
||
v-for="dict in getMethodCodeDict"
|
||
:key="dict.value"
|
||
:label="dict.label"
|
||
:value="dict.value"
|
||
/>
|
||
</el-select>
|
||
<el-input v-else disabled placeholder="加载中..." />
|
||
</el-form-item>
|
||
<el-form-item label="频次">
|
||
<el-input v-model="editForm.frequency" disabled />
|
||
</el-form-item>
|
||
</el-form>
|
||
<div class="dialog-actions">
|
||
<el-button @click="handleCancelEdit">取消</el-button>
|
||
<el-button type="primary" @click="handleSaveEdit">保存</el-button>
|
||
</div>
|
||
</div>
|
||
</el-dialog>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, computed, getCurrentInstance, onMounted, watch, nextTick } from 'vue'
|
||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||
import useUserStore from '@/store/modules/user'
|
||
import { checkPassword } from '@/api/surgicalschedule'
|
||
import { savePrescription } from '@/views/clinicmanagement/bargain/component/api.js'
|
||
|
||
// 定义props
|
||
const props = defineProps({
|
||
// 患者和医生信息
|
||
patientInfo: {
|
||
type: Object,
|
||
default: () => ({
|
||
patientName: '',
|
||
visitId: '',
|
||
operCode: '',
|
||
roomCode: '',
|
||
doctorName: '',
|
||
role: '',
|
||
patientId: null,
|
||
organizationId: null,
|
||
})
|
||
},
|
||
// 一区域:已引用计费药品(待生成医嘱)
|
||
billingMedicines: {
|
||
type: Array,
|
||
default: () => []
|
||
},
|
||
// 二区域:临时医嘱预览(已生成医嘱)- v-model:temporary-advices 对应 prop 名
|
||
temporaryAdvices: {
|
||
type: Array,
|
||
default: () => []
|
||
},
|
||
// 签名状态:用于保持按钮名称一致性
|
||
isSignedProp: {
|
||
type: Boolean,
|
||
default: false
|
||
}
|
||
})
|
||
|
||
// 定义emit事件
|
||
const emit = defineEmits(['submit', 'cancel', 'refresh', 'quote-billing', 'update:temporary-advices'])
|
||
|
||
// 用户store
|
||
const userStore = useUserStore()
|
||
|
||
// 获取当前实例
|
||
const { proxy } = getCurrentInstance()
|
||
|
||
// 获取字典数据(与门诊医生站保持一致)
|
||
const { method_code } = proxy.useDict('method_code')
|
||
|
||
// 🔧 新增:用法编码映射表(将通用编码映射到后端字典的正确编码)
|
||
const usageCodeMapping = {
|
||
'iv': '404', // 静脉注射
|
||
'po': '1', // 口服
|
||
'im': '403', // 肌肉注射
|
||
'sc': '401', // 皮下注射
|
||
'ivgtt': '405', // 静脉滴注
|
||
'ih': '5', // 吸入给药
|
||
'it': '610', // 含化
|
||
'ip': '604', // 腹腔用药
|
||
'top': '6', // 局部用药
|
||
'pr': '2' // 直肠给药
|
||
}
|
||
|
||
// 🔧 新增:将用法编码映射到后端字典的正确编码
|
||
const mapUsageCode = (advice) => {
|
||
const mappedAdvice = { ...advice }
|
||
if (usageCodeMapping[advice.usage]) {
|
||
mappedAdvice.usage = usageCodeMapping[advice.usage]
|
||
}
|
||
return mappedAdvice
|
||
}
|
||
|
||
// 🔧 新增:本地备用用法字典,确保字典未加载时也能显示中文
|
||
const localMethodCode = [
|
||
{ value: '404', label: '静脉注射' },
|
||
{ value: '1', label: '口服' },
|
||
{ value: '403', label: '肌肉注射' },
|
||
{ value: '401', label: '皮下注射' },
|
||
{ value: '405', label: '静脉滴注' },
|
||
{ value: '5', label: '吸入给药' },
|
||
{ value: '610', label: '含化' },
|
||
{ value: '604', label: '腹腔用药' },
|
||
{ value: '6', label: '局部用药' },
|
||
{ value: '2', label: '直肠给药' }
|
||
]
|
||
|
||
// 🔧 新增:获取用法字典(优先使用从后端加载的,否则使用本地备用)
|
||
const getMethodCodeDict = computed(() => {
|
||
let dict = method_code.value && method_code.value.length > 0 ? method_code.value : localMethodCode
|
||
return dict
|
||
})
|
||
|
||
// 响应式数据 - isSigned 从父组件传入的 prop 初始化
|
||
const isSigned = ref(props.isSignedProp)
|
||
const signatureTime = ref('')
|
||
const showSignDialog = ref(false)
|
||
const signPassword = ref('')
|
||
const showEditDialog = ref(false)
|
||
const currentEditIndex = ref(-1)
|
||
const editForm = ref({
|
||
adviceName: '',
|
||
dosage: '',
|
||
unit: '',
|
||
usage: '',
|
||
frequency: '临时'
|
||
})
|
||
|
||
// 计算属性
|
||
const currentUser = computed(() => ({
|
||
name: userStore.name || '未知用户',
|
||
id: userStore.id
|
||
}))
|
||
|
||
const insuranceAmount = computed(() => {
|
||
return (props.billingMedicines || [])
|
||
.filter(med => med.insuranceType === '甲' || med.insuranceType === '乙' || med.insuranceType === '医保')
|
||
.reduce((sum, med) => sum + (Number(med.subtotal) || 0), 0)
|
||
})
|
||
|
||
const selfPayAmount = computed(() => {
|
||
return (props.billingMedicines || [])
|
||
.filter(med => !med.insuranceType || med.insuranceType === '自费')
|
||
.reduce((sum, med) => sum + (Number(med.subtotal) || 0), 0)
|
||
})
|
||
|
||
const totalAmount = computed(() => {
|
||
return Number(insuranceAmount.value || 0) + Number(selfPayAmount.value || 0)
|
||
})
|
||
|
||
// 将计费药品转换为临时医嘱数据
|
||
const convertedAdvices = computed(() => {
|
||
return props.billingMedicines.map((medicine, index) => {
|
||
// 解析规格中的数值和单位
|
||
const specMatch = medicine.specification ? medicine.specification.match(/(\d+)(\D+)/) : null
|
||
const specValue = specMatch ? parseInt(specMatch[1]) : 1
|
||
const specUnit = specMatch ? specMatch[2] : 'ml'
|
||
|
||
// 计算剂量 = 规格数值 × 数量
|
||
const dosage = specValue * (medicine.quantity || 1)
|
||
|
||
// 🔧 修复:根据药品名称判断用法,使用后端字典的正确编码
|
||
let usageCode = '404' // 默认静脉注射编码
|
||
let usageLabel = '静脉注射' // 默认显示名称
|
||
if (medicine.medicineName && medicine.medicineName.includes('注射液')) {
|
||
usageCode = '404'
|
||
usageLabel = '静脉注射'
|
||
} else if (medicine.medicineName && medicine.medicineName.includes('片')) {
|
||
usageCode = '1'
|
||
usageLabel = '口服'
|
||
} else if (medicine.medicineName && medicine.medicineName.includes('胶囊')) {
|
||
usageCode = '1'
|
||
usageLabel = '口服'
|
||
}
|
||
|
||
return {
|
||
id: index + 1,
|
||
adviceName: medicine.medicineName || '',
|
||
dosage: dosage,
|
||
unit: specUnit,
|
||
usage: usageCode, // 🔧 修复:使用后端字典的正确编码
|
||
usageLabel: usageLabel, // 🔧 新增:保存显示名称
|
||
frequency: '临时',
|
||
executeTime: new Date().toLocaleString('zh-CN'),
|
||
originalMedicine: medicine
|
||
}
|
||
})
|
||
})
|
||
|
||
// 🔧 修复:使用 ref 而不是 computed,避免响应性问题
|
||
// 直接引用父组件传入的数据,确保更新能立即反映
|
||
const displayAdvices = ref([])
|
||
|
||
// 初始化 displayAdvices
|
||
const initDisplayAdvices = () => {
|
||
// 只要有用户修改过的数据,就优先使用用户修改后的数据
|
||
// 避免自动转换覆盖用户的修改
|
||
if (props.temporaryAdvices && props.temporaryAdvices.length > 0) {
|
||
// 🔧 修复:将旧编码映射到新编码
|
||
displayAdvices.value = props.temporaryAdvices.map(mapUsageCode)
|
||
} else {
|
||
// 否则自动转换第一区域的已引用计费药品
|
||
displayAdvices.value = convertedAdvices.value
|
||
}
|
||
}
|
||
|
||
// 初始化
|
||
initDisplayAdvices()
|
||
|
||
// 组件挂载时,如果没有传入临时医嘱数据,将自动转换后的数据同步到父组件
|
||
// 确保修改可以被父组件保存,下次打开仍然能看到
|
||
onMounted(() => {
|
||
|
||
|
||
// 初始化 displayAdvices
|
||
initDisplayAdvices()
|
||
|
||
if ((!props.temporaryAdvices || props.temporaryAdvices.length === 0) && convertedAdvices.value.length > 0) {
|
||
console.log('=== onMounted 触发 emit ===')
|
||
emit('update:temporary-advices', convertedAdvices.value)
|
||
}
|
||
})
|
||
|
||
// 🔧 新增:监听 temporary-advices prop 的变化,同步更新 displayAdvices
|
||
watch(() => props.temporaryAdvices, (newVal, oldVal) => {
|
||
console.log('=== watch props.temporaryAdvices 被调用 ===')
|
||
console.log('=== newVal ===', newVal)
|
||
|
||
// 如果 props 有新数据,更新 displayAdvices
|
||
if (newVal && newVal.length > 0) {
|
||
// 🔧 修复:将旧编码映射到新编码
|
||
displayAdvices.value = newVal.map(mapUsageCode)
|
||
}
|
||
}, { deep: true, immediate: true })
|
||
|
||
// 监听第一区域的计费药品变化,如果第一区域更新了,并且用户还没修改过第二区域数据,自动更新第二区域
|
||
watch(() => props.billingMedicines, (newVal) => {
|
||
console.log('=== watch billingMedicines 被调用 ===')
|
||
console.log('=== newVal ===', newVal)
|
||
console.log('=== props.temporaryAdvices ===', props.temporaryAdvices)
|
||
console.log('=== props.temporaryAdvices.length ===', props.temporaryAdvices?.length)
|
||
|
||
// 🔧 修复:只有当 temporary-advices 为空时才自动更新,避免覆盖用户的修改
|
||
if (!props.temporaryAdvices || props.temporaryAdvices.length === 0) {
|
||
if (newVal.length > 0) {
|
||
console.log('=== watch 触发 emit ===')
|
||
displayAdvices.value = convertedAdvices.value
|
||
emit('update:temporary-advices', convertedAdvices.value)
|
||
}
|
||
} else {
|
||
console.log('=== watch 不触发 emit,因为 props.temporaryAdvices 已有数据 ===')
|
||
}
|
||
}, { deep: true })
|
||
|
||
// 🔧 新增:监听字典加载,确保字典加载后编辑弹窗能正确显示
|
||
watch(() => method_code.value, (newVal) => {
|
||
console.log('=== watch method_code 被调用 ===')
|
||
console.log('字典数据已更新,长度:', newVal?.length || 0)
|
||
}, { immediate: true })
|
||
|
||
// 方法
|
||
const handleSign = () => {
|
||
showSignDialog.value = true
|
||
}
|
||
|
||
// 编辑医嘱
|
||
const handleEditAdvice = (index) => {
|
||
const advice = displayAdvices.value[index]
|
||
|
||
// 🔧 修复:如果用法是旧编码,映射到新编码
|
||
let usageCode = advice.usage
|
||
if (usageCodeMapping[usageCode]) {
|
||
usageCode = usageCodeMapping[usageCode]
|
||
}
|
||
|
||
currentEditIndex.value = index
|
||
editForm.value = {
|
||
adviceName: advice.adviceName,
|
||
dosage: advice.dosage,
|
||
unit: advice.unit,
|
||
usage: usageCode, // 使用映射后的正确编码
|
||
frequency: advice.frequency
|
||
}
|
||
showEditDialog.value = true
|
||
}
|
||
|
||
// 保存编辑
|
||
const handleSaveEdit = () => {
|
||
if (!editForm.value.dosage && editForm.value.dosage !== 0) {
|
||
ElMessage.warning('请填写剂量')
|
||
return
|
||
}
|
||
// 🔧 新增:验证剂量必须为数字
|
||
if (isNaN(editForm.value.dosage) || editForm.value.dosage === '') {
|
||
ElMessage.warning('剂量必须为数字')
|
||
return
|
||
}
|
||
if (!editForm.value.usage) {
|
||
ElMessage.warning('请填写用法')
|
||
return
|
||
}
|
||
|
||
console.log('=== 保存编辑 ===')
|
||
console.log('editForm.value.usage:', editForm.value.usage)
|
||
console.log('editForm.value.usage 类型:', typeof editForm.value.usage)
|
||
|
||
// 构建更新后的数据
|
||
const updatedAdvice = {
|
||
...displayAdvices.value[currentEditIndex.value],
|
||
...editForm.value
|
||
}
|
||
|
||
// 🔧 修复:确保 usage 字段保存的是编码,而不是中文名称
|
||
// 如果用户选择的是编码,直接使用;如果用户选择的是中文名称,需要转换为编码
|
||
if (editForm.value.usage && typeof editForm.value.usage === 'string') {
|
||
// 检查是否是编码(通常编码较短,如 'iv', 'po')
|
||
const isCode = editForm.value.usage.length <= 10 && getMethodCodeDict.value.some(item => item.value === editForm.value.usage)
|
||
if (!isCode) {
|
||
// 如果是中文名称,转换为编码
|
||
const dictItem = getMethodCodeDict.value.find(item => item.label === editForm.value.usage)
|
||
if (dictItem) {
|
||
updatedAdvice.usage = dictItem.value
|
||
updatedAdvice.usageLabel = dictItem.label
|
||
}
|
||
} else {
|
||
// 如果是编码,从字典中获取对应的标签
|
||
const dictItem = getMethodCodeDict.value.find(item => item.value === editForm.value.usage)
|
||
if (dictItem) {
|
||
updatedAdvice.usageLabel = dictItem.label
|
||
}
|
||
}
|
||
}
|
||
|
||
// 🔧 新增:同时更新 originalMedicine 中的数据,确保提交时使用最新的用户修改
|
||
const originalMedicine = displayAdvices.value[currentEditIndex.value].originalMedicine
|
||
if (originalMedicine && originalMedicine.contentJson) {
|
||
try {
|
||
const contentData = JSON.parse(originalMedicine.contentJson)
|
||
// 更新用户修改的字段
|
||
contentData.dose = editForm.value.dosage
|
||
contentData.doseUnitCode = editForm.value.unit
|
||
contentData.methodCode = updatedAdvice.usage
|
||
|
||
// 如果用户修改了剂量,重新计算数量
|
||
if (originalMedicine.specification) {
|
||
const specMatch = originalMedicine.specification.match(/(\d+)(\D+)/)
|
||
const specValue = specMatch ? parseInt(specMatch[1]) : 1
|
||
if (specValue > 0) {
|
||
const newQuantity = editForm.value.dosage / specValue
|
||
contentData.quantity = newQuantity
|
||
contentData.totalPrice = contentData.unitPrice * newQuantity
|
||
|
||
// 🔧 关键修复:同时更新显示字段,确保表格正确显示修改后的值
|
||
updatedAdvice.quantity = newQuantity
|
||
}
|
||
}
|
||
|
||
// 更新 contentJson
|
||
updatedAdvice.originalMedicine = {
|
||
...originalMedicine,
|
||
contentJson: JSON.stringify(contentData)
|
||
}
|
||
} catch (e) {
|
||
console.error('解析 originalMedicine.contentJson 失败', e)
|
||
}
|
||
}
|
||
|
||
// 构建完整的更新后列表
|
||
const updatedAdvices = [...displayAdvices.value]
|
||
updatedAdvices[currentEditIndex.value] = updatedAdvice
|
||
|
||
// 通知父组件更新数据
|
||
emit('update:temporary-advices', updatedAdvices)
|
||
|
||
showEditDialog.value = false
|
||
ElMessage.success('编辑成功(已暂存本地,请点击"一键签名并生成医嘱"按钮提交到服务器)')
|
||
}
|
||
|
||
// 取消编辑
|
||
const handleCancelEdit = () => {
|
||
showEditDialog.value = false
|
||
currentEditIndex.value = -1
|
||
editForm.value = {
|
||
adviceName: '',
|
||
dosage: '',
|
||
unit: '',
|
||
usage: '',
|
||
frequency: '临时'
|
||
}
|
||
}
|
||
|
||
const confirmSign = async () => {
|
||
if (!signPassword.value) {
|
||
ElMessage.warning('请输入密码')
|
||
return
|
||
}
|
||
|
||
// 调用后端接口验证密码
|
||
try {
|
||
const response = await checkPassword({
|
||
password: signPassword.value
|
||
})
|
||
|
||
if (response.code === 200 && response.data) {
|
||
isSigned.value = true
|
||
signatureTime.value = new Date().toLocaleString('zh-CN')
|
||
showSignDialog.value = false
|
||
signPassword.value = ''
|
||
ElMessage.success('签名成功')
|
||
|
||
// 签名成功后自动提交,用 setTimeout 确保响应式状态更新完成
|
||
setTimeout(() => {
|
||
handleSubmit()
|
||
}, 100)
|
||
} else {
|
||
// 🔧 修改:当密码验证失败时,显示更清晰的错误提示
|
||
signPassword.value = ''
|
||
}
|
||
} catch (error) {
|
||
}
|
||
}
|
||
|
||
const handleSignAndSubmit = () => {
|
||
if (isSigned.value) {
|
||
// 如果已经签名,直接提交
|
||
handleSubmit()
|
||
} else {
|
||
// 如果未签名,打开签名弹窗
|
||
handleSign()
|
||
}
|
||
}
|
||
|
||
const handleDeleteAdvice = (index) => {
|
||
ElMessageBox.confirm('确定要删除这条医嘱吗?', '提示', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning'
|
||
}).then(() => {
|
||
// 构建新的临时医嘱数据
|
||
const updatedAdvices = [...displayAdvices.value]
|
||
updatedAdvices.splice(index, 1)
|
||
|
||
// 通知父组件更新数据
|
||
emit('update:temporary-advices', updatedAdvices)
|
||
|
||
ElMessage.success('删除成功')
|
||
}).catch(() => {
|
||
// 用户取消删除
|
||
})
|
||
}
|
||
|
||
// 🔧 防重复提交标志位
|
||
const isSubmitting = ref(false)
|
||
|
||
const handleSubmit = async () => {
|
||
if (!isSigned.value) {
|
||
ElMessage.warning('请先进行电子签名')
|
||
return
|
||
}
|
||
|
||
// 🔧 防重复提交:如果正在提交,直接返回
|
||
if (isSubmitting.value) {
|
||
ElMessage.warning('正在提交医嘱,请稍候...')
|
||
return
|
||
}
|
||
|
||
// 检查是否有医嘱数据
|
||
if (displayAdvices.value.length === 0) {
|
||
ElMessage.warning('没有可保存的医嘱数据')
|
||
return
|
||
}
|
||
|
||
// 🔧 设置提交标志位
|
||
isSubmitting.value = true
|
||
|
||
try {
|
||
// 构建保存医嘱的请求参数
|
||
const saveData = {
|
||
organizationId: props.patientInfo.orgId || props.patientInfo.organizationId || 1, // 使用计费时的orgId
|
||
adviceSaveList: displayAdvices.value.map((advice, index) => {
|
||
// 获取原始药品数据
|
||
const originalMedicine = advice.originalMedicine
|
||
|
||
// 解析contentJson
|
||
let contentJsonData = {}
|
||
if (originalMedicine && originalMedicine.contentJson) {
|
||
try {
|
||
contentJsonData = JSON.parse(originalMedicine.contentJson)
|
||
} catch (e) {
|
||
// 解析失败,继续使用originalMedicine中的数据
|
||
}
|
||
}
|
||
|
||
// 根据修改后的剂量重新计算数量和总价
|
||
let quantity = originalMedicine?.quantity || 1;
|
||
const unitPrice = originalMedicine?.unitPrice || contentJsonData.unitPrice || 0;
|
||
// 如果用户修改了剂量,重新计算数量 = 剂量 / 规格数值
|
||
if (advice.dosage !== undefined && originalMedicine?.specification) {
|
||
const specMatch = originalMedicine.specification.match(/(\d+)(\D+)/);
|
||
const specValue = specMatch ? parseInt(specMatch[1]) : 1;
|
||
if (specValue > 0) {
|
||
quantity = advice.dosage / specValue;
|
||
}
|
||
}
|
||
const totalPrice = unitPrice * quantity;
|
||
|
||
// ✅ 关键修复:把修改后的数据更新到contentJson中,后端会优先读取这里的值
|
||
contentJsonData.adviceName = advice.adviceName;
|
||
contentJsonData.quantity = quantity;
|
||
contentJsonData.volume = advice.dosage + (advice.unit || '');
|
||
contentJsonData.totalPrice = totalPrice;
|
||
contentJsonData.unitPrice = unitPrice;
|
||
// 用法、剂量、单位也更新到contentJson
|
||
// 🔧 修复:确保 methodCode 使用的是编码,而不是中文名称
|
||
let methodCode = advice.usage;
|
||
if (methodCode && typeof methodCode === 'string') {
|
||
// 检查是否是编码(通常编码较短,如 'iv', 'po')
|
||
const isCode = methodCode.length <= 10 && getMethodCodeDict.value.some(item => item.value === methodCode)
|
||
if (!isCode) {
|
||
// 如果是中文名称,转换为编码
|
||
const dictItem = getMethodCodeDict.value.find(item => item.label === methodCode)
|
||
if (dictItem) {
|
||
methodCode = dictItem.value
|
||
}
|
||
}
|
||
}
|
||
contentJsonData.methodCode = methodCode;
|
||
contentJsonData.dose = advice.dosage;
|
||
contentJsonData.doseUnitCode = advice.unit;
|
||
contentJsonData.rateCode = advice.frequency;
|
||
|
||
// 重新序列化contentJson
|
||
const updatedContentJson = JSON.stringify(contentJsonData);
|
||
|
||
// 构造请求参数(与门诊医生工作站完全一致)
|
||
return {
|
||
// 基础信息
|
||
// 🔧 修复:dbOpType 的判断逻辑 - 如果有 requestId 则为修改,否则为新增
|
||
// 但对于从计费药品转换来的数据,即使没有 requestId,也应该先更新 chargeItemId
|
||
dbOpType: originalMedicine?.requestId ? '2' : (originalMedicine?.chargeItemId ? '2' : '1'),
|
||
adviceType: originalMedicine?.adviceType || 1, // 使用原始类型或默认1
|
||
requestId: originalMedicine?.requestId,
|
||
chargeItemId: originalMedicine?.chargeItemId,
|
||
contentJson: updatedContentJson,
|
||
categoryCode: contentJsonData.categoryCode || originalMedicine?.categoryCode,
|
||
pharmacologyCategoryCode: contentJsonData.pharmacologyCategoryCode || originalMedicine?.pharmacologyCategoryCode,
|
||
partPercent: originalMedicine?.partPercent || contentJsonData.partPercent || 1,
|
||
partAttributeEnum: originalMedicine?.partAttributeEnum || contentJsonData.partAttributeEnum,
|
||
executeNum: contentJsonData.executeNum || originalMedicine?.executeNum || 1,
|
||
prescriptionNo: originalMedicine?.prescriptionNo,
|
||
|
||
// 数量和单位:使用重新计算后的数量
|
||
quantity: quantity,
|
||
dispensePerDuration: originalMedicine?.dispensePerDuration || contentJsonData.dispensePerDuration,
|
||
unitCode: contentJsonData.unitCode || originalMedicine?.unitCode || advice.unit,
|
||
unitPrice: unitPrice,
|
||
// 总价根据新的数量重新计算
|
||
totalPrice: totalPrice,
|
||
definitionId: originalMedicine?.definitionId ? String(originalMedicine.definitionId) : contentJsonData.definitionId ? String(contentJsonData.definitionId) : advice.definitionId ? String(advice.definitionId) : null,
|
||
definitionDetailId: originalMedicine?.definitionDetailId ? String(originalMedicine.definitionDetailId) : contentJsonData.definitionDetailId ? String(contentJsonData.definitionDetailId) : advice.definitionDetailId ? String(advice.definitionDetailId) : null,
|
||
lotNumber: originalMedicine?.lotNumber || contentJsonData.lotNumber,
|
||
|
||
// 状态和类型
|
||
statusEnum: originalMedicine?.statusEnum || 2, // 默认状态:已发送
|
||
categoryEnum: originalMedicine?.categoryEnum || contentJsonData.categoryEnum || 1,
|
||
|
||
// 药品/诊疗信息 - 🔧 修复:优先使用originalMedicine中的adviceDefinitionId和adviceTableName
|
||
// 🔧 关键修复:确保adviceDefinitionId不为null,使用definitionId作为后备
|
||
adviceDefinitionId: originalMedicine?.adviceDefinitionId || contentJsonData.adviceDefinitionId || advice.definitionId || contentJsonData.definitionId || definitionId,
|
||
adviceTableName: originalMedicine?.adviceTableName || contentJsonData.adviceTableName || 'med_medication_definition',
|
||
adviceName: advice.adviceName,
|
||
minUnitQuantity: originalMedicine?.minUnitQuantity || contentJsonData.minUnitQuantity,
|
||
|
||
// 患者和就诊信息
|
||
patientId: props.patientInfo.patientId,
|
||
practitionerId: currentUser.value.id || originalMedicine?.practitionerId, // 开方医生
|
||
locationId: originalMedicine?.positionId || contentJsonData.locationId || props.patientInfo.orgId || props.patientInfo.positionId,
|
||
positionId: originalMedicine?.positionId || contentJsonData.positionId,
|
||
orgId: originalMedicine?.orgId || props.patientInfo.orgId || props.patientInfo.positionId,
|
||
performLocation: originalMedicine?.performLocation || contentJsonData.performLocation,
|
||
founderOrgId: currentUser.value.id || originalMedicine?.founderOrgId, // 开方人科室
|
||
encounterId: props.patientInfo.visitId || contentJsonData.encounterId || originalMedicine?.encounterId,
|
||
accountId: contentJsonData.accountId || originalMedicine?.accountId,
|
||
conditionId: contentJsonData.conditionId || originalMedicine?.conditionId,
|
||
encounterDiagnosisId: originalMedicine?.encounterDiagnosisId || contentJsonData.encounterDiagnosisId,
|
||
conditionDefinitionId: originalMedicine?.conditionDefinitionId || contentJsonData.conditionDefinitionId,
|
||
|
||
// 治疗信息
|
||
therapyEnum: originalMedicine?.therapyEnum || contentJsonData.therapyEnum || 1, // 默认临时医嘱
|
||
// 🔧 修复:methodCode 使用编码,而不是中文名称
|
||
methodCode: methodCode, // 用法(使用编码)
|
||
rateCode: advice.frequency, // 频次
|
||
dose: advice.dosage,
|
||
firstDose: originalMedicine?.firstDose || contentJsonData.firstDose,
|
||
doseUnitCode: contentJsonData.doseUnitCode || originalMedicine?.doseUnitCode || advice.unit,
|
||
skinTestFlag: originalMedicine?.skinTestFlag || contentJsonData.skinTestFlag,
|
||
injectFlag: originalMedicine?.injectFlag || contentJsonData.injectFlag,
|
||
|
||
// 分组信息
|
||
groupId: originalMedicine?.groupId,
|
||
packageId: originalMedicine?.packageId || contentJsonData.packageId,
|
||
|
||
// 诊疗活动信息
|
||
activityId: contentJsonData.adviceDefinitionId || originalMedicine?.adviceDefinitionId, // 对于诊疗类型,使用 adviceDefinitionId 作为 activity_id
|
||
|
||
// 医保信息
|
||
ybClassEnum: originalMedicine?.ybClassEnum || contentJsonData.ybClassEnum,
|
||
|
||
// 中药信息
|
||
chineseHerbsDoseQuantity: originalMedicine?.chineseHerbsDoseQuantity || contentJsonData.chineseHerbsDoseQuantity || 1
|
||
}
|
||
})
|
||
}
|
||
|
||
// 调用保存医嘱接口
|
||
// 如果已签名,则执行签发操作('1'),否则执行保存操作('0')
|
||
const adviceOpType = isSigned.value ? '1' : '0'
|
||
const response = await savePrescription(saveData, adviceOpType)
|
||
|
||
if (response.code === 200) {
|
||
ElMessage.success('临时医嘱保存成功')
|
||
|
||
// 🔧 关键修复:处理后端返回的医嘱 ID
|
||
// 后端返回的 data 数组只包含新创建的医嘱记录的 ID,不包含已更新的记录
|
||
// 我们需要正确地映射这些 ID 到对应的临时医嘱数据
|
||
if (response.data && Array.isArray(response.data) && response.data.length > 0) {
|
||
// 创建一个索引,记录哪些记录是新创建的
|
||
let newDataIndex = 0
|
||
|
||
displayAdvices.value.forEach((advice, index) => {
|
||
const originalMedicine = advice.originalMedicine || {}
|
||
// 如果这个记录没有 requestId,说明是新创建的
|
||
if (!originalMedicine.requestId) {
|
||
if (newDataIndex < response.data.length) {
|
||
// 更新 originalMedicine 中的 requestId
|
||
if (!displayAdvices.value[index].originalMedicine) {
|
||
displayAdvices.value[index].originalMedicine = {}
|
||
}
|
||
displayAdvices.value[index].originalMedicine.requestId = response.data[newDataIndex]
|
||
newDataIndex++
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
// 🔧 修复:将保存后的医嘱数据(包含用户的修改和后端返回的 requestId)传递给父组件
|
||
// 这样父组件可以使用用户修改后的数据,而不是重新加载数据
|
||
const submitData = {
|
||
patientInfo: props.patientInfo,
|
||
billingMedicines: props.billingMedicines,
|
||
temporaryAdvices: displayAdvices.value, // 使用用户修改后的数据,包含后端返回的 requestId
|
||
signature: {
|
||
doctorName: currentUser.value.name,
|
||
signatureTime: signatureTime.value
|
||
}
|
||
}
|
||
|
||
// 通知父组件
|
||
emit('submit', submitData)
|
||
} else {
|
||
ElMessage.error('保存医嘱失败:' + (response.msg || response.message || '未知错误'))
|
||
}
|
||
} catch (error) {
|
||
ElMessage.error('保存医嘱失败,请重试')
|
||
} finally {
|
||
// 🔧 重置防重复提交标志位
|
||
isSubmitting.value = false
|
||
}
|
||
}
|
||
|
||
const handleCancel = () => {
|
||
// 通知父组件关闭弹窗
|
||
emit('cancel')
|
||
}
|
||
|
||
// 刷新按钮点击
|
||
const handleRefresh = () => {
|
||
emit('refresh')
|
||
}
|
||
|
||
// 引用计费按钮点击
|
||
const handleQuoteBilling = () => {
|
||
emit('quote-billing')
|
||
}
|
||
|
||
// 数量改变时重新计算小计
|
||
const handleQuantityChange = () => {
|
||
// 数量变化会自动更新,因为是响应式
|
||
}
|
||
|
||
// 获取医保标签样式类
|
||
const getInsuranceClass = (insuranceType) => {
|
||
if (!insuranceType) return ''
|
||
if (insuranceType === '甲' || insuranceType === '乙' || insuranceType === '医保') {
|
||
return 'insurance-tag'
|
||
}
|
||
if (insuranceType === '自费') {
|
||
return 'selfpay-tag'
|
||
}
|
||
return ''
|
||
}
|
||
|
||
// 🔧 新增:根据用法编码获取对应的显示名称
|
||
const getUsageLabel = (usageCode) => {
|
||
if (!usageCode) return '-'
|
||
const dictItem = getMethodCodeDict.value.find(item => item.value === usageCode)
|
||
return dictItem ? dictItem.label : usageCode
|
||
}
|
||
|
||
// 🔧 新增:获取编辑表单中当前选中的用法标签
|
||
const editFormUsageLabel = computed(() => {
|
||
if (!editForm.value.usage) return ''
|
||
return getUsageLabel(editForm.value.usage)
|
||
})
|
||
</script>
|
||
|
||
<style scoped>
|
||
.temporary-medical-container {
|
||
padding: 0;
|
||
max-height: 80vh;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
/* 顶部容器 */
|
||
.top-container {
|
||
height: 180px;
|
||
padding: 0 0 20px 0;
|
||
background: linear-gradient(135deg, #63A3E7 0%, #4a8bc9 100%);
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
/* 标题栏 */
|
||
.title-bar {
|
||
padding: 16px 20px;
|
||
text-align: center;
|
||
}
|
||
|
||
.title-text {
|
||
color: white;
|
||
font-size: 1.5rem;
|
||
font-weight: 600;
|
||
margin: 0;
|
||
line-height: 1.2;
|
||
}
|
||
|
||
/* 患者信息卡 */
|
||
.patient-info-card {
|
||
flex: 1;
|
||
margin: 0 20px 12px 20px;
|
||
padding: 16px 20px;
|
||
background: rgba(255, 255, 255, 0.9);
|
||
border-radius: 8px;
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 16px 40px;
|
||
align-items: center;
|
||
}
|
||
|
||
.info-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
|
||
.info-label {
|
||
font-weight: bold;
|
||
color: #333;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.info-value {
|
||
color: #333;
|
||
font-size: 14px;
|
||
}
|
||
|
||
/* 操作按钮组 */
|
||
.action-buttons {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
gap: 16px;
|
||
padding: 0 20px;
|
||
}
|
||
|
||
/* 刷新按钮 */
|
||
.refresh-btn {
|
||
background: linear-gradient(135deg, #63A3E7 0%, #4a8bc9 100%);
|
||
border-color: #63A3E7;
|
||
color: white;
|
||
font-size: 14px;
|
||
padding: 8px 20px;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.refresh-btn:hover {
|
||
background: linear-gradient(135deg, #5391d1 0%, #3a7bb5 100%);
|
||
border-color: #5391d1;
|
||
color: white;
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 4px 8px rgba(99, 163, 231, 0.4);
|
||
}
|
||
|
||
/* 引用计费按钮 */
|
||
.quote-btn {
|
||
background: rgba(255, 255, 255, 0.9);
|
||
border-color: #63A3E7;
|
||
color: #63A3E7;
|
||
font-size: 14px;
|
||
padding: 8px 20px;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.quote-btn:hover {
|
||
background: rgba(255, 255, 255, 1);
|
||
border-color: #5391d1;
|
||
color: #5391d1;
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 4px 8px rgba(99, 163, 231, 0.3);
|
||
}
|
||
|
||
.medicine-section,
|
||
.advice-section,
|
||
.signature-section {
|
||
margin: 24px 20px 30px 20px;
|
||
}
|
||
|
||
/* 区域标题 */
|
||
.section-title {
|
||
font-size: 1.2rem;
|
||
color: #333;
|
||
font-weight: 600;
|
||
padding-bottom: 12px;
|
||
margin-bottom: 16px;
|
||
border-bottom: 2px solid #e4e7ed;
|
||
}
|
||
|
||
.medicine-summary {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
gap: 30px;
|
||
padding: 16px;
|
||
background-color: #f5f7fa;
|
||
border-radius: 4px;
|
||
margin-top: 12px;
|
||
}
|
||
|
||
.summary-item {
|
||
font-size: 15px;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.summary-item.insurance {
|
||
color: #63A3E7;
|
||
}
|
||
|
||
.summary-item.self-pay {
|
||
color: #67c23a;
|
||
}
|
||
|
||
.summary-item.total {
|
||
font-weight: bold;
|
||
color: #f56c6c;
|
||
font-size: 16px;
|
||
}
|
||
|
||
/* 医保标签样式 */
|
||
:deep(.insurance-tag) {
|
||
background-color: #63A3E7;
|
||
color: white;
|
||
}
|
||
|
||
:deep(.selfpay-tag) {
|
||
background-color: #67c23a;
|
||
color: white;
|
||
}
|
||
|
||
/* 计费药品表格表头浅灰色背景 */
|
||
.medicine-section :deep(.el-table th) {
|
||
background-color: #f5f7fa !important;
|
||
color: #333 !important;
|
||
}
|
||
|
||
.medicine-section :deep(.el-table th.el-table__cell > .cell) {
|
||
color: #333 !important;
|
||
font-weight: 600;
|
||
}
|
||
|
||
/* 临时医嘱表格表头浅灰色背景(与计费药品表格保持一致) */
|
||
.advice-section :deep(.el-table th) {
|
||
background-color: #f5f7fa !important;
|
||
color: #333 !important;
|
||
}
|
||
|
||
.advice-section :deep(.el-table th.el-table__cell > .cell) {
|
||
color: #333 !important;
|
||
font-weight: 600;
|
||
}
|
||
|
||
/* 签名信息卡 */
|
||
.signature-card {
|
||
padding: 20px;
|
||
background-color: #f5f7fa;
|
||
border-radius: 8px;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.signature-info {
|
||
margin-bottom: 16px;
|
||
font-size: 15px;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.signature-info:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.signature-info .info-label {
|
||
font-weight: bold;
|
||
color: #333;
|
||
width: 100px;
|
||
}
|
||
|
||
.signature-info .info-value {
|
||
color: #333;
|
||
}
|
||
|
||
.unsigned {
|
||
color: #f56c6c;
|
||
font-weight: 500;
|
||
}
|
||
|
||
/* 签名操作按钮区 */
|
||
.signature-actions {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
gap: 30px;
|
||
}
|
||
|
||
.cancel-btn {
|
||
width: 140px;
|
||
height: 48px;
|
||
font-size: 16px;
|
||
border: 1px solid #dcdfe6;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.cancel-btn:hover {
|
||
border-color: #409eff;
|
||
color: #409eff;
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 4px 8px rgba(64, 158, 255, 0.2);
|
||
}
|
||
|
||
/* 一键签名按钮 */
|
||
.sign-btn {
|
||
width: 220px;
|
||
height: 48px;
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
background: linear-gradient(135deg, #67c23a 0%, #85ce61 100%);
|
||
border: none;
|
||
color: white;
|
||
transition: all 0.3s ease;
|
||
box-shadow: 0 4px 8px rgba(103, 194, 58, 0.3);
|
||
}
|
||
|
||
.sign-btn:hover {
|
||
transform: translateY(-3px);
|
||
box-shadow: 0 6px 12px rgba(103, 194, 58, 0.4);
|
||
}
|
||
|
||
.sign-btn:active {
|
||
transform: translateY(-1px);
|
||
box-shadow: 0 2px 4px rgba(103, 194, 58, 0.4);
|
||
}
|
||
|
||
.sign-dialog-content p {
|
||
margin-bottom: 16px;
|
||
color: #666;
|
||
}
|
||
|
||
.dialog-actions {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
gap: 12px;
|
||
}
|
||
|
||
:deep(.el-descriptions) {
|
||
margin-top: 8px;
|
||
}
|
||
|
||
:deep(.el-descriptions__label) {
|
||
font-weight: bold;
|
||
}
|
||
</style> |