Files
his/openhis-ui-vue3/src/views/charge/outpatientregistration/components/reprintDialog.vue

932 lines
27 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>
<el-dialog
title="补打挂号单凭证"
v-model="dialogVisible"
width="900px"
append-to-body
destroy-on-close
:close-on-click-modal="false"
>
<div v-loading="loading" style="background-color: #ffffff; padding: 20px; min-height: 400px;">
<!-- 标题区域 -->
<div style="text-align: center; margin-bottom: 20px;">
<h2 style="color: #ff0000; font-size: 24px; font-weight: bold; margin: 0 0 10px 0;">挂号单重打</h2>
<p style="color: #ff0000; font-size: 14px; margin: 0;">补打挂号单将作废原有的挂号单据并生成新的挂号单据</p>
</div>
<!-- 表单区域 -->
<el-form :model="form" ref="reprintFormRef" label-width="120px" style="background-color: #ffffff; padding: 20px; border-radius: 4px;">
<el-row :gutter="30">
<!-- 左列 -->
<el-col :span="12">
<el-form-item label="病人姓名:" prop="name">
<el-input v-model="form.name" placeholder="病人姓名" :disabled="true" />
</el-form-item>
<el-form-item label="医生姓名:" prop="practitionerName">
<el-input v-model="form.practitionerName" placeholder="医生姓名" :disabled="true" />
</el-form-item>
<el-form-item label="诊疗费:" prop="activityPrice">
<el-input v-model="form.activityPrice" placeholder="诊疗费" :disabled="true" />
</el-form-item>
<el-form-item label="流水号:" prop="serialNo">
<el-input v-model="form.serialNo" placeholder="流水号" :disabled="true" />
</el-form-item>
<el-form-item label="合计:" prop="totalPrice">
<el-input v-model="form.totalPrice" placeholder="合计" :disabled="true" />
</el-form-item>
</el-col>
<!-- 右列 -->
<el-col :span="12">
<el-form-item label="挂号科室:" prop="organizationName">
<el-input v-model="form.organizationName" placeholder="挂号科室" :disabled="true" />
</el-form-item>
<el-form-item label="挂号费:" prop="price">
<el-input v-model="form.price" placeholder="挂号费" :disabled="true" />
</el-form-item>
<el-form-item label="病历费:" prop="medicalRecordFee">
<el-input v-model="form.medicalRecordFee" placeholder="病历费" :disabled="true" />
</el-form-item>
<el-form-item label="打印时间:" prop="printTime">
<el-input v-model="form.printTime" placeholder="打印时间" :disabled="true" />
</el-form-item>
</el-col>
</el-row>
<!-- 跨两列的字段 -->
<el-row>
<el-col :span="24">
<el-form-item label="预约/挂号时间:" prop="visitTime">
<el-input v-model="form.visitTime" placeholder="预约/挂号时间" :disabled="true" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<!-- 底部搜索和操作区域 -->
<div style="margin-top: 20px; padding: 15px; background-color: #ffffff; border-radius: 4px;">
<el-form :inline="true" style="margin: 0;">
<el-form-item label="就诊卡号:" style="margin-bottom: 0;">
<el-input
v-model="searchForm.cardNo"
placeholder="请输入就诊卡号检索条"
style="width: 300px; margin-right: 10px;"
clearable
@keyup.enter="handleSearch"
/>
<el-button type="primary" @click="handleSearch" :loading="loading">确认(O)</el-button>
<el-button @click="handleCancel">取消(C)</el-button>
</el-form-item>
</el-form>
</div>
</div>
<!-- 挂号记录选择对话框 -->
<el-dialog
title="挂号记录选择"
v-model="selectDialogVisible"
width="800px"
append-to-body
:close-on-click-modal="false"
>
<el-table
:data="recordList"
highlight-current-row
@current-change="handleRecordSelect"
style="width: 100%"
max-height="400"
>
<el-table-column label="序号" type="index" width="60" align="center" />
<el-table-column label="挂号时间" prop="registerTime" width="180" align="center">
<template #default="scope">
{{ scope.row.registerTime ? parseTime(scope.row.registerTime, '{y}.{m}.{d} {h}时{i}分') : '-' }}
</template>
</el-table-column>
<el-table-column label="挂号科室" prop="organizationName" align="center" />
<el-table-column label="医生姓名" prop="practitionerName" align="center" />
<el-table-column label="流水号" prop="encounterNo" align="center">
<template #default="scope">
{{ scope.row.encounterNo || scope.row.visitNo || scope.row.serialNo || '-' }}
</template>
</el-table-column>
</el-table>
<template #footer>
<div class="dialog-footer">
<el-button @click="selectDialogVisible = false">取消(C)</el-button>
<el-button type="primary" @click="handleConfirmSelect" :disabled="!selectedRecord">确认(O)</el-button>
</div>
</template>
</el-dialog>
<!-- 打印预览对话框 -->
<el-dialog
title="打印预览"
v-model="printPreviewVisible"
width="600px"
append-to-body
:close-on-click-modal="false"
class="print-preview-dialog"
>
<div id="print-content" class="print-content">
<!-- 打印内容 -->
<div class="print-header">
<div class="reprint-label-left">补打</div>
<div class="header-content">
<div class="document-title">门诊预约挂号凭条</div>
<div class="print-time">打印时间: {{ form.printTime }}</div>
</div>
</div>
<div class="print-section">
<div class="section-title">患者基本信息</div>
<div class="info-row">
<span class="label">患者姓名:</span>
<span class="value">{{ form.name || '-' }}</span>
</div>
<div class="info-row">
<span class="label">门诊号:</span>
<span class="value">{{ form.serialNo || '-' }}</span>
</div>
<div class="info-row">
<span class="label">就诊卡号:</span>
<span class="value">{{ form.cardNo || '-' }}</span>
</div>
<div class="info-row">
<span class="label">身份证号:</span>
<span class="value">{{ form.idCard || '-' }}</span>
</div>
<div class="info-row">
<span class="label">联系电话:</span>
<span class="value">{{ form.phone || '-' }}</span>
</div>
</div>
<div class="print-section">
<div class="section-title">预约详情</div>
<div class="info-row">
<span class="label">就诊科室:</span>
<span class="value">{{ form.organizationName || '-' }}</span>
</div>
<div class="info-row">
<span class="label">医生姓名:</span>
<span class="value">{{ form.practitionerName || '-' }}</span>
</div>
<div class="info-row">
<span class="label">预约时间:</span>
<span class="value">{{ form.visitTime || '-' }}</span>
</div>
<div class="info-row">
<span class="label">就诊地点:</span>
<span class="value">{{ form.visitLocation || '-' }}</span>
</div>
<div class="info-row">
<span class="label">预约状态:</span>
<span class="value">{{ form.statusText || '-' }}</span>
</div>
</div>
<div class="print-section">
<div class="section-title">费用信息</div>
<table class="fee-table">
<thead>
<tr>
<th>项目</th>
<th>数量</th>
<th>单价</th>
<th>金额</th>
</tr>
</thead>
<tbody>
<tr>
<td>挂号费</td>
<td>1</td>
<td>¥{{ parseFloat(form.price || 0).toFixed(2) }}</td>
<td>¥{{ parseFloat(form.price || 0).toFixed(2) }}</td>
</tr>
<tr v-if="parseFloat(form.activityPrice || 0) > 0">
<td>诊疗费</td>
<td>1</td>
<td>¥{{ parseFloat(form.activityPrice || 0).toFixed(2) }}</td>
<td>¥{{ parseFloat(form.activityPrice || 0).toFixed(2) }}</td>
</tr>
<tr v-if="parseFloat(form.medicalRecordFee || 0) > 0">
<td>病历费</td>
<td>1</td>
<td>¥{{ parseFloat(form.medicalRecordFee || 0).toFixed(2) }}</td>
<td>¥{{ parseFloat(form.medicalRecordFee || 0).toFixed(2) }}</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="3" class="total-label">合计:</td>
<td class="total-value">¥{{ parseFloat(form.totalPrice || 0).toFixed(2) }}</td>
</tr>
</tfoot>
</table>
</div>
<div class="print-footer">
<div class="reminder">温馨提示: 请妥善保管此凭条就诊时请携带</div>
</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="printPreviewVisible = false">关闭</el-button>
<el-button type="primary" @click="handleBrowserPrint">打印</el-button>
</div>
</template>
</el-dialog>
</el-dialog>
</template>
<script setup>
import {getCurrentInstance, reactive, ref, watch} from 'vue';
import {getOutpatientRegistrationCurrent, reprintRegistration} from './outpatientregistration';
import {parseTime} from '@/utils/his';
import {formatDateStr} from '@/utils/index';
const { proxy } = getCurrentInstance();
const props = defineProps({
open: {
type: Boolean,
default: false,
},
});
const emit = defineEmits(['close']);
const dialogVisible = ref(false);
const loading = ref(false);
const reprintFormRef = ref(null);
const selectDialogVisible = ref(false);
const recordList = ref([]);
const selectedRecord = ref(null);
const currentRecord = ref(null); // 保存当前选择的记录,用于打印
const printPreviewVisible = ref(false); // 打印预览对话框显示状态
const searchForm = reactive({
cardNo: '',
});
const form = reactive({
cardNo: '',
name: '',
idCard: '',
phone: '',
organizationName: '',
practitionerName: '',
price: '',
activityPrice: '',
medicalRecordFee: '',
serialNo: '',
totalPrice: '',
visitTime: '',
visitLocation: '',
statusText: '',
printTime: '',
encounterId: '',
});
const rules = {
cardNo: [{ required: true, message: '就诊卡号不能为空', trigger: 'blur' }],
name: [{ required: true, message: '姓名不能为空', trigger: 'blur' }],
organizationName: [{ required: true, message: '就诊科室不能为空', trigger: 'blur' }],
practitionerName: [{ required: true, message: '医生不能为空', trigger: 'blur' }],
};
// 监听open属性变化
watch(
() => props.open,
(newVal) => {
dialogVisible.value = newVal;
if (newVal) {
// 打开对话框时重置表单
resetForm();
resetSearch();
}
}
);
// 监听dialogVisible变化同步到父组件
watch(dialogVisible, (newVal) => {
if (!newVal) {
emit('close');
}
});
// 搜索挂号记录并确认补打
async function handleSearch() {
if (!searchForm.cardNo) {
proxy.$modal.msgWarning('请输入就诊卡号');
return;
}
loading.value = true;
try {
// 使用就诊卡号作为searchKey查询
const endDate = new Date();
const startDate = new Date();
startDate.setFullYear(startDate.getFullYear() - 1);
const queryParams = {
pageNo: 1,
pageSize: 100,
registerTimeSTime: formatDateStr(startDate, 'YYYY-MM-DD') + ' 00:00:00',
registerTimeETime: formatDateStr(endDate, 'YYYY-MM-DD') + ' 23:59:59',
searchKey: searchForm.cardNo
};
// 调用API查询挂号记录
const response = await getOutpatientRegistrationCurrent(queryParams);
if (response.code === 200) {
let records = response.data.records || response.data || [];
if (records.length > 0) {
if (records.length === 1) {
// 只有一条记录,直接使用
const row = records[0];
currentRecord.value = row; // 保存记录用于打印
fillForm(row);
await handleSubmit();
} else {
// 多条记录,显示选择对话框
recordList.value = records;
selectedRecord.value = records[0]; // 默认选择第一条
selectDialogVisible.value = true;
loading.value = false;
}
} else {
proxy.$modal.msgWarning('未查询到相关挂号记录,请检查就诊卡号是否正确');
resetForm();
loading.value = false;
}
} else {
proxy.$modal.msgWarning('查询失败: ' + (response.msg || '接口返回异常'));
resetForm();
loading.value = false;
}
} catch (error) {
console.error('查询挂号记录异常:', error);
proxy.$modal.msgError('查询出错: ' + (error.message || '网络异常'));
resetForm();
loading.value = false;
}
}
// 填充表单
function fillForm(row) {
console.log('fillForm row:', row); // 调试日志
// 就诊卡号 - 从 identifierNo 字段获取
form.cardNo = row.identifierNo || row.cardNo || '';
// 病人姓名 - 从 patientName 字段获取
form.name = row.patientName || row.name || '';
// 身份证号 - 从 idCard 字段获取,需要脱敏处理
let idCard = row.idCard || '';
if (idCard && idCard.length >= 10) {
// 只显示前6位和后4位中间用*代替
const prefix = idCard.substring(0, 6);
const suffix = idCard.substring(idCard.length - 4);
const stars = '*'.repeat(Math.max(0, idCard.length - 10));
form.idCard = prefix + stars + suffix;
} else if (idCard) {
// 如果身份证号长度不足10位只显示部分并用*代替
if (idCard.length >= 6) {
const prefix = idCard.substring(0, 3);
const suffix = idCard.substring(idCard.length - 1);
form.idCard = prefix + '*'.repeat(idCard.length - 4) + suffix;
} else {
form.idCard = idCard;
}
} else {
form.idCard = '';
}
// 联系电话 - 从 phone 字段获取,需要脱敏处理
let phone = row.phone || '';
if (phone && phone.length >= 7) {
// 只显示前3位和后4位中间用*代替
const prefix = phone.substring(0, 3);
const suffix = phone.substring(phone.length - 4);
form.phone = prefix + '****' + suffix;
} else if (phone) {
// 如果手机号长度不足7位部分脱敏
if (phone.length >= 4) {
const prefix = phone.substring(0, 2);
const suffix = phone.substring(phone.length - 2);
form.phone = prefix + '**' + suffix;
} else {
form.phone = phone;
}
} else {
form.phone = '';
}
// 挂号科室 - 从 organizationName 字段获取
form.organizationName = row.organizationName || '';
// 医生姓名 - 从 practitionerName 字段获取
form.practitionerName = row.practitionerName || '';
// 挂号费 - 如果没有单独的 price将 totalPrice 作为挂号费
// 实际系统中,可能需要查询更详细的费用明细
form.price = row.price ? parseFloat(row.price).toFixed(2) :
(row.totalPrice ? parseFloat(row.totalPrice).toFixed(2) : '0.00');
// 诊疗费 - API 未返回,暂时设为 0.00
form.activityPrice = row.activityPrice ? parseFloat(row.activityPrice).toFixed(2) : '0.00';
// 病历费 - API 未返回,暂时设为 0.00
form.medicalRecordFee = row.medicalRecordFee ? parseFloat(row.medicalRecordFee).toFixed(2) : '0.00';
// 流水号 - 使用 encounterId 的后3位如果为空则生成001-999的序列号
let serialNo = '';
if (row.encounterId) {
// 使用 encounterId 的后3位作为流水号
const idStr = String(row.encounterId);
const lastThree = idStr.slice(-3);
const num = parseInt(lastThree) || 0;
serialNo = String((num % 999) + 1).padStart(3, '0');
} else {
// 如果 encounterId 为空生成一个001-999的序列号
const timestamp = Date.now();
const serial = (timestamp % 999) + 1;
serialNo = String(serial).padStart(3, '0');
}
form.serialNo = serialNo;
// 合计 - 优先使用 totalPrice否则计算各项费用之和
if (row.totalPrice) {
form.totalPrice = parseFloat(row.totalPrice).toFixed(2);
} else {
const total = parseFloat(form.price || 0) + parseFloat(form.activityPrice || 0) + parseFloat(form.medicalRecordFee || 0);
form.totalPrice = total.toFixed(2);
}
// 预约/挂号时间 - 从 registerTime 字段获取
if (row.registerTime) {
form.visitTime = parseTime(row.registerTime, '{y}-{m}-{d} {h}:{i}:{s}');
} else {
form.visitTime = formatDateTime(new Date());
}
// 就诊地点 - 暂时设为空,后续可根据实际需求填充
form.visitLocation = row.visitLocation || row.locationName || '';
// 预约状态 - 从 statusEnum_enumText 字段获取,如果没有则根据 statusEnum 判断
if (row.statusEnum_enumText) {
form.statusText = row.statusEnum_enumText;
} else if (row.statusEnum !== undefined) {
// 根据 statusEnum 判断状态
// 状态枚举可能需要根据实际情况调整
const statusMap = {
1: '已预约',
2: '已完成',
3: '已取消',
4: '进行中'
};
form.statusText = statusMap[row.statusEnum] || '已预约';
} else {
form.statusText = '已预约';
}
// 打印时间(当前时间)
form.printTime = formatDateTime(new Date());
// 保存encounterId用于提交 - 注意字段名是 encounterId
form.encounterId = row.encounterId || row.id || '';
console.log('fillForm form:', form); // 调试日志
}
// 格式化日期时间
function formatDateTime(date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
// 提交补打挂号
async function handleSubmit() {
if (!form.encounterId) {
proxy.$modal.msgWarning('请先搜索并选择挂号记录');
loading.value = false;
return;
}
try {
// 如果 reprintFormRef 不存在,跳过验证
let valid = true;
if (reprintFormRef.value) {
valid = await reprintFormRef.value.validate().catch(() => false);
}
if (!valid) {
loading.value = false;
return;
}
// 在提交前,验证表单数据是否已正确填充
console.log('handleSubmit form before submit:', form); // 调试日志
const submitData = {
encounterId: form.encounterId,
cardNo: form.cardNo,
name: form.name,
organizationName: form.organizationName,
practitionerName: form.practitionerName,
price: parseFloat(form.price) || 0,
activityPrice: parseFloat(form.activityPrice) || 0,
medicalRecordFee: parseFloat(form.medicalRecordFee || 0),
totalPrice: parseFloat(form.totalPrice) || 0,
visitTime: form.visitTime,
};
console.log('handleSubmit submitData:', submitData); // 调试日志
const res = await reprintRegistration(submitData);
if (res.code === 200) {
proxy.$modal.msgSuccess('补打挂号成功');
// 不关闭补打对话框,直接显示打印预览
// 这样可以确保 form 数据不会丢失
loading.value = false;
showPrintPreview();
} else {
proxy.$modal.msgError(res.msg || '补打挂号失败');
loading.value = false;
}
} catch (error) {
console.error('补打挂号失败:', error);
proxy.$modal.msgError('补打挂号失败: ' + (error.message || '未知错误'));
loading.value = false;
}
}
// 取消(实际执行提交操作,因为确认按钮触发搜索)
function handleCancel() {
dialogVisible.value = false;
}
// 重置表单
function resetForm() {
Object.assign(form, {
cardNo: '',
name: '',
idCard: '',
phone: '',
organizationName: '',
practitionerName: '',
price: '',
activityPrice: '',
medicalRecordFee: '',
serialNo: '',
totalPrice: '',
visitTime: '',
visitLocation: '',
statusText: '',
printTime: '',
encounterId: '',
});
if (reprintFormRef.value) {
reprintFormRef.value.clearValidate();
}
}
// 重置搜索
function resetSearch() {
searchForm.cardNo = '';
}
// 显示打印预览
function showPrintPreview() {
// 直接使用浏览器打印预览,避免 hiprint 连接错误
// 因为 hiprint 需要本地服务运行,如果服务未运行会导致连接失败
// 确保 loading 已关闭
loading.value = false;
// 验证表单数据是否已正确填充
console.log('showPrintPreview form:', form); // 调试日志
console.log('showPrintPreview currentRecord:', currentRecord.value); // 调试日志
// 如果 form 的关键字段为空,尝试从 currentRecord 重新填充
if (!form.name && currentRecord.value) {
console.log('重新填充表单数据...');
fillForm(currentRecord.value);
}
// 显示打印预览对话框
printPreviewVisible.value = true;
}
// 浏览器打印
function handleBrowserPrint() {
const printContent = document.getElementById('print-content');
if (!printContent) {
proxy.$modal.msgError('打印内容不存在');
return;
}
// 创建新窗口用于打印
const printWindow = window.open('', '_blank');
if (!printWindow) {
proxy.$modal.msgError('无法打开打印窗口,请检查浏览器弹窗设置');
return;
}
// 写入打印内容
printWindow.document.write(`
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>门诊预约挂号凭条</title>
<style>
body {
font-family: Arial, sans-serif;
padding: 20px;
margin: 0;
}
.print-header {
margin-bottom: 20px;
position: relative;
}
.reprint-label-left {
position: absolute;
top: 0;
left: 0;
color: red;
font-size: 16px;
font-weight: bold;
}
.header-content {
text-align: center;
}
.document-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 10px;
}
.print-time {
font-size: 12px;
color: #666;
text-align: right;
}
.print-section {
margin-bottom: 20px;
}
.section-title {
font-size: 14px;
font-weight: bold;
margin-bottom: 10px;
border-bottom: 1px solid #ddd;
padding-bottom: 5px;
}
.info-row {
margin-bottom: 8px;
font-size: 13px;
}
.label {
display: inline-block;
width: 100px;
font-weight: bold;
}
.value {
display: inline-block;
}
.fee-table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}
.fee-table th,
.fee-table td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
.fee-table th {
background-color: #f5f5f5;
font-weight: bold;
}
.total-label {
font-weight: bold;
text-align: right;
}
.total-value {
font-weight: bold;
color: red;
}
.print-footer {
margin-top: 20px;
font-size: 12px;
color: #666;
}
@media print {
body {
padding: 0;
}
}
</style>
</head>
<body>
${printContent.innerHTML}
</body>
</html>
`);
printWindow.document.close();
// 等待内容加载完成后打印
printWindow.onload = function() {
setTimeout(() => {
printWindow.print();
// 打印后关闭窗口(可选)
// printWindow.close();
}, 250);
};
}
// 选择挂号记录
function handleRecordSelect(row) {
selectedRecord.value = row;
}
// 确认选择记录
async function handleConfirmSelect() {
if (!selectedRecord.value) {
proxy.$modal.msgWarning('请选择一条挂号记录');
return;
}
loading.value = true;
selectDialogVisible.value = false;
try {
// 保存当前记录,用于打印
currentRecord.value = selectedRecord.value;
// 填充表单 - 确保数据正确填充
fillForm(selectedRecord.value);
// 等待一小段时间,确保 form 数据已更新
await new Promise(resolve => setTimeout(resolve, 50));
// 验证表单数据是否已正确填充
if (!form.encounterId) {
proxy.$modal.msgError('获取挂号记录ID失败请重试');
loading.value = false;
return;
}
// 提交补打操作handleSubmit 内部会管理 loading 状态)
await handleSubmit();
} catch (error) {
console.error('确认选择记录失败:', error);
proxy.$modal.msgError('处理失败: ' + (error.message || '未知错误'));
loading.value = false;
}
}
</script>
<style scoped>
/* 确保对话框内容区域的背景色 */
:deep(.el-dialog__body) {
padding: 0;
background-color: #ffffff;
}
/* 输入框样式 */
:deep(.el-input__inner) {
background-color: #ffffff;
}
/* 标签样式 */
:deep(.el-form-item__label) {
font-weight: normal;
color: #333;
}
/* 打印预览对话框样式 */
.print-preview-dialog {
:deep(.el-dialog__body) {
padding: 20px;
max-height: 70vh;
overflow-y: auto;
}
}
.print-content {
background: white;
padding: 20px;
font-family: Arial, sans-serif;
}
.print-header {
margin-bottom: 20px;
position: relative;
}
.reprint-label-left {
position: absolute;
top: 0;
left: 0;
color: red;
font-size: 16px;
font-weight: bold;
}
.header-content {
text-align: center;
}
.document-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 10px;
}
.print-time {
font-size: 12px;
color: #666;
text-align: right;
}
.print-section {
margin-bottom: 20px;
}
.section-title {
font-size: 14px;
font-weight: bold;
margin-bottom: 10px;
border-bottom: 1px solid #ddd;
padding-bottom: 5px;
}
.info-row {
margin-bottom: 8px;
font-size: 13px;
}
.info-row .label {
display: inline-block;
width: 100px;
font-weight: bold;
}
.info-row .value {
display: inline-block;
}
.fee-table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}
.fee-table th,
.fee-table td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
.fee-table th {
background-color: #f5f5f5;
font-weight: bold;
}
.total-label {
font-weight: bold;
text-align: right;
}
.total-value {
font-weight: bold;
color: red;
}
.print-footer {
margin-top: 20px;
font-size: 12px;
color: #666;
}
.reminder {
text-align: center;
padding: 10px;
background-color: #f9f9f9;
border-radius: 4px;
}
</style>