Files
his/openhis-ui-vue3/src/views/inpatientNurse/InpatientBilling/components/depositQuery.vue
2025-12-10 14:20:24 +08:00

490 lines
15 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>
<div style="height: calc(100vh - 126px)">
<!-- 操作工具栏 -->
<div
style="
height: 51px;
border-bottom: 2px solid #e4e7ed;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 15px;
"
>
<div style="display: flex; align-items: center">
<!-- 日期选择tabs -->
<el-tabs
v-model="dateRange"
type="card"
class="date-tabs"
@tab-click="handleDateTabClick"
style="margin-right: 20px"
>
<el-tab-pane label="今日" name="today"></el-tab-pane>
<el-tab-pane label="昨日" name="yesterday"></el-tab-pane>
<el-tab-pane label="其他" name="other"></el-tab-pane>
</el-tabs>
<!-- 日期选择器 -->
<el-date-picker
v-model="dateRangeValue"
type="daterange"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
@change="handleDatePickerChange"
style="width: 240px; margin-right: 20px"
/>
<!-- 缴费方式选择 -->
<el-select
v-model="paymentMethod"
placeholder="请选择缴费方式"
clearable
style="width: 150px; margin-right: 20px"
>
<el-option
v-for="method in paymentMethodOptions"
:key="method.value"
:label="method.label"
:value="method.value"
/>
</el-select>
<!-- 查询按钮 -->
<el-button type="primary" @click="handleQuery">查询</el-button>
</div>
<div style="display: flex; align-items: center">
<!-- 导出按钮 -->
<el-button @click="handleExport">导出</el-button>
<!-- 打印按钮 -->
<el-button @click="handlePrint" style="margin-left: 15px">打印</el-button>
</div>
</div>
<!-- 预交金列表区域 -->
<div
style="padding: 10px; background-color: #eef9fd; height: 100%; overflow-y: auto"
v-loading="loading"
>
<!-- 费用汇总信息 -->
<div style="background-color: white; padding: 15px; margin-bottom: 10px; border-radius: 4px;">
<div style="display: flex; justify-content: flex-end; align-items: center">
<div style="text-align: right;">
<p style="margin: 0; font-size: 18px; font-weight: bold; color: #ff4d4f;">
合计金额¥{{ totalAmount.toFixed(2) }}
</p>
<p style="margin: 5px 0; color: #606266; font-size: 14px;">缴费次数{{ depositList.length }}</p>
</div>
</div>
</div>
<el-table
ref="tableRef"
:data="depositList"
border
style="width: 100%"
:header-cell-style="{ background: '#eef9fd !important' }"
@sort-change="handleSortChange"
>
<el-table-column label="序号" type="index" width="60" align="center" />
<el-table-column label="预交金编号" prop="depositNo" min-width="180" />
<el-table-column label="金额" prop="amount" width="120" align="center" sortable>
<template #default="scope">
<span style="color: #ff4d4f">{{ scope.row.amount.toFixed(2) }}</span>
</template>
</el-table-column>
<el-table-column label="缴费方式" prop="paymentMethodName" width="120" align="center" />
<el-table-column label="缴费时间" prop="paymentTime" width="150" align="center" sortable />
<el-table-column label="收费员" prop="cashier" width="100" align="center" />
</el-table>
<!-- 分页 -->
<div style="margin-top: 15px; display: flex; justify-content: flex-end;">
<el-pagination
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
<!-- 无数据提示 -->
<el-empty v-if="!loading && depositList.length === 0" description="暂无预交金数据" />
</div>
<!-- 打印预览弹窗 -->
<el-dialog v-model="printDialogVisible" title="打印预览" width="80%" :close-on-click-modal="false">
<div id="print-content">
<div style="text-align: center; margin-bottom: 20px;">
<h2 style="margin: 0;">预交金清单</h2>
<p style="margin: 5px 0;">患者姓名{{ patientInfo || '未选择患者' }}</p>
<p style="margin: 5px 0;">费用周期{{ formatDateRange() }}</p>
</div>
<table style="width: 100%; border-collapse: collapse;">
<thead>
<tr style="background-color: #eef9fd;">
<th style="border: 1px solid #e4e7ed; padding: 8px;">序号</th>
<th style="border: 1px solid #e4e7ed; padding: 8px;">预交金编号</th>
<th style="border: 1px solid #e4e7ed; padding: 8px;">金额</th>
<th style="border: 1px solid #e4e7ed; padding: 8px;">缴费方式</th>
<th style="border: 1px solid #e4e7ed; padding: 8px;">缴费时间</th>
<th style="border: 1px solid #e4e7ed; padding: 8px;">收费员</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in depositList" :key="item.id">
<td style="border: 1px solid #e4e7ed; padding: 8px;">{{ index + 1 }}</td>
<td style="border: 1px solid #e4e7ed; padding: 8px;">{{ item.depositNo }}</td>
<td style="border: 1px solid #e4e7ed; padding: 8px;">{{ item.amount.toFixed(2) }}</td>
<td style="border: 1px solid #e4e7ed; padding: 8px;">{{ item.paymentMethodName }}</td>
<td style="border: 1px solid #e4e7ed; padding: 8px;">{{ item.paymentTime }}</td>
<td style="border: 1px solid #e4e7ed; padding: 8px;">{{ item.cashier }}</td>
</tr>
</tbody>
<tfoot>
<tr style="background-color: #f5f7fa;">
<td colspan="2" style="border: 1px solid #e4e7ed; padding: 8px; text-align: right; font-weight: bold;">合计</td>
<td colspan="4" style="border: 1px solid #e4e7ed; padding: 8px; color: #ff4d4f; font-weight: bold;">¥{{ totalAmount.toFixed(2) }}</td>
</tr>
</tfoot>
</table>
</div>
<template #footer>
<el-button @click="printDialogVisible = false">关闭</el-button>
<el-button type="primary" @click="doPrint">打印</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue';
import { ElMessage } from 'element-plus';
import { patientInfoList } from '../../medicalOrderExecution/store/patient.js';
import { getSinglePatient } from '../store/patient.js'; // 导入获取单选患者信息的方法
import { formatDateStr } from '@/utils/index';
// 响应式数据
const loading = ref(false);
const depositList = ref([]);
const dateRange = ref('today'); // today, yesterday, other
const dateRangeValue = ref([]);
const paymentMethod = ref('');
const paymentMethodOptions = ref([]);
const tableRef = ref(null);
const patientInfo = ref('');
// 分页相关
const currentPage = ref(1);
const pageSize = ref(20);
const total = ref(0);
// 打印相关
const printDialogVisible = ref(false);
// 计算总金额
const totalAmount = computed(() => {
return depositList.value.reduce((sum, item) => {
return sum + (item.amount || 0);
}, 0);
});
// 初始化
onMounted(() => {
// 设置默认日期
const today = new Date();
dateRangeValue.value = [formatDateStr(today, 'YYYY-MM-DD'), formatDateStr(today, 'YYYY-MM-DD')];
// 加载缴费方式选项
loadPaymentMethodOptions();
// 监听患者选择变化
watchPatientSelection();
});
// 监听患者选择变化
function watchPatientSelection() {
// 定期检查患者选择状态变化
setInterval(() => {
// 使用getSinglePatient方法获取单选患者信息
const selectedPatient = getSinglePatient();
if (selectedPatient) {
patientInfo.value = selectedPatient.patientName || '';
} else {
patientInfo.value = '未选择患者';
}
}, 300);
}
// 加载缴费方式选项
function loadPaymentMethodOptions() {
// 模拟缴费方式数据
paymentMethodOptions.value = [
{ label: '现金', value: 'cash' },
{ label: '银行卡', value: 'bankcard' },
{ label: '微信支付', value: 'wechat' },
{ label: '支付宝', value: 'alipay' },
{ label: '其他', value: 'others' },
];
}
// 处理日期tabs点击
function handleDateTabClick(tab) {
const rangeType = tab.paneName;
const today = new Date();
const yesterday = new Date();
yesterday.setDate(today.getDate() - 1);
switch (rangeType) {
case 'today':
dateRangeValue.value = [
formatDateStr(today, 'YYYY-MM-DD'),
formatDateStr(today, 'YYYY-MM-DD'),
];
break;
case 'yesterday':
dateRangeValue.value = [
formatDateStr(yesterday, 'YYYY-MM-DD'),
formatDateStr(yesterday, 'YYYY-MM-DD'),
];
break;
// other 情况保持用户选择的值
}
}
// 处理日期选择器变化
function handleDatePickerChange() {
if (dateRangeValue.value.length > 0) {
dateRange.value = 'other';
}
}
// 格式化日期范围显示
function formatDateRange() {
if (dateRangeValue.value && dateRangeValue.value.length === 2) {
return `${dateRangeValue.value[0]}${dateRangeValue.value[1]}`;
}
return '';
}
// 生成模拟数据
function generateMockData() {
// 缴费方式映射
const paymentMethodMap = {
'cash': '现金',
'bankcard': '银行卡',
'wechat': '微信支付',
'alipay': '支付宝',
'others': '其他'
};
// 生成模拟数据
const mockData = [];
const baseDate = new Date(dateRangeValue.value[0]);
const endDate = new Date(dateRangeValue.value[1]);
const daysDiff = Math.ceil((endDate - baseDate) / (1000 * 60 * 60 * 24)) + 1;
// 收费员池
const cashiers = ['收费员A', '收费员B', '收费员C', '收费员D'];
// 生成数据
let id = 1;
for (let day = 0; day < daysDiff; day++) {
const currentDate = new Date(baseDate);
currentDate.setDate(baseDate.getDate() + day);
// 每天生成1-3条记录
const recordsCount = Math.floor(Math.random() * 3) + 1;
for (let i = 0; i < recordsCount; i++) {
// 随机选择一个缴费方式
const paymentMethods = paymentMethod.value ? [paymentMethod.value] : Object.keys(paymentMethodMap);
const randomMethod = paymentMethods[Math.floor(Math.random() * paymentMethods.length)];
// 生成随机金额 (500-5000元)
const amount = Math.floor(Math.random() * 4500) + 500;
// 生成时间
const hours = Math.floor(Math.random() * 8) + 8; // 8-16点
const minutes = Math.floor(Math.random() * 60);
const seconds = Math.floor(Math.random() * 60);
currentDate.setHours(hours, minutes, seconds);
const timeStr = formatDateStr(currentDate, 'YYYY-MM-DD HH:mm:ss');
// 生成预交金编号 (示例格式5000120200001)
const dateCode = formatDateStr(currentDate, 'YYYYMMDD');
const serialNum = String(id).padStart(6, '0');
const depositNo = `500${dateCode.slice(2)}${serialNum}`;
mockData.push({
id: id++,
depositNo: depositNo,
amount: amount,
paymentMethod: randomMethod,
paymentMethodName: paymentMethodMap[randomMethod],
paymentTime: timeStr,
cashier: cashiers[Math.floor(Math.random() * cashiers.length)]
});
}
}
return mockData;
}
// 查询按钮点击
function handleQuery() {
// 添加调试日志,查看患者列表数据结构
console.log('患者列表数据:', patientInfoList.value);
// 使用getSinglePatient方法获取单选患者信息
const selectedPatient = getSinglePatient();
if (!selectedPatient) {
ElMessage.warning('请先选择患者');
return;
}
// 更新患者信息显示
const patientName = selectedPatient.patientName ||
selectedPatient.name ||
selectedPatient.patientInfo ||
selectedPatient.patient ||
'未命名患者';
patientInfo.value = patientName;
loading.value = true;
// 模拟API调用延迟
setTimeout(() => {
try {
// 使用模拟数据
const allData = generateMockData();
total.value = allData.length;
// 分页处理
const start = (currentPage.value - 1) * pageSize.value;
const end = start + pageSize.value;
depositList.value = allData.slice(start, end);
} catch (error) {
console.error('查询错误:', error);
ElMessage.error('查询失败,请重试');
depositList.value = [];
total.value = 0;
} finally {
loading.value = false;
}
}, 500);
}
// 处理排序变化
function handleSortChange({ prop, order }) {
const sortedData = [...depositList.value];
if (order === 'ascending') {
sortedData.sort((a, b) => (a[prop] > b[prop]) ? 1 : -1);
} else if (order === 'descending') {
sortedData.sort((a, b) => (a[prop] < b[prop]) ? 1 : -1);
}
depositList.value = sortedData;
}
// 处理分页大小变化
function handleSizeChange(newSize) {
pageSize.value = newSize;
currentPage.value = 1;
handleQuery();
}
// 处理当前页变化
function handleCurrentChange(newCurrent) {
currentPage.value = newCurrent;
handleQuery();
}
// 导出
function handleExport() {
if (depositList.value.length === 0) {
ElMessage.warning('暂无数据可导出');
return;
}
// 模拟导出操作
ElMessage.success('导出成功');
// 实际项目中这里应该调用导出API或使用Excel库生成文件
}
// 打印预览
function handlePrint() {
if (depositList.value.length === 0) {
ElMessage.warning('暂无数据可打印');
return;
}
printDialogVisible.value = true;
}
// 执行打印
function doPrint() {
try {
// 获取要打印的内容
const printContent = document.getElementById('print-content').innerHTML;
// 创建临时窗口
const printWindow = window.open('', '_blank');
// 写入内容
printWindow.document.write(`
<html>
<head>
<title>预交金清单</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
table { width: 100%; border-collapse: collapse; }
th, td { border: 1px solid #ccc; padding: 8px; }
th { background-color: #f2f2f2; }
tfoot { font-weight: bold; }
.total-row { background-color: #f5f5f5; }
</style>
</head>
<body>
${printContent}
</body>
</html>
`);
// 打印
printWindow.document.close();
printWindow.focus();
printWindow.print();
} catch (e) {
ElMessage.error('打印失败');
console.error('Print error:', e);
}
}
// 暴露方法供父组件调用
defineExpose({
handleQuery,
});
</script>
<style scoped>
/* 日期tabs样式 */
.date-tabs .el-tabs__header {
margin-bottom: 0;
}
.date-tabs .el-tabs__content {
display: none;
}
</style>