46
openhis-ui-vue3/src/views/charge/clinicRecord/components/api.js
Executable file
46
openhis-ui-vue3/src/views/charge/clinicRecord/components/api.js
Executable file
@@ -0,0 +1,46 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 获取支付记录列表
|
||||
export function getList(query) {
|
||||
return request({
|
||||
url: '/payment/payment/page',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
export function invoiceMzInvoice(data) {
|
||||
return request({
|
||||
url: '/invoice/mzInvoice',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
export function invoiceReissue(data) {
|
||||
return request({
|
||||
url: '/invoice/invoiceReissue',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
export function invoiceWriteoff(data) {
|
||||
return request({
|
||||
url: '/invoice/invoiceWriteoff',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
export function invoiceOpen(invoiceId) {
|
||||
return request({
|
||||
url: '/invoice/invoiceOpen?invoiceId=' + invoiceId,
|
||||
method: 'put',
|
||||
})
|
||||
}
|
||||
// 收费详情
|
||||
export function paymentDetail(data) {
|
||||
return request({
|
||||
url: '/payment/payment/detail',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
346
openhis-ui-vue3/src/views/charge/clinicRecord/index.vue
Executable file
346
openhis-ui-vue3/src/views/charge/clinicRecord/index.vue
Executable file
@@ -0,0 +1,346 @@
|
||||
<template>
|
||||
<div class="app-continer">
|
||||
<div style="margin: 15px 0; padding: 0 20px">
|
||||
<el-form :model="queryParams" ref="queryRef" :inline="true" label-width="90px">
|
||||
<el-form-item label="患者姓名:" prop="searchKey">
|
||||
<el-input
|
||||
v-model="queryParams.searchKey"
|
||||
placeholder="患者姓名"
|
||||
clearable
|
||||
style="width: 240px"
|
||||
@keyup.enter="getClinicRecord"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="发票号:" prop="invoiceNo" label-width="120px">
|
||||
<el-input
|
||||
v-model="queryParams.invoiceNo"
|
||||
placeholder="发票号"
|
||||
clearable
|
||||
style="width: 240px"
|
||||
@keyup.enter="getClinicRecord"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="发票状态:" prop="invoiceStatus">
|
||||
<el-select
|
||||
v-model="queryParams.invoiceStatus"select
|
||||
placeholder="发票状态"
|
||||
clearable
|
||||
style="width: 240px"
|
||||
@keyup.enter="getClinicRecord"
|
||||
>
|
||||
<el-option v-for="item in invoiceStatusList" :key="item.value" :label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="结算时间:" prop="activeFlag">
|
||||
<el-date-picker
|
||||
v-model="occurrenceTime"
|
||||
type="daterange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
style="width: 300px; margin-bottom: 10px; margin-left: 20px"
|
||||
value-format="YYYY-MM-DD"
|
||||
:clearable="false"
|
||||
@change="getClinicRecord"
|
||||
/>
|
||||
</el-form-item>
|
||||
<div style="float: right">
|
||||
<el-button type="primary" plain @click="getClinicRecord">查询</el-button>
|
||||
<el-button type="warning" plain @click="handleReset">重置</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
<div style="float: right; margin: 0 20px 10px 0">
|
||||
<span style="margin-right: 20px">
|
||||
{{ '总数:' + count + '/' + '成功:' + successCount }}
|
||||
</span>
|
||||
<el-button type="primary" :loading="loading" plain @click="handleBatchProcess">批量开具</el-button>
|
||||
</div>
|
||||
<el-table :data="clinicRecord" border>
|
||||
<!-- <el-table-column label="计算类型" align="center" prop="statusEnum_enumText" /> -->
|
||||
<el-table-column label="患者姓名" align="center" prop="patientName" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="支付状态" align="center" prop="statusEnum_dictText" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="费用类型" align="center" prop="paymentEnum_dictText" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="医保结算Id" align="center" prop="ybSettleIds" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="收费流水号" align="center" prop="paymentNo" width="280" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="发票号" align="center" prop="invoiceNo" :show-overflow-tooltip="true"/>
|
||||
<el-table-column
|
||||
label="结算金额"
|
||||
align="right"
|
||||
prop="tenderedAmount"
|
||||
header-align="center"
|
||||
width="100"
|
||||
:show-overflow-tooltip="true"
|
||||
>
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.tenderedAmount + ' 元' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="支付金额"
|
||||
align="right"
|
||||
prop="displayAmount"
|
||||
header-align="center"
|
||||
width="100"
|
||||
:show-overflow-tooltip="true"
|
||||
>
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.displayAmount + ' 元' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="结算时间"
|
||||
align="center"
|
||||
key="billDate"
|
||||
prop="billDate"
|
||||
|
||||
:show-overflow-tooltip="true"
|
||||
>
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.billDate) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="收款人" align="center" prop="entererName" :show-overflow-tooltip="true"/>
|
||||
<!-- <el-table-column label="医生" align="center" prop="paymentEnum_enumText" /> -->
|
||||
<el-table-column label="支付结果" align="center" prop="outcomeEnum_dictText" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="打印次数" align="center" prop="printCount" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="操作" align="center" prop="paymentEnum_enumText" width="340">
|
||||
<template #default="scope">
|
||||
<!-- <el-button type="primary" link @click="handlePrint(scope.row)">单据</el-button> -->
|
||||
<!-- <el-button type="primary" link @click="handleEdit(scope.row)">冲红</el-button> -->
|
||||
<el-button type="primary" link @click="handleOpen(scope.row,4)">收费详情</el-button>
|
||||
<el-button type="primary" link @click="handleOpen(scope.row,1)" :disabled="scope.row.invoiceNo || scope.row.statusEnum == 3">开具电子发票</el-button>
|
||||
<el-button :disabled="!scope.row.relationId" type="primary" link @click="handleOpenReasonDialog(scope.row)">冲销发票</el-button>
|
||||
<el-button type="primary" link @click="handleOpen(scope.row,3)" :disabled="!scope.row.invoiceNo">调阅发票</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getLists"
|
||||
/>
|
||||
<el-dialog title="收费详情" v-model="paymentDetailShow" width="1000" append-to-body style="height:90vh">
|
||||
<el-table :data="paymentDetailList" border style="height: 80vh">
|
||||
<el-table-column label="支付类型" align="center" prop="payEnum_dictText" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="金额" align="center" prop="amount" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="找零" align="center" prop="returnAmount" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="交款" align="center" prop="chargeAmount" :show-overflow-tooltip="true"/>
|
||||
</el-table>
|
||||
</el-dialog>
|
||||
<el-dialog title="请输入原因" v-model="reasonDialogVisible" width="30%">
|
||||
<el-form :model="reasonForm" label-width="80px">
|
||||
<el-form-item label="冲销原因">
|
||||
<el-input v-model="reasonForm.reason" placeholder="请输入原因" type="textarea" :rows="3" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="reasonDialogVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="submitReason">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="ClinicRecord">
|
||||
const { proxy } = getCurrentInstance();
|
||||
import {getList, invoiceOpen, invoiceReissue, invoiceWriteoff, paymentDetail} from './components/api.js';
|
||||
import {formatDate} from '@/utils/index';
|
||||
|
||||
const occurrenceTime = ref([formatDate(new Date()),formatDate(new Date())]);
|
||||
const total = ref(0);
|
||||
const queryParams = ref({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
billDateSTime:"",
|
||||
billDateETime:"",
|
||||
searchKey:"",
|
||||
invoiceStatus:1,
|
||||
kinsEnum: 1
|
||||
});
|
||||
const invoiceStatusList = ref([
|
||||
{ value: 1, label: '已开具' },
|
||||
{ value: 0, label: '未开具' },
|
||||
]);
|
||||
const paymentDetailShow = ref(false)
|
||||
const clinicRecord = ref([]);
|
||||
const successCount = ref(0);
|
||||
const count = ref(0);
|
||||
const reasonDialogVisible = ref(false);
|
||||
const reasonForm = ref({
|
||||
reason: ''
|
||||
});
|
||||
const currentRow = ref(null);
|
||||
const paymentDetailList = ref([])
|
||||
getLists();
|
||||
function getClinicRecord() {
|
||||
queryParams.value.billDateSTime =
|
||||
occurrenceTime.value && occurrenceTime.value.length == 2
|
||||
? occurrenceTime.value[0] + " 00:00:00"
|
||||
: "";
|
||||
queryParams.value.billDateETime =
|
||||
occurrenceTime.value && occurrenceTime.value.length == 2
|
||||
? occurrenceTime.value[1] + " 23:59:59"
|
||||
: "";
|
||||
queryParams.value.pageNo = 1;
|
||||
getLists()
|
||||
}
|
||||
function getLists(){
|
||||
getList(queryParams.value).then((res) => {
|
||||
total.value = res.data.total;
|
||||
clinicRecord.value = res.data.records;
|
||||
});
|
||||
}
|
||||
function handleOpenReasonDialog(row) {
|
||||
// 可选:保存当前行数据以便后续使用
|
||||
currentRow.value = row;
|
||||
reasonForm.value.reason = ''; // 清空上次输入
|
||||
reasonDialogVisible.value = true;
|
||||
}
|
||||
// 提交原因
|
||||
function submitReason() {
|
||||
if (!reasonForm.value.reason.trim()) {
|
||||
proxy.$message.warning('请输入原因');
|
||||
return;
|
||||
}
|
||||
|
||||
invoiceWriteoff({paymentId:currentRow.value.relationIdStr,reason:reasonForm.value.reason}).then((res) => {
|
||||
if (res.data) {
|
||||
if(res.data.includes(" 电子票据红冲失败")){
|
||||
proxy.$message.error(res.data);
|
||||
}else{
|
||||
proxy.$message.success('红冲成功');
|
||||
// 关闭弹窗
|
||||
reasonDialogVisible.value = false;
|
||||
|
||||
// 可选:重置表单
|
||||
reasonForm.value.reason = '';
|
||||
window.open(res.data)
|
||||
}
|
||||
}
|
||||
getLists();
|
||||
}).catch((err)=>{
|
||||
})
|
||||
}
|
||||
/** 清空条件按钮操作 */
|
||||
function handleReset() {
|
||||
// 清空查询条件
|
||||
occurrenceTime.value = ""
|
||||
queryParams.value.billDateSTime = ""
|
||||
queryParams.value.billDateETime = ""
|
||||
proxy.resetForm("queryRef");
|
||||
getLists();
|
||||
}
|
||||
// function handlePrint(row){
|
||||
|
||||
// }
|
||||
// function handleEdit(row){
|
||||
|
||||
// }
|
||||
|
||||
const loading = ref(false)
|
||||
async function handleBatchProcess() {
|
||||
// 遍历list并异步执行invoiceReissue方法
|
||||
let list = clinicRecord.value.filter(item =>{
|
||||
return item.statusEnum == 1 && (item.invoiceNo == undefined || item.invoiceNo == null)
|
||||
})
|
||||
loading.value = true
|
||||
count.value = list.length;
|
||||
for (const item of list) {
|
||||
try {
|
||||
const res = await invoiceReissue({
|
||||
paymentId: item.id,
|
||||
encounterId: item.encounterId ? item.encounterId : ""
|
||||
});
|
||||
|
||||
if (res.data) {
|
||||
// 门诊电子发票开具失败 住院电子发票开具失败 电子发票类型不明确
|
||||
if (
|
||||
res.data.includes(" 挂号电子发票开具失败") ||
|
||||
res.data.includes(" 住院电子发票开具失败") ||
|
||||
res.data.includes(" 门诊电子发票开具失败") ||
|
||||
res.data.includes(" 电子发票类型不明确")
|
||||
) {
|
||||
// proxy.$message.error(res.data);
|
||||
} else {
|
||||
successCount.value++;
|
||||
// window.open(res.data);
|
||||
}
|
||||
}
|
||||
if (res.code == 200) {
|
||||
// getLists();
|
||||
} else {
|
||||
// proxy.$message.error(res.data);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
loading.value = false
|
||||
getLists()
|
||||
}
|
||||
|
||||
function handleOpen(row,type){
|
||||
if(type==1){
|
||||
invoiceReissue({paymentId:row.id,encounterId:row.encounterId?row.encounterId:""}).then((res) => {
|
||||
if (res.data) {
|
||||
// 门诊电子发票开具失败 住院电子发票开具失败 电子发票类型不明确
|
||||
if(res.data.includes(" 挂号电子发票开具失败")||res.data.includes(" 住院电子发票开具失败")||res.data.includes(" 门诊电子发票开具失败")||res.data.includes(" 电子发票类型不明确")){
|
||||
proxy.$message.error(res.data);
|
||||
}else{
|
||||
window.open(res.data)
|
||||
}
|
||||
}
|
||||
if(res.code == 200) {
|
||||
getLists();
|
||||
}
|
||||
proxy.$message.error(res.data);
|
||||
}).catch((err)=>{
|
||||
})
|
||||
}else if(type==2) {
|
||||
invoiceWriteoff({paymentId:row.id,encounterId:row.encounterId?row.encounterId:""}).then((res) => {
|
||||
if (res.data) {
|
||||
if(res.data.includes(" 电子票据红冲失败")){
|
||||
proxy.$message.error(res.data);
|
||||
}else{
|
||||
window.open(res.data)
|
||||
}
|
||||
}
|
||||
}).catch((err)=>{
|
||||
})
|
||||
}else if(type==3){
|
||||
// 调阅电子发票
|
||||
invoiceOpen(row.invoiceId?row.invoiceId:"").then((res) => {
|
||||
if (res.data) {
|
||||
window.open(res.data)
|
||||
}
|
||||
}).catch((err)=>{
|
||||
})
|
||||
}else{
|
||||
paymentDetail({id:row.id?row.id:""}).then((res) => {
|
||||
if (res.data) {
|
||||
paymentDetailShow.value = true
|
||||
paymentDetailList.value = res.data
|
||||
}
|
||||
}).catch((err)=>{
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.el-dialog{
|
||||
height: 90vh!important;
|
||||
}
|
||||
.dialog-footer {
|
||||
text-align: right;
|
||||
}
|
||||
.el-textarea__inner {
|
||||
resize: none;
|
||||
}
|
||||
</style>
|
||||
156
openhis-ui-vue3/src/views/charge/cliniccharge/components/api.js
Executable file
156
openhis-ui-vue3/src/views/charge/cliniccharge/components/api.js
Executable file
@@ -0,0 +1,156 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
/**
|
||||
* 收费患者列表
|
||||
*/
|
||||
export function getList(queryParams) {
|
||||
return request({
|
||||
url: '/charge-manage/charge/encounter-patient-page',
|
||||
method: 'get',
|
||||
params: queryParams
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 患者处方列表
|
||||
*/
|
||||
export function getChargeList(encounterId, config = {}) {
|
||||
return request({
|
||||
url: '/charge-manage/charge/patient-prescription?encounterId=' + encounterId,
|
||||
method: 'get',
|
||||
...config
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 医保转自费
|
||||
*/
|
||||
export function changeToSelfPay(encounterId) {
|
||||
return request({
|
||||
url: '/charge-manage/charge/self-pay?encounterId=' + encounterId,
|
||||
method: 'put',
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 自费转医保
|
||||
*/
|
||||
export function changeToMedicalInsurance(encounterId) {
|
||||
return request({
|
||||
url: '/charge-manage/charge/medical-insurance?encounterId=' + encounterId,
|
||||
method: 'put',
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 学生医保转学生自费
|
||||
*/
|
||||
export function changeStudentPayTosStudentSelf(encounterId) {
|
||||
return request({
|
||||
url: '/charge-manage/charge/student-self-pay?encounterId=' + encounterId,
|
||||
method: 'put',
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 学生自费转学生医保
|
||||
*/
|
||||
export function changeStudentSelfToStudentPay(encounterId) {
|
||||
return request({
|
||||
url: '/charge-manage/charge/student-yb-pay?encounterId=' + encounterId,
|
||||
method: 'put',
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 收费
|
||||
*/
|
||||
export function savePayment(data) {
|
||||
return request({
|
||||
url: '/payment/payment/charge',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
export function init() {
|
||||
return request({
|
||||
url: '/charge-manage/charge/init',
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 收费预结算
|
||||
*/
|
||||
export function precharge(data) {
|
||||
return request({
|
||||
url: '/payment/payment/precharge',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消预结算
|
||||
*/
|
||||
export function unprecharge(data) {
|
||||
return request({
|
||||
url: '/payment/payment/unprecharge',
|
||||
method: 'post',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 发耗材
|
||||
*/
|
||||
export function dispenseMedicalConsumables(data, config = {}) {
|
||||
return request({
|
||||
url: '/pharmacy-manage/device-dispense/consumables-dispense',
|
||||
method: 'put',
|
||||
data: data,
|
||||
...config
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 补打小票
|
||||
*/
|
||||
export function getChargeInfo(param, config = {}) {
|
||||
return request({
|
||||
url: '/payment/bill/getDetail',
|
||||
method: 'get',
|
||||
params: param,
|
||||
...config
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信支付
|
||||
*/
|
||||
export function wxPay (data) {
|
||||
return request ({
|
||||
url: '/three-part/pay/pay-for',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信支付
|
||||
*/
|
||||
export function WxPayResult (data) {
|
||||
return request ({
|
||||
url: '/three-part/pay/pay-query/' + data.paymentId,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
967
openhis-ui-vue3/src/views/charge/cliniccharge/components/chargeDialog.vue
Executable file
967
openhis-ui-vue3/src/views/charge/cliniccharge/components/chargeDialog.vue
Executable file
@@ -0,0 +1,967 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
title="确认收费"
|
||||
v-model="props.open"
|
||||
width="700px"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
@open="handleOpen"
|
||||
@close="close"
|
||||
>
|
||||
<div v-loading="dialogLoading">
|
||||
<el-text size="large" style="display: block; margin-bottom: 15px">
|
||||
收费日期:{{ currentDate }}
|
||||
</el-text>
|
||||
<el-text size="large">费用性质:{{ '自费' }}</el-text>
|
||||
<div class="amount-row">
|
||||
<el-text size="large">应收金额:</el-text>
|
||||
<el-text size="large" type="primary" class="amount">
|
||||
{{ props.totalAmount.toFixed(2) + ' 元' }}
|
||||
</el-text>
|
||||
</div>
|
||||
<div class="amount-row">
|
||||
<el-text size="large">折扣金额:</el-text>
|
||||
<el-text size="large" type="warning" class="amount">
|
||||
{{ discountAmount.toFixed(2) + ' 元' }}
|
||||
</el-text>
|
||||
</div>
|
||||
|
||||
<!-- 自费支付 -->
|
||||
<div class="payment-container">
|
||||
<template v-for="(item, index) in formData.selfPay" :key="index">
|
||||
<div v-show="item.payEnum != 220500" class="payment-item">
|
||||
<span>支付方式:</span>
|
||||
<img
|
||||
v-if="item.payEnum == 220100 || item.payEnum == 220200"
|
||||
:src="imgs[item.payEnum == 220100 ? 0 : 1]"
|
||||
style="width: 20px; height: 20px"
|
||||
/>
|
||||
<el-select
|
||||
v-model="item.payEnum"
|
||||
placeholder="选择支付方式"
|
||||
style="width: 160px"
|
||||
@change="(value) => clearAmount(index, value)"
|
||||
>
|
||||
<el-option
|
||||
v-for="payEnum in selfPayMethods"
|
||||
:key="payEnum.value"
|
||||
:label="payEnum.label"
|
||||
:value="payEnum.value"
|
||||
:disabled="isMethodDisabled(payEnum)"
|
||||
/>
|
||||
</el-select>
|
||||
<span>支付金额:</span>
|
||||
<div class="suffix-wrapper">
|
||||
<el-input-number
|
||||
v-model="item.amount"
|
||||
:precision="2"
|
||||
:min="0"
|
||||
:max="getMax(index)"
|
||||
:controls="false"
|
||||
placeholder="金额"
|
||||
class="amount-input"
|
||||
@change="handleAmountChange"
|
||||
/>
|
||||
<span class="suffix-text">元</span>
|
||||
</div>
|
||||
<el-button
|
||||
type="danger"
|
||||
circle
|
||||
:icon="Delete"
|
||||
@click="removePayment(index)"
|
||||
v-if="index > 0"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<div class="add-payment">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click="addPayment"
|
||||
:disabled="formData.selfPay.length >= 4 || remainingAmount <= 0"
|
||||
>
|
||||
添加支付方式
|
||||
</el-button>
|
||||
<el-text v-if="remainingAmount <= 0" type="danger" class="tip">
|
||||
金额已满足应收,不可继续添加
|
||||
</el-text>
|
||||
</div>
|
||||
<div style="margin-top: 10px" v-if="userStore.hospitalName == '同一医院'">
|
||||
<span>折扣:</span>
|
||||
<el-radio-group v-model="discountRadio" @change="handleDiscountChange">
|
||||
<el-radio-button
|
||||
v-for="item in charge_discount"
|
||||
:key="item.value"
|
||||
link
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
<div class="payment-item">
|
||||
<span>{{ payTypeText }}支付:</span>
|
||||
<el-input
|
||||
ref="txtCodeRef"
|
||||
v-model="txtCode"
|
||||
style="width: 300px"
|
||||
:placeholder="payTypePlaceholder"
|
||||
/>
|
||||
<el-button link type="primary" @click="handleWxPay()">扫码支付</el-button>
|
||||
<el-button link type="primary" @click="getWxPayResult()">查看结果</el-button>
|
||||
</div>
|
||||
<div>
|
||||
<el-table :data="props.details" max-height="200" border>
|
||||
<el-table-column prop="payEnumText" label="支付类型" align="center" />
|
||||
<el-table-column
|
||||
prop="amount"
|
||||
label="金额"
|
||||
header-align="center"
|
||||
align="right"
|
||||
width="200"
|
||||
>
|
||||
<template #default="scope">
|
||||
{{ scope.row.amount ? scope.row.amount + ' 元' : '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<!-- 金额汇总 -->
|
||||
<div class="summary">
|
||||
<el-space :size="30">
|
||||
<div class="summary-item">
|
||||
<el-text type="info">实收合计:</el-text>
|
||||
<el-text type="success">{{ displayAmount + ' 元' }}</el-text>
|
||||
</div>
|
||||
<div class="summary-item">
|
||||
<el-text type="info">应找零:</el-text>
|
||||
<el-text type="warning">{{ returnedAmount + ' 元' }}</el-text>
|
||||
</div>
|
||||
</el-space>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="throttledGetList" :disabled="dialogLoading">
|
||||
确 定
|
||||
</el-button>
|
||||
<!-- <el-button type="primary" @click="print()" :disabled="dialogLoading">打 印</el-button> -->
|
||||
<el-button @click="close" :disabled="dialogLoading">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {dispenseMedicalConsumables, getChargeInfo, savePayment, wxPay, WxPayResult,} from './api';
|
||||
import {computed, getCurrentInstance, reactive, ref, watch} from 'vue';
|
||||
import {Delete} from '@element-plus/icons-vue';
|
||||
import {debounce} from 'lodash-es';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
import {hiprint} from 'vue-plugin-hiprint';
|
||||
import templateJson from './template.json';
|
||||
import printUtils, {PRINT_TEMPLATE} from '@/utils/printUtils';
|
||||
import image1 from '../../../../assets/images/weixinzhifu.png';
|
||||
import image2 from '../../../../assets/images/zhifubaozhifu.png';
|
||||
|
||||
const imgs = ref([image1, image2]);
|
||||
const props = defineProps({
|
||||
open: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
totalAmount: {
|
||||
type: Number,
|
||||
default: 0.0,
|
||||
},
|
||||
category: {
|
||||
type: String,
|
||||
},
|
||||
paymentId: {
|
||||
type: String,
|
||||
},
|
||||
userCardInfo: {
|
||||
type: Object,
|
||||
},
|
||||
patientInfo: {
|
||||
type: Object,
|
||||
default: undefined,
|
||||
},
|
||||
chargeItemIds: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
consumablesIdList: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
chrgBchnoList: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
|
||||
details: {
|
||||
type: Object,
|
||||
default: undefined,
|
||||
},
|
||||
chargedItems: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
// 单位字典
|
||||
const { unit_code } = proxy.useDict('unit_code');
|
||||
|
||||
const userStore = useUserStore();
|
||||
const discountRadio = ref();
|
||||
const discountAmount = ref(0);
|
||||
const txtCode = ref('');
|
||||
|
||||
const formData = reactive({
|
||||
totalAmount: 0,
|
||||
selfPay: [{ payEnum: 220100, amount: 0.0, payLevelEnum: 2 }],
|
||||
medicalInsurance: {
|
||||
account: '',
|
||||
poolPay: 0,
|
||||
personalPay: 0,
|
||||
},
|
||||
});
|
||||
const dialogLoading = ref(false);
|
||||
|
||||
watch(
|
||||
() => props.totalAmount,
|
||||
(newValue) => {
|
||||
formData.totalAmount = newValue;
|
||||
formData.selfPay[0].amount = newValue;
|
||||
}
|
||||
);
|
||||
|
||||
const emit = defineEmits(['close']);
|
||||
let displayAmountTemp = 0;
|
||||
|
||||
// 获取单位字典数据的方法
|
||||
const getUnitLabel = (unitCode) => {
|
||||
if (!unitCode) return '';
|
||||
|
||||
// 从已加载的 unit_code 字典中查找对应项
|
||||
const unit = unit_code.value?.find((item) => item.value === unitCode);
|
||||
return unit ? unit.label : ''; // 如果找不到则返回空字符串
|
||||
};
|
||||
|
||||
async function printReceipt(param) {
|
||||
// 打印收费小票数据
|
||||
console.log('========== 打印收费小票 - 开始 ==========');
|
||||
console.log('[A] 传入参数检查:');
|
||||
console.log(' - param对象:', param ? '存在' : '不存在');
|
||||
console.log(' - param.chargedItems:', param?.chargedItems ? `存在(${param.chargedItems.length}条)` : '不存在/空');
|
||||
console.log(' - param.detail:', param?.detail ? `存在(${param.detail.length}条)` : '不存在/空');
|
||||
console.log(' - param.regNo:', param?.regNo);
|
||||
console.log(' - param.fixmedinsName:', param?.fixmedinsName);
|
||||
console.log(' - props.patientInfo:', props.patientInfo ? '存在' : '不存在');
|
||||
|
||||
if (param?.chargedItems) {
|
||||
console.log('[B] 收费项目数据:');
|
||||
param.chargedItems.forEach((item, idx) => {
|
||||
console.log(` - 项目[${idx}]:`, item.chargeItemName || '未命名', '-', item.quantityWithUnit || item.quantityValue);
|
||||
});
|
||||
}
|
||||
|
||||
// 确保第一个支付方式的金额与总金额一致;
|
||||
if (formData.selfPay.length > 0) {
|
||||
formData.selfPay[0].amount = props.totalAmount;
|
||||
}
|
||||
formData.selfPay = [
|
||||
{
|
||||
payEnum: 220100, // 现金支付
|
||||
amount: props.totalAmount,
|
||||
payLevelEnum: 2,
|
||||
},
|
||||
];
|
||||
|
||||
try {
|
||||
// 处理param.chargedItems,添加quantityWithUnit字段
|
||||
console.log('[C] 开始处理收费项目列表...');
|
||||
const processedChargeItems = (param.chargedItems || []).map((item) => {
|
||||
// 获取单位标签
|
||||
const unitLabel = getUnitLabel(item.quantityUnit);
|
||||
// 拼接数量和单位
|
||||
const quantityWithUnit = unitLabel
|
||||
? `${item.quantityValue} ${unitLabel}`
|
||||
: item.quantityValue;
|
||||
|
||||
return {
|
||||
...item,
|
||||
quantityWithUnit, // 添加带单位的数量字段供打印使用
|
||||
};
|
||||
});
|
||||
console.log('[C] 处理完成,项目数:', processedChargeItems.length);
|
||||
|
||||
// 构造打印数据,整合选中行信息
|
||||
console.log('[D] 开始构造打印数据...');
|
||||
const printData = {
|
||||
data: [
|
||||
{
|
||||
...param,
|
||||
|
||||
// 收费项目列表
|
||||
chargeItemsList: processedChargeItems,
|
||||
// chargeItemsList: param.chargeItem,
|
||||
|
||||
// 基础支付类型
|
||||
|
||||
// 金额大于0时显示金额和单位,等于0时不显示单位
|
||||
YB_FUND_PAY: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 100000)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 基金支付总额
|
||||
SELF_PAY: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 200000)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 个人负担总金额
|
||||
OTHER_PAY: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 300000)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 其他(如医院负担金额)
|
||||
|
||||
// 基本医保统筹基金支出
|
||||
YB_TC_FUND_AMOUNT: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 110000)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 基本医保统筹基金支出
|
||||
YB_BC_FUND_AMOUNT: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 120000)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 补充医疗保险基金支出
|
||||
YB_JZ_FUND_AMOUNT: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 130000)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 医疗救助基金支出
|
||||
YB_OTHER_AMOUNT: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 140000)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 其他支出
|
||||
|
||||
// 职工基本医疗保险
|
||||
YB_TC_ZG_FUND_VALUE: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 110100)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 职工基本医疗保险
|
||||
YB_TC_JM_FUND_VALUE: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 110200)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 居民基本医疗保险
|
||||
|
||||
// 补充医疗保险基金支出细分
|
||||
YB_BC_JM_DB_VALUE: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 120100)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 全体参保人的居民大病保险
|
||||
YB_BC_DE_BZ_VALUE: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 120200)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 大额医疗费用补助
|
||||
YB_BC_ZG_DE_BZ_VALUE: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 120300)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 企业职工大额医疗费用补助
|
||||
YB_BC_GWY_BZ_VALUE: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 120400)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 公务员医疗补助
|
||||
|
||||
// 其他支出细分
|
||||
OTHER_PAY_DD_FUND_VALUE: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 300001)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 兜底基金支出
|
||||
OTHER_PAY_YW_SH_FUND_VALUE: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 300002)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 意外伤害基金支出
|
||||
OTHER_PAY_LX_YL_FUND_VALUE: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 300003)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 离休人员医疗保障金支出
|
||||
OTHER_PAY_LX_YH_FUND_VALUE: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 300004)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 离休人员优惠金支出
|
||||
OTHER_PAY_CZ_FUND_VALUE: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 300005)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 财政基金支出
|
||||
OTHER_PAY_CZ_YZ_FUND_VALUE: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 300006)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 财政预支支出
|
||||
OTHER_PAY_ZG_DB_FUND_VALUE: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 300007)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 职工大病基金支出
|
||||
OTHER_PAY_EY_FUND_VALUE: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 300008)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 二乙基金支出
|
||||
OTHER_PAY_QX_JZ_FUND_VALUE: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 300009)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 倾斜救助支出
|
||||
OTHER_PAY_YL_JZ_FUND_VALUE: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 300010)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 医疗救助再救助基金
|
||||
HOSP_PART_AMT: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 300011)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 医院负担金额
|
||||
|
||||
// 医保结算返回值
|
||||
FULAMT_OWNPAY_AMT: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 1)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 全自费金额
|
||||
OVERLMT_SELFPAY: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 3)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 超限价自费费用
|
||||
PRESELFPAY_AMT: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 4)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 先行自付金额
|
||||
INSCP_SCP_AMT: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 5)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 符合政策范围金额
|
||||
ACT_PAY_DEDC: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 6)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 实际支付起付线
|
||||
POOL_PROP_SELFPAY: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 7)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 基本医疗保险统筹基金支付比例
|
||||
BALC: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 8)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 余额
|
||||
|
||||
// 特殊支付方式
|
||||
SELF_YB_ZH_PAY: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 210000)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 个人医保账户支付
|
||||
SELF_YB_ZH_GJ_VALUE: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 210100)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 账户共济支付金额
|
||||
SELF_CASH_PAY: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 220000)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 个人现金支付金额
|
||||
SELF_VX_PAY: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 230000)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 微信支付金额
|
||||
SELF_ALI_PAY: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 240000)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 阿里支付金额
|
||||
|
||||
// 现金支付细分
|
||||
SELF_CASH_VALUE: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 220400)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 个人现金支付金额(现金)
|
||||
SELF_CASH_VX_VALUE: (() => {
|
||||
// 微信+银联+支付宝的合计金额
|
||||
const vxValue = param.detail?.find((t) => t.payEnum === 220100)?.amount ?? 0;
|
||||
const unionValue = param.detail?.find((t) => t.payEnum === 220300)?.amount ?? 0;
|
||||
const aliValue = param.detail?.find((t) => t.payEnum === 220200)?.amount ?? 0;
|
||||
return (Number(vxValue) + Number(unionValue) + Number(aliValue)).toFixed(2) + ' 元';
|
||||
})(),
|
||||
SELF_CASH_ALI_VALUE: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 220200)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 个人现金支付金额(支付宝)
|
||||
SELF_CASH_UNION_VALUE: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 220300)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 个人现金支付金额(银联)
|
||||
|
||||
// 基金类型(扩展)
|
||||
BIRTH_FUND: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 510100)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 生育基金
|
||||
RETIREE_MEDICAL: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 340100)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 离休人员医疗保障基金
|
||||
URBAN_BASIC_MEDICAL: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 390100)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 城乡居民基本医疗保险基金
|
||||
URBAN_SERIOUS_ILLNESS: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 390200)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 城乡居民大病医疗保险基金
|
||||
MEDICAL_ASSISTANCE: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 610100)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 医疗救助基金
|
||||
GOVERNMENT_SUBSIDY: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 640100)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 政府兜底基金
|
||||
ACCIDENT_INSURANCE: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 390400)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 意外伤害基金
|
||||
CARE_INSURANCE: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 620100)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 照护保险基金
|
||||
FINANCIAL_FUND: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 360100)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 财政基金
|
||||
HOSPITAL_ADVANCE: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 999900)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 医院垫付
|
||||
SUPPLEMENTARY_INSURANCE: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 390300)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 城乡居民大病补充保险基金
|
||||
HEALTHCARE_PREPAYMENT: (() => {
|
||||
const amount = param.detail?.find((t) => t.payEnum === 360300)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 保健预支基金
|
||||
|
||||
Mr_QR_Code: param.regNo,
|
||||
regNo: param.regNo || '',
|
||||
sex: props.patientInfo?.genderEnum_enumText || '',
|
||||
age: props.patientInfo?.age || '',
|
||||
|
||||
personType: param.contractName,
|
||||
|
||||
fixmedinsName: (param.fixmedinsName || '') + '门诊收费明细',
|
||||
|
||||
//电子收据二维码
|
||||
pictureUrl: param.pictureUrl || 'https://chinaebill.com/img/xiaochengxu.png',
|
||||
|
||||
// 添加本地患者信息,注意安全访问
|
||||
patientName: props.patientInfo?.patientName || '',
|
||||
gender: props.patientInfo?.genderEnum_enumText || '',
|
||||
encounterBusNo: props.patientInfo?.encounterBusNo || '',
|
||||
currentDate: currentDate.value,
|
||||
// chargedItems: props.chargedItems,
|
||||
// 优先使用选中行的金额字段值(从图片中获取)
|
||||
totalAmount:
|
||||
(param.selectedRow?.receivableAmount
|
||||
? param.selectedRow.receivableAmount.toFixed(2)
|
||||
: props.totalAmount.toFixed(2)) + ' 元',
|
||||
displayAmount:
|
||||
(param.selectedRow?.receivedAmount
|
||||
? param.selectedRow.receivedAmount.toFixed(2)
|
||||
: displayAmount.value) + ' 元',
|
||||
returnedAmount: returnedAmount.value + ' 元',
|
||||
userName: userStore.nickName,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// 使用printUtils进行打印
|
||||
// 选择门诊收费打印模板并传递正确的数据格式
|
||||
console.log('[E] 最终打印数据检查:');
|
||||
console.log(' - printData.data[0]存在:', !!printData.data[0]);
|
||||
console.log(' - 关键字段:');
|
||||
console.log(' * patientName:', printData.data[0]?.patientName);
|
||||
console.log(' * regNo:', printData.data[0]?.regNo);
|
||||
console.log(' * chargeItemsList:', printData.data[0]?.chargeItemsList ? `${printData.data[0].chargeItemsList.length}条` : '无');
|
||||
console.log(' * totalAmount:', printData.data[0]?.totalAmount);
|
||||
console.log(' * currentDate:', printData.data[0]?.currentDate);
|
||||
|
||||
console.log('[F] 开始调用printUtils.print...');
|
||||
console.log(' - 模板:', 'OUTPATIENT_CHARGE');
|
||||
|
||||
await printUtils.print(PRINT_TEMPLATE.OUTPATIENT_CHARGE, printData.data[0]);
|
||||
|
||||
console.log('[G] 打印调用成功完成');
|
||||
console.log('========== 打印收费小票 - 结束 ==========');
|
||||
} catch (error) {
|
||||
console.error('[ERROR] 打印失败:', error);
|
||||
console.error('[ERROR] 错误详情:', error.message);
|
||||
console.error('[ERROR] 错误堆栈:', error.stack);
|
||||
console.log('========== 打印收费小票 - 异常结束 ==========');
|
||||
proxy.$modal.msgError('打印失败: ' + error.message);
|
||||
}
|
||||
}
|
||||
const throttledGetList = debounce(submit, 300);
|
||||
|
||||
function handleWxPay() {
|
||||
wxPay({
|
||||
txtCode: txtCode.value,
|
||||
chargeItemIds: props.chargeItemIds,
|
||||
encounterId: props.patientInfo.encounterId,
|
||||
id: props.paymentId,
|
||||
paymentDetails: formData.selfPay,
|
||||
ybMdtrtCertType: props.userCardInfo.psnCertType,
|
||||
busiCardInfo: props.userCardInfo.busiCardInfo,
|
||||
});
|
||||
}
|
||||
|
||||
function getWxPayResult() {
|
||||
WxPayResult({
|
||||
txtCode: txtCode.value,
|
||||
chargeItemIds: props.chargeItemIds,
|
||||
encounterId: props.patientInfo.encounterId,
|
||||
id: props.paymentId,
|
||||
paymentDetails: formData.selfPay,
|
||||
ybMdtrtCertType: props.userCardInfo.psnCertType,
|
||||
busiCardInfo: props.userCardInfo.busiCardInfo,
|
||||
});
|
||||
}
|
||||
|
||||
function handleOpen() {
|
||||
formData.totalAmount = props.totalAmount;
|
||||
formData.selfPay[0].amount = props.totalAmount;
|
||||
}
|
||||
|
||||
async function submit() {
|
||||
displayAmountTemp = displayAmount.value;
|
||||
|
||||
let amount = formData.selfPay
|
||||
.reduce((sum, item) => {
|
||||
return sum + (Number(item.amount) || 0);
|
||||
}, 0)
|
||||
.toFixed(2);
|
||||
if (parseFloat(amount) < parseFloat(formData.totalAmount.toFixed(2))) {
|
||||
proxy.$modal.msgError('请输入正确的结算金额');
|
||||
return;
|
||||
}
|
||||
dialogLoading.value = true;
|
||||
savePayment({
|
||||
chargeItemIds: props.chargeItemIds,
|
||||
encounterId: props.patientInfo.encounterId,
|
||||
id: props.paymentId,
|
||||
paymentDetails: formData.selfPay,
|
||||
ybMdtrtCertType: props.userCardInfo.psnCertType,
|
||||
busiCardInfo: props.userCardInfo.busiCardInfo,
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.code == 200) {
|
||||
getChargeInfo({ paymentId: props.paymentId }, { skipErrorMsg: true })
|
||||
.then((res) => {
|
||||
// 传递完整的选中数据信息到打印方法
|
||||
printReceipt({ ...res.data, chargedItems: props.chargedItems });
|
||||
})
|
||||
.catch(() => {
|
||||
// 打印失败不影响收费成功流程
|
||||
});
|
||||
formData.selfPay = [{ payEnum: 220100, amount: 0.0, payLevelEnum: 2 }];
|
||||
emit('close', 'success', res.msg);
|
||||
emit('refresh'); // 发送刷新事件给父组件
|
||||
// 长春市朝阳区中医院自动发耗材(静默执行,不阻塞主流程)
|
||||
if (userStore.fixmedinsCode == 'H22010200672' && props.consumablesIdList.length > 0) {
|
||||
dispenseMedicalConsumables(props.consumablesIdList, { skipErrorMsg: true })
|
||||
.then(() => {})
|
||||
.catch(() => {
|
||||
// 发耗材失败不影响收费成功流程
|
||||
});
|
||||
}
|
||||
} else {
|
||||
proxy.$modal.msgError(res.msg || '收费失败');
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('收费失败:', error);
|
||||
proxy.$modal.msgError(error.message || '收费失败,请重试');
|
||||
})
|
||||
.finally(() => {
|
||||
dialogLoading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
/** 打印收费结算单 */
|
||||
async function print() {
|
||||
console.log('patientInfo', props.patientInfo);
|
||||
console.log('category', props.category);
|
||||
console.log('totalAmount', props.totalAmount);
|
||||
console.log('chargeItemIds', props.chargeItemIds);
|
||||
console.log('consumablesIdList', props.consumablesIdList);
|
||||
console.log('userCardInfo', props.userCardInfo);
|
||||
console.log('paymentId', props.paymentId);
|
||||
console.log('details', props.details);
|
||||
console.log('chargedItems', props.chargedItems);
|
||||
const result = {
|
||||
data: [
|
||||
{
|
||||
name: props.patientInfo.patientName, // 姓名
|
||||
gender: props.patientInfo.genderEnum_enumText, // 性别
|
||||
age: props.patientInfo.age, // 年龄
|
||||
encounterBusNo: props.patientInfo.encounterBusNo, // 病例号
|
||||
currentDate: currentDate.value, // 收费日期
|
||||
chargedItems: props.chargedItems, // 收费项目
|
||||
totalAmount: props.totalAmount.toFixed(2) + ' 元', // 应收金额
|
||||
displayAmount: displayAmount.value + ' 元', // 实收金额
|
||||
returnedAmount: returnedAmount.value + ' 元', // 应找零
|
||||
},
|
||||
],
|
||||
};
|
||||
console.log(result, '==result.data==');
|
||||
|
||||
const printElements = JSON.parse(
|
||||
JSON.stringify(templateJson).replace(/{{HOSPITAL_NAME}}/g, userStore.hospitalName)
|
||||
);
|
||||
var hiprintTemplate = new hiprint.PrintTemplate({ template: printElements }); // 定义模板
|
||||
const printerList = hiprintTemplate.getPrinterList();
|
||||
console.log(hiprintTemplate, '打印机列表');
|
||||
hiprintTemplate.print2(result.data[0], {
|
||||
title: '门诊收费结算单',
|
||||
});
|
||||
}
|
||||
|
||||
const currentDate = ref(new Date().toLocaleString());
|
||||
|
||||
const selfPayMethods = [
|
||||
{ label: '现金', value: 220400, isWebPay: false },
|
||||
{ label: '微信', value: 220100, isWebPay: true },
|
||||
{ label: '支付宝', value: 220200, isWebPay: true },
|
||||
{ label: '银联', value: 220300, isWebPay: true },
|
||||
{ label: '优惠', value: 220500, isWebPay: false },
|
||||
];
|
||||
|
||||
// 计算剩余可输入金额
|
||||
const remainingAmount = computed(() => {
|
||||
return (
|
||||
formData.totalAmount - formData.selfPay.reduce((sum, item) => sum + Number(item.amount), 0)
|
||||
);
|
||||
});
|
||||
|
||||
// 获取单个支付方式的最大可输入金额
|
||||
const getMax = (index) => {
|
||||
const otherSum = formData.selfPay.reduce(
|
||||
(sum, item, i) => (i !== index ? sum + Number(item.amount) : sum),
|
||||
0
|
||||
);
|
||||
if (formData.selfPay[index].payEnum == 220400) {
|
||||
return formData.totalAmount + 100 - otherSum;
|
||||
}
|
||||
return formData.totalAmount - otherSum;
|
||||
};
|
||||
|
||||
// 折扣计算
|
||||
function handleDiscountChange(value) {
|
||||
let amount = props.totalAmount * Number(value);
|
||||
discountAmount.value = props.totalAmount - amount;
|
||||
formData.selfPay = [
|
||||
{ payEnum: 220100, amount: amount, payLevelEnum: 2 },
|
||||
{ payEnum: 220500, amount: discountAmount.value, payLevelEnum: 2 },
|
||||
];
|
||||
}
|
||||
|
||||
// 检查支付方式是否已使用
|
||||
const isMethodDisabled = (option) => {
|
||||
if (formData.selfPay.length > 1) {
|
||||
// 禁用已被选择的相同方式,避免重复选择
|
||||
const selectedEnums = formData.selfPay.map((item) => item.payEnum);
|
||||
if (selectedEnums.includes(option.value)) {
|
||||
return true;
|
||||
}
|
||||
// 若已经选择了任一线上支付方式,则其他线上方式不可再选,仅允许现金等线下方式
|
||||
const hasSelectedWebPay = selectedEnums.some((val) => {
|
||||
const found = selfPayMethods.find((m) => m.value === val);
|
||||
return found ? found.isWebPay === true : false;
|
||||
});
|
||||
if (hasSelectedWebPay && option.isWebPay) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const handleAmountChange = () => {
|
||||
// 不需要在这里直接设置 returnedAmount,依赖 computed 属性
|
||||
};
|
||||
|
||||
const addPayment = () => {
|
||||
if (remainingAmount.value <= 0) {
|
||||
return;
|
||||
}
|
||||
formData.selfPay.push({ payEnum: '', amount: remainingAmount.value });
|
||||
};
|
||||
|
||||
const removePayment = (index) => {
|
||||
formData.selfPay.splice(index, 1);
|
||||
};
|
||||
|
||||
const payTypeText = ref('微信');
|
||||
const payTypePlaceholder = computed(() => {
|
||||
if (payTypeText.value === '现金') {
|
||||
return '请输入现金金额';
|
||||
}
|
||||
return payTypeText.value + '支付二维码';
|
||||
});
|
||||
const clearAmount = (index, value) => {
|
||||
const selectedOption = selfPayMethods.find((item) => item.value === value);
|
||||
if (selectedOption) {
|
||||
payTypeText.value = selectedOption.label;
|
||||
}
|
||||
};
|
||||
|
||||
// 计算属性
|
||||
const displayAmount = computed(() => {
|
||||
return formData.selfPay
|
||||
.reduce((sum, item) => {
|
||||
if (item.payEnum !== 220500) {
|
||||
return sum + (Number(item.amount) || 0);
|
||||
}
|
||||
return sum;
|
||||
}, 0)
|
||||
.toFixed(2);
|
||||
});
|
||||
const returnedAmount = computed(() => {
|
||||
const display = parseFloat(displayAmount.value);
|
||||
if (isNaN(display) || display <= 0) {
|
||||
return '0.00';
|
||||
}
|
||||
const returned = display - formData.totalAmount;
|
||||
return returned >= 0 ? returned.toFixed(2) : '0.00';
|
||||
});
|
||||
|
||||
function close() {
|
||||
// unprecharge({ encounterId: props.patientInfo.encounterId }).then((res) => {
|
||||
// if (res.code == 200) {
|
||||
// emit('close');
|
||||
// } else {
|
||||
// proxy.$modal.msgError(res.message);
|
||||
// }
|
||||
// });
|
||||
formData.totalAmount = 0;
|
||||
formData.selfPay = [{ payEnum: 220100, amount: 0.0, payLevelEnum: 2 }];
|
||||
formData.medicalInsurance = {
|
||||
account: '',
|
||||
poolPay: 0,
|
||||
personalPay: 0,
|
||||
};
|
||||
|
||||
// 重置折扣相关状态
|
||||
discountRadio.value = undefined;
|
||||
discountAmount.value = 0;
|
||||
emit('close');
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
printReceipt,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
:deep(.pagination-container .el-pagination) {
|
||||
right: 20px !important;
|
||||
}
|
||||
.charge-container {
|
||||
max-width: 600px;
|
||||
margin: 20px auto;
|
||||
padding: 20px 30px;
|
||||
}
|
||||
|
||||
.header {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.amount-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.amount {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.payment-type {
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.payment-container {
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.payment-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.amount-input {
|
||||
width: 140px;
|
||||
}
|
||||
|
||||
.add-payment {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.tip {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.summary {
|
||||
margin: 25px 0;
|
||||
padding: 15px;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.summary-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
text-align: center;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
.el-text.el-text--success {
|
||||
font-size: 18px !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.el-text.el-text--warning {
|
||||
font-size: 18px !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.suffix-wrapper {
|
||||
position: relative;
|
||||
display: inline-block; /* 保持行内布局 */
|
||||
}
|
||||
|
||||
.suffix-text {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: #999;
|
||||
pointer-events: none; /* 避免点击干扰 */
|
||||
}
|
||||
|
||||
/* 调整输入框内边距 */
|
||||
.amount-input .el-input__inner {
|
||||
padding-right: 30px !important;
|
||||
}
|
||||
</style>
|
||||
433
openhis-ui-vue3/src/views/charge/cliniccharge/components/template.json
Executable file
433
openhis-ui-vue3/src/views/charge/cliniccharge/components/template.json
Executable file
@@ -0,0 +1,433 @@
|
||||
{
|
||||
"panels": [
|
||||
{
|
||||
"index": 0,
|
||||
"name": 1,
|
||||
"paperType": "自定义",
|
||||
"height": 160,
|
||||
"width": 80,
|
||||
"paperHeader": 0,
|
||||
"paperFooter": 450.7086614173229,
|
||||
"paperNumberDisabled": true,
|
||||
"paperNumberContinue": true,
|
||||
"expandCss": "",
|
||||
"overPrintOptions": {
|
||||
"content": "",
|
||||
"opacity": 0.7,
|
||||
"type": 1
|
||||
},
|
||||
"watermarkOptions": {
|
||||
"content": "",
|
||||
"fillStyle": "rgba(184, 184, 184, 0.3)",
|
||||
"fontSize": "36px",
|
||||
"rotate": 25,
|
||||
"width": 413,
|
||||
"height": 310,
|
||||
"timestamp": false,
|
||||
"format": "YYYY-MM-DD HH:mm"
|
||||
},
|
||||
"panelLayoutOptions": {
|
||||
"layoutType": "column",
|
||||
"layoutRowGap": 0,
|
||||
"layoutColumnGap": 0
|
||||
},
|
||||
"printElements": [
|
||||
{
|
||||
"options": {
|
||||
"left": 45,
|
||||
"top": 15,
|
||||
"height": 16.5,
|
||||
"width": 142.5,
|
||||
"title": "长大医院门诊收费结算单",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"fontWeight": "bold",
|
||||
"letterSpacing": 0.75,
|
||||
"textAlign": "center",
|
||||
"qrCodeLevel": 0,
|
||||
"fontSize": 12
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 15,
|
||||
"top": 39,
|
||||
"height": 14,
|
||||
"width": 80,
|
||||
"title": "姓名",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0,
|
||||
"field": "name"
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 99,
|
||||
"top": 39,
|
||||
"height": 14,
|
||||
"width": 60,
|
||||
"title": "性别",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0,
|
||||
"field": "gender"
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 163.5,
|
||||
"top": 39,
|
||||
"height": 14,
|
||||
"width": 60,
|
||||
"title": "年龄",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0,
|
||||
"field": "age"
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 15,
|
||||
"top": 60,
|
||||
"height": 14,
|
||||
"width": 120,
|
||||
"title": "病人类型",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0,
|
||||
"field": "medType"
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 13.5,
|
||||
"top": 82.5,
|
||||
"height": 14,
|
||||
"width": 120,
|
||||
"title": "病历号",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0,
|
||||
"field": "encounterBusNo"
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 13.5,
|
||||
"top": 102,
|
||||
"height": 37.5,
|
||||
"width": 208.5,
|
||||
"title": "undefined+beforeDragIn",
|
||||
"field": "chargedItems",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"textAlign": "center",
|
||||
"tableBodyRowBorder": "border",
|
||||
"tableBodyCellBorder": "border",
|
||||
"columns": [
|
||||
[
|
||||
{
|
||||
"title": "项目名称",
|
||||
"titleSync": false,
|
||||
"tableQRCodeLevel": 0,
|
||||
"tableSummaryTitle": true,
|
||||
"tableSummary": "",
|
||||
"width": 61.93559159547676,
|
||||
"field": "itemName",
|
||||
"checked": true,
|
||||
"columnId": "itemName",
|
||||
"fixed": false,
|
||||
"rowspan": 1,
|
||||
"colspan": 1
|
||||
},
|
||||
{
|
||||
"title": "单价",
|
||||
"titleSync": false,
|
||||
"tableQRCodeLevel": 0,
|
||||
"tableSummaryTitle": true,
|
||||
"tableSummary": "",
|
||||
"width": 37.1097311853845,
|
||||
"field": "unitPrice",
|
||||
"checked": true,
|
||||
"columnId": "unitPrice",
|
||||
"fixed": false,
|
||||
"rowspan": 1,
|
||||
"colspan": 1
|
||||
},
|
||||
{
|
||||
"title": "数量",
|
||||
"titleSync": false,
|
||||
"tableQRCodeLevel": 0,
|
||||
"tableSummaryTitle": true,
|
||||
"tableSummary": "",
|
||||
"width": 37.12571954521698,
|
||||
"field": "quantityValue",
|
||||
"checked": true,
|
||||
"columnId": "quantityValue",
|
||||
"fixed": false,
|
||||
"rowspan": 1,
|
||||
"colspan": 1
|
||||
},
|
||||
{
|
||||
"title": "总价",
|
||||
"titleSync": false,
|
||||
"tableQRCodeLevel": 0,
|
||||
"tableSummaryTitle": true,
|
||||
"tableSummary": "",
|
||||
"width": 35.15170328143829,
|
||||
"field": "totalPrice",
|
||||
"checked": true,
|
||||
"columnId": "totalPrice",
|
||||
"fixed": false,
|
||||
"rowspan": 1,
|
||||
"colspan": 1
|
||||
},
|
||||
{
|
||||
"title": "费用性质",
|
||||
"titleSync": false,
|
||||
"tableQRCodeLevel": 0,
|
||||
"tableSummaryTitle": true,
|
||||
"tableSummary": "",
|
||||
"width": 37.17725439248345,
|
||||
"field": "contractName",
|
||||
"checked": true,
|
||||
"columnId": "contractName",
|
||||
"fixed": false,
|
||||
"rowspan": 1,
|
||||
"colspan": 1
|
||||
},
|
||||
{
|
||||
"title": "收费名称",
|
||||
"titleSync": false,
|
||||
"tableQRCodeLevel": 0,
|
||||
"tableSummaryTitle": true,
|
||||
"tableSummary": "",
|
||||
"width": 56.86712269302148,
|
||||
"field": "chargeItem",
|
||||
"checked": false,
|
||||
"columnId": "chargeItem",
|
||||
"fixed": false,
|
||||
"rowspan": 1,
|
||||
"colspan": 1
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "表格",
|
||||
"type": "table",
|
||||
"editable": true,
|
||||
"columnDisplayEditable": true,
|
||||
"columnDisplayIndexEditable": true,
|
||||
"columnTitleEditable": true,
|
||||
"columnResizable": true,
|
||||
"columnAlignEditable": true,
|
||||
"isEnableEditField": true,
|
||||
"isEnableContextMenu": true,
|
||||
"isEnableInsertRow": true,
|
||||
"isEnableDeleteRow": true,
|
||||
"isEnableInsertColumn": true,
|
||||
"isEnableDeleteColumn": true,
|
||||
"isEnableMergeCell": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 99,
|
||||
"top": 147,
|
||||
"height": 15,
|
||||
"width": 123,
|
||||
"title": "合计金额",
|
||||
"field": "itemTotalAmount",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 6,
|
||||
"top": 171,
|
||||
"height": 14,
|
||||
"width": 108,
|
||||
"title": "应收金额",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0,
|
||||
"field": "totalAmount"
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 124.5,
|
||||
"top": 171,
|
||||
"height": 14,
|
||||
"width": 97.5,
|
||||
"title": "实收金额",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0,
|
||||
"field": "displayAmount"
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 6,
|
||||
"top": 193.5,
|
||||
"height": 14,
|
||||
"width": 108,
|
||||
"title": "全自费金额",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0,
|
||||
"field": "FULAMT_OWNPAY_AMT"
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 124.5,
|
||||
"top": 193.5,
|
||||
"height": 13.5,
|
||||
"width": 97.5,
|
||||
"title": "医保政策金额",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0,
|
||||
"field": "INSCP_SCP_AMT"
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 6,
|
||||
"top": 216,
|
||||
"height": 14,
|
||||
"width": 108,
|
||||
"title": "基金支付",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0,
|
||||
"field": "YB_FUND_PAY"
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 124.5,
|
||||
"top": 216,
|
||||
"height": 13.5,
|
||||
"width": 97.5,
|
||||
"title": "统筹支付",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0,
|
||||
"field": "YB_TC_FUND_AMOUNT"
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 6,
|
||||
"top": 240,
|
||||
"height": 14,
|
||||
"width": 216,
|
||||
"title": "个人医保账户支付",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0,
|
||||
"field": "SELF_YB_ZH_PAY"
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 6,
|
||||
"top": 268.5,
|
||||
"height": 14,
|
||||
"width": 106.5,
|
||||
"title": "收费员",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0,
|
||||
"field": "userName"
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 6,
|
||||
"top": 294,
|
||||
"height": 14,
|
||||
"width": 214.5,
|
||||
"title": "收费时间",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0,
|
||||
"field": "currentDate"
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
693
openhis-ui-vue3/src/views/charge/cliniccharge/index.vue
Executable file
693
openhis-ui-vue3/src/views/charge/cliniccharge/index.vue
Executable file
@@ -0,0 +1,693 @@
|
||||
<template>
|
||||
<div style="display: flex; justify-content: space-between" class="app-container" v-loading="readCardLoading"
|
||||
:element-loading-text="loadingText">
|
||||
<el-card style="width: 30%">
|
||||
<template #header>
|
||||
<span style="vertical-align: middle">患者列表</span>
|
||||
</template>
|
||||
<div style="width: 100%">
|
||||
<el-input v-model="queryParams.searchKey" placeholder="请输入患者名/病历号" clearable
|
||||
style="width: 48%; margin-bottom: 10px; margin-right: 10px" @keyup.enter="getPatientList">
|
||||
<template #append>
|
||||
<el-button icon="Search" @click="getPatientList" />
|
||||
</template>
|
||||
</el-input>
|
||||
<el-select v-model="queryParams.statusEnum" style="width: 48%; margin-bottom: 10px; margin-right: 10px"
|
||||
placeholder="收费状态" @change="getPatientList">
|
||||
<el-option v-for="item in chargeStatusOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
<div style="width: 100%">
|
||||
<el-date-picker v-model="receptionTime" type="daterange" range-separator="~" start-placeholder="开始时间"
|
||||
end-placeholder="结束时间" placement="bottom" value-format="YYYY-MM-DD"
|
||||
style="width: 84%; margin-bottom: 10px; margin-right: 10px" @change="getPatientList" />
|
||||
<el-button type="primary" style="margin-bottom: 10px" @click="getPatientList">
|
||||
搜索
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table ref="patientListRef" height="620" :data="patientList" row-key="encounterId" @cell-click="clickRow"
|
||||
highlight-current-row>
|
||||
<el-table-column label="病历号" align="center" prop="encounterBusNo" />
|
||||
<el-table-column label="姓名" align="center" prop="patientName" />
|
||||
<!-- <el-table-column label="时间" align="center" prop="receptionTime" width="160">
|
||||
<template #default="scope">
|
||||
{{ formatDate(scope.row.receptionTime) }}
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<el-table-column label="收费状态" align="center" prop="statusEnum_enumText" />
|
||||
</el-table>
|
||||
</div>
|
||||
</el-card>
|
||||
<div style="width: 69%">
|
||||
<el-card style="margin-bottom: 20px">
|
||||
<template #header>
|
||||
<span style="vertical-align: middle">基本信息</span>
|
||||
</template>
|
||||
<el-descriptions :column="5">
|
||||
<el-descriptions-item label="姓名:">{{ patientInfo.patientName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="性别:">
|
||||
{{ patientInfo.genderEnum_enumText }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="年龄:">{{ patientInfo.age }}</el-descriptions-item>
|
||||
<el-descriptions-item label="科室:">
|
||||
{{ patientInfo.organizationName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="就诊时间:">
|
||||
{{ formatDateStr(patientInfo.receptionTime, 'YYYY-MM-DD HH:mm:ss') }}
|
||||
</el-descriptions-item>
|
||||
<!-- <el-descriptions-item label="身份证号:">{{ patientInfo.idCard }}</el-descriptions-item> -->
|
||||
<!-- <el-descriptions-item label="手机号">{{ patientInfo.name }}</el-descriptions-item>
|
||||
<el-descriptions-item label="出生日期">{{ patientInfo.name }}</el-descriptions-item> -->
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
<el-card style="min-width: 1100px">
|
||||
<template #header>
|
||||
<span style="vertical-align: middle">收费项目</span>
|
||||
</template>
|
||||
<div style="margin-bottom: 10px">
|
||||
<el-button type="primary" @click="confirmCharge()" :disabled="buttonDisabled">
|
||||
确认收费
|
||||
</el-button>
|
||||
<el-button type="primary" plain @click="handleReadCard('01')" style="width: 65px">
|
||||
电子凭证
|
||||
</el-button>
|
||||
<el-button type="primary" plain @click="handleReadCard('02')" style="width: 65px" :disabled="true">
|
||||
身份证
|
||||
</el-button>
|
||||
<el-button type="primary" plain @click="handleReadCard('03')" style="width: 65px">
|
||||
医保卡
|
||||
</el-button>
|
||||
<el-button type="primary" @click="payToSelt()" style="margin-left: 20px" :disabled="buttonDisabled">
|
||||
医保转自费
|
||||
</el-button>
|
||||
<el-button type="primary" @click="patToMedicalInsurance()" style="margin-left: 20px"
|
||||
:disabled="buttonDisabled">
|
||||
自费转医保
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="studentPayTosStudentSelf()"
|
||||
style="margin-left: 20px"
|
||||
:disabled="buttonDisabled"
|
||||
>
|
||||
学生医保转学生自费
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="studentSelfToStudentPay()"
|
||||
style="margin-left: 20px"
|
||||
:disabled="buttonDisabled"
|
||||
>
|
||||
学生自费转学生医保
|
||||
</el-button>
|
||||
</div>
|
||||
<div style="text-align: right; padding-right: 20px; margin-bottom: 10px;">
|
||||
<span style="font-weight: bold; font-size: 14px;"
|
||||
>合计金额:{{ totalAmounts ? totalAmounts.toFixed(2) : 0 }}元</span
|
||||
>
|
||||
</div>
|
||||
<el-table
|
||||
ref="chargeListRef"
|
||||
height="530"
|
||||
:data="chargeList"
|
||||
row-key="id"
|
||||
@selection-change="handleSelectionChange"
|
||||
v-loading="chargeLoading"
|
||||
:span-method="objectSpanMethod"
|
||||
border
|
||||
>
|
||||
<el-table-column type="selection" :selectable="checkSelectable" width="55" />
|
||||
<el-table-column label="单据号" align="center" prop="busNo" width="180" />
|
||||
<el-table-column label="收费项目" align="center" prop="itemName" width="200" />
|
||||
<el-table-column label="数量" align="center" prop="quantityValue" width="80" />
|
||||
<el-table-column label="医疗类型" align="center" prop="medTypeCode_dictText" />
|
||||
<el-table-column label="医保编码" align="center" prop="ybNo" />
|
||||
<el-table-column label="费用性质" align="center" prop="contractName" />
|
||||
<el-table-column label="收费状态" align="center" prop="statusEnum_enumText" width="150">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.statusEnum === 1" disable-transitions>
|
||||
{{ scope.row.statusEnum_enumText }}
|
||||
</el-tag>
|
||||
<el-tag v-else-if="scope.row.statusEnum === 5" type="success" disable-transitions>
|
||||
{{ scope.row.statusEnum_enumText }}
|
||||
</el-tag>
|
||||
<el-tag v-else-if="scope.row.statusEnum === 8" type="danger" disable-transitions>
|
||||
{{ scope.row.statusEnum_enumText }}
|
||||
</el-tag>
|
||||
<el-tag v-else type="warning" disable-transitions>
|
||||
{{ scope.row.statusEnum_enumText }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="金额" align="right" prop="totalPrice" header-align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.totalPrice.toFixed(2) + ' 元' || '0.00' + ' 元' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="收款人" align="center" prop="entererId_dictText" />
|
||||
<el-table-column
|
||||
label="操作"
|
||||
align="center"
|
||||
fixed="right"
|
||||
header-align="center"
|
||||
class-name="no-hover-column"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
:disabled="!scope.row.paymentId"
|
||||
link
|
||||
type="primary"
|
||||
@click="printCharge(scope.row)"
|
||||
>
|
||||
打印
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<ChargeDialog
|
||||
ref="chargeDialogRef"
|
||||
:open="openDialog"
|
||||
@close="handleClose"
|
||||
:category="patientInfo.categoryEnum"
|
||||
:totalAmount="totalAmount"
|
||||
:patientInfo="patientInfo"
|
||||
:chargeItemIds="chargeItemIdList"
|
||||
:consumablesIdList="consumablesIdList"
|
||||
:chrgBchnoList="chrgBchnoList"
|
||||
:userCardInfo="userCardInfo"
|
||||
:paymentId="paymentId"
|
||||
:details="details"
|
||||
:chargedItems="chargedItems"
|
||||
:feeType="patientInfo.medfeePaymtdCode"
|
||||
:medfee_paymtd_code="medfee_paymtd_code"
|
||||
@refresh="getPatientList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="ClinicCharge">
|
||||
import {
|
||||
changeStudentPayTosStudentSelf,
|
||||
changeStudentSelfToStudentPay,
|
||||
changeToMedicalInsurance,
|
||||
changeToSelfPay,
|
||||
getChargeInfo,
|
||||
getChargeList,
|
||||
getList,
|
||||
init,
|
||||
precharge,
|
||||
} from './components/api';
|
||||
import {invokeYbPlugin5000, invokeYbPlugin5001} from '@/api/public';
|
||||
import ChargeDialog from './components/chargeDialog.vue';
|
||||
import {formatDateStr} from '@/utils';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
import Decimal from 'decimal.js';
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const userStore = useUserStore();
|
||||
const { medfee_paymtd_code } = proxy.useDict('medfee_paymtd_code');
|
||||
const queryParams = ref({
|
||||
pageNum: 1,
|
||||
pageSize: 50,
|
||||
statusEnum: 1,
|
||||
});
|
||||
|
||||
const totalAmounts = ref(0);
|
||||
const selectedRows = ref([]);
|
||||
const patientList = ref([]);
|
||||
const chargeList = ref([]);
|
||||
const chargeItemIdList = ref([]);
|
||||
const chrgBchnoList = ref([]);
|
||||
const chargeLoading = ref(false);
|
||||
const encounterId = ref('');
|
||||
const paymentId = ref('');
|
||||
const patientInfo = ref({});
|
||||
const openDialog = ref(false);
|
||||
const totalAmount = ref(0);
|
||||
const chargeListRef = ref();
|
||||
const details = ref({});
|
||||
const chargeStatusOptions = ref([]);
|
||||
const receptionTime = ref([
|
||||
formatDateStr(new Date(), 'YYYY-MM-DD'),
|
||||
formatDateStr(new Date(), 'YYYY-MM-DD'),
|
||||
]);
|
||||
const buttonDisabled = computed(() => {
|
||||
return Object.keys(patientInfo.value).length === 0;
|
||||
});
|
||||
const chargedItems = ref([]);
|
||||
|
||||
watch(
|
||||
() => selectedRows.value,
|
||||
(newVlaue) => {
|
||||
if (newVlaue && newVlaue.length > 0) {
|
||||
handleTotalAmount();
|
||||
} else {
|
||||
totalAmounts.value = 0;
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
watch(
|
||||
() => chargeList.value,
|
||||
(newVlaue) => {
|
||||
if (newVlaue && newVlaue.length > 0) {
|
||||
handleTotalAmount();
|
||||
} else {
|
||||
totalAmounts.value = 0;
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
function handleSelectionChange(selection) {
|
||||
selectedRows.value = selection;
|
||||
}
|
||||
function handleTotalAmount() {
|
||||
if (selectedRows.value.length == 0) {
|
||||
totalAmounts.value = chargeList.value.reduce((accumulator, currentRow) => {
|
||||
return new Decimal(accumulator).add(currentRow.totalPrice.toFixed(2) || 0);
|
||||
}, new Decimal(0));
|
||||
} else {
|
||||
totalAmounts.value = selectedRows.value.reduce((accumulator, currentRow) => {
|
||||
return new Decimal(accumulator).add(currentRow.totalPrice.toFixed(2) || 0);
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
getPatientList();
|
||||
initOption();
|
||||
/**
|
||||
* 患者列表
|
||||
*/
|
||||
function getPatientList() {
|
||||
if (receptionTime.value.length > 0) {
|
||||
queryParams.value.receptionTimeSTime = receptionTime.value[0] + ' 00:00:00';
|
||||
queryParams.value.receptionTimeETime = receptionTime.value[1] + ' 23:59:59';
|
||||
} else {
|
||||
queryParams.value.receptionTimeSTime = undefined;
|
||||
queryParams.value.receptionTimeETime = undefined;
|
||||
}
|
||||
getList(queryParams.value).then((res) => {
|
||||
patientList.value = res.data?.data?.records || [];
|
||||
});
|
||||
}
|
||||
|
||||
function initOption() {
|
||||
init().then((res) => {
|
||||
chargeStatusOptions.value = res.data.chargeItemStatusOptions;
|
||||
});
|
||||
}
|
||||
|
||||
function checkSelectable(row, index) {
|
||||
// 已结算时禁用选择框
|
||||
return row.statusEnum === 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击患者列表行 获取处方列表
|
||||
*/
|
||||
function clickRow(row) {
|
||||
patientInfo.value = row;
|
||||
chargeLoading.value = true;
|
||||
encounterId.value = row.encounterId;
|
||||
getChargeList(row.encounterId).then((res) => {
|
||||
chargeList.value = res.data;
|
||||
setTimeout(() => {
|
||||
chargeLoading.value = false;
|
||||
chargeListRef.value.toggleAllSelection();
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
|
||||
function handleClose(value, msg) {
|
||||
openDialog.value = false;
|
||||
if (value == 'success') {
|
||||
proxy.$modal.msgSuccess(msg);
|
||||
chargeLoading.value = true;
|
||||
getChargeList(patientInfo.value.encounterId, { skipErrorMsg: true }).then((res) => {
|
||||
chargeList.value = res.data;
|
||||
setTimeout(() => {
|
||||
chargeLoading.value = false;
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const consumablesIdList = ref([]);
|
||||
// 确认收费
|
||||
function confirmCharge() {
|
||||
let selectRows = chargeListRef.value.getSelectionRows();
|
||||
if (selectRows.length == 0) {
|
||||
proxy.$modal.msgWarning('请选择一条收费项目');
|
||||
return;
|
||||
}
|
||||
chargeItemIdList.value = selectRows.map((item) => {
|
||||
return item.id;
|
||||
});
|
||||
consumablesIdList.value = selectRows
|
||||
.filter((item) => {
|
||||
return item.serviceTable == 'wor_device_request';
|
||||
})
|
||||
.map((item) => {
|
||||
return item.id;
|
||||
});
|
||||
chargedItems.value = selectRows;
|
||||
|
||||
// 将选中的行数据赋值给chargedItems
|
||||
chargedItems.value = selectRows;
|
||||
|
||||
// totalAmount.value = selectRows.reduce((accumulator, currentRow) => {
|
||||
// return accumulator + (currentRow.totalPrice || 0);
|
||||
// }, 0);
|
||||
precharge({
|
||||
patientId: patientInfo.value.patientId,
|
||||
encounterId: patientInfo.value.encounterId,
|
||||
chargeItemIds: chargeItemIdList.value,
|
||||
}).then((res) => {
|
||||
if (res.code == 200 && res.data) {
|
||||
// totalAmount.value = res.data.psnCashPay;
|
||||
paymentId.value = res.data.paymentId;
|
||||
chrgBchnoList.value = res.data.chrgBchnoList;
|
||||
totalAmount.value = res.data.details?.find((item) => item.payEnum == 220000)?.amount ?? 0;
|
||||
details.value = res.data.details?.filter((item) => {
|
||||
return item.amount > 0;
|
||||
}) || [];
|
||||
openDialog.value = true;
|
||||
} else {
|
||||
proxy.$modal.msgError(res?.msg || '预结算失败');
|
||||
}
|
||||
});
|
||||
// console.log(patientInfo)
|
||||
}
|
||||
|
||||
let userCardInfo = ref({});
|
||||
const readCardLoading = ref(false);
|
||||
const loadingText = ref('');
|
||||
const BusiCardInfo = ref(''); // miyao
|
||||
async function handleReadCard(value) {
|
||||
// if (window.CefSharp === undefined) {
|
||||
// alert('请在医保版本中调用读卡功能!');
|
||||
// } else {
|
||||
try {
|
||||
// await CefSharp.BindObjectAsync('boundAsync');
|
||||
// string url,
|
||||
// string fixmedins_code,
|
||||
// string businessType,
|
||||
// string operatorCode,
|
||||
// string operatorName,
|
||||
// string officeId,
|
||||
// string officeName
|
||||
|
||||
// readCardLoading.value = true;
|
||||
let jsonResult;
|
||||
let cardInfo;
|
||||
let userMessage = undefined;
|
||||
switch (value) {
|
||||
case '01': // 电子凭证
|
||||
// readCardLoading.value = true;
|
||||
await invokeYbPlugin5000({
|
||||
FunctionId: 3,
|
||||
url: 'http://10.47.0.67:8089/localcfc/api/hsecfc/localQrCodeQuery',
|
||||
orgId: 'H22010200672',
|
||||
businessType: '01101',
|
||||
operatorId: userStore.id.toString(),
|
||||
operatorName: userStore.name,
|
||||
officeId: 'D83',
|
||||
officeName: '财务科',
|
||||
})
|
||||
.then((res) => {
|
||||
readCardLoading.value = true;
|
||||
loadingText.value = '正在读取...';
|
||||
jsonResult = res.data;
|
||||
})
|
||||
.catch(() => {
|
||||
readCardLoading.value = false;
|
||||
})
|
||||
.finally(() => {
|
||||
readCardLoading.value = false;
|
||||
});
|
||||
cardInfo = JSON.parse(JSON.stringify(jsonResult));
|
||||
let message = JSON.parse(cardInfo.data);
|
||||
userMessage = {
|
||||
certType: '02', // 证件类型
|
||||
certNo: message.data.idNo, // 身份证号
|
||||
psnCertType: '02', // 居民身份证
|
||||
};
|
||||
userCardInfo = {
|
||||
certType: '01', // 证件类型
|
||||
certNo: message.data.idNo, // 身份证号
|
||||
psnCertType: '01', // 居民身份证
|
||||
busiCardInfo: message.data.ecToken, // 令牌
|
||||
};
|
||||
BusiCardInfo.value = message.data.ecToken;
|
||||
console.log(BusiCardInfo.value);
|
||||
break;
|
||||
case '02':
|
||||
break;
|
||||
case '03': // 社保卡
|
||||
readCardLoading.value = true;
|
||||
loadingText.value = '正在读取...';
|
||||
await invokeYbPlugin5001(
|
||||
JSON.stringify({
|
||||
FunctionId: 1,
|
||||
IP: 'ddjk.jlhs.gov.cn',
|
||||
PORT: 20215,
|
||||
TIMEOUT: 60,
|
||||
SFZ_DRIVER_TYPE: 1,
|
||||
})
|
||||
)
|
||||
.then((res) => {
|
||||
jsonResult = JSON.stringify(res.data);
|
||||
})
|
||||
.finally(() => {
|
||||
readCardLoading.value = false;
|
||||
});
|
||||
// console.log(
|
||||
// 'jsonResult',
|
||||
// JSON.parse({
|
||||
// IssuingAreaCode: '310000',
|
||||
// SocialSecurityNumber: '371324198810224515',
|
||||
// CardNumber: 'M501A1A78',
|
||||
// CardIdentificationCode: '310000D15600000535925154E880AB97',
|
||||
// Name: '\u5218\u5CF0',
|
||||
// CardResetInfo: '00814A444686603100333E4FA9',
|
||||
// SpecificationVersion: '3.00',
|
||||
// IssuingDate: '20190313',
|
||||
// ExpirationDate: '20290313',
|
||||
// TerminalNumber: '000000000000',
|
||||
// TerminalDeviceNumber: '00041161201901000005',
|
||||
// Code: 0,
|
||||
// ErrorMessage: null,
|
||||
// })
|
||||
// );
|
||||
let message1 = JSON.parse(jsonResult);
|
||||
userMessage = {
|
||||
certType: '02', // 证件类型
|
||||
certNo: message1.SocialSecurityNumber, // 身份证号
|
||||
psnCertType: '02', // 居民身份证
|
||||
};
|
||||
userCardInfo = {
|
||||
certType: '02', // 证件类型
|
||||
certNo: message1.SocialSecurityNumber, // 身份证号
|
||||
psnCertType: '02', // 居民身份证
|
||||
busiCardInfo: message1.BusiCardInfo, //卡号
|
||||
};
|
||||
BusiCardInfo.value = message1.BusiCardInfo;
|
||||
console.log(message1.BusiCardInfo);
|
||||
break;
|
||||
case '99':
|
||||
break;
|
||||
}
|
||||
readCardLoading.value = false;
|
||||
if (userMessage.certNo) {
|
||||
let selectRows = chargeListRef.value.getSelectionRows();
|
||||
if (selectRows.length == 0) {
|
||||
proxy.$modal.msgWarning('请选择一条收费项目');
|
||||
return;
|
||||
}
|
||||
chargeItemIdList.value = selectRows.map((item) => {
|
||||
return item.id;
|
||||
});
|
||||
totalAmount.value = selectRows.reduce((accumulator, currentRow) => {
|
||||
return accumulator + (currentRow.totalPrice || 0);
|
||||
}, 0);
|
||||
precharge({
|
||||
patientId: patientInfo.value.patientId,
|
||||
encounterId: patientInfo.value.encounterId,
|
||||
chargeItemIds: chargeItemIdList.value,
|
||||
ybMdtrtCertType: userCardInfo.psnCertType,
|
||||
busiCardInfo: userCardInfo.busiCardInfo,
|
||||
}).then((res) => {
|
||||
if (res.code == 200 && res.data) {
|
||||
// totalAmount.value = res.data.psnCashPay;
|
||||
paymentId.value = res.data.paymentId;
|
||||
totalAmount.value = res.data.details?.find((item) => item.payEnum == 220000)?.amount ?? 0;
|
||||
details.value = res.data.details || [];
|
||||
// chrgBchnoList.value = res.data.chrgBchnoList;
|
||||
chargeItemIdList.value = selectRows.map((item) => {
|
||||
return item.id;
|
||||
});
|
||||
// 打印项目赋值
|
||||
chargedItems.value = selectRows;
|
||||
consumablesIdList.value = selectRows
|
||||
.filter((item) => {
|
||||
return item.serviceTable == 'wor_device_request';
|
||||
})
|
||||
.map((item) => {
|
||||
return item.id;
|
||||
});
|
||||
openDialog.value = true;
|
||||
} else {
|
||||
proxy.$modal.msgError(res?.msg || '预结算失败');
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('调用失败:', error);
|
||||
readCardLoading.value = false;
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* 医保转自费
|
||||
*/
|
||||
function payToSelt() {
|
||||
changeToSelfPay(encounterId.value).then((res) => {
|
||||
if (res.code == 200) {
|
||||
proxy.$modal.msgSuccess('操作成功');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 自费转医保
|
||||
*/
|
||||
function patToMedicalInsurance() {
|
||||
changeToMedicalInsurance(encounterId.value).then((res) => {
|
||||
if (res.code == 200) {
|
||||
proxy.$modal.msgSuccess('操作成功');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 学生医保转学生自费
|
||||
*/
|
||||
function studentPayTosStudentSelf() {
|
||||
changeStudentPayTosStudentSelf(encounterId.value).then((res) => {
|
||||
if (res.code == 200) {
|
||||
proxy.$modal.msgSuccess('操作成功');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 学生自费转学生医保
|
||||
*/
|
||||
function studentSelfToStudentPay() {
|
||||
changeStudentSelfToStudentPay(encounterId.value).then((res) => {
|
||||
if (res.code == 200) {
|
||||
proxy.$modal.msgSuccess('操作成功');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 添加行合并方法
|
||||
function objectSpanMethod({ row, column, rowIndex, columnIndex }) {
|
||||
// 只对操作列进行合并(根据列索引判断,操作列为最后一列)
|
||||
if (columnIndex === 10) {
|
||||
// 操作列索引为10(从0开始计数)
|
||||
// 如果当前行的paymentId为空,则不合并
|
||||
if (!row.paymentId) {
|
||||
return [1, 1];
|
||||
}
|
||||
|
||||
// 查找相同paymentId的连续行
|
||||
let spanCount = 1;
|
||||
if (rowIndex === 0 || chargeList.value[rowIndex - 1].paymentId !== row.paymentId) {
|
||||
// 这是具有相同paymentId的第一行,计算需要合并的行数
|
||||
for (let i = rowIndex + 1; i < chargeList.value.length; i++) {
|
||||
if (chargeList.value[i].paymentId === row.paymentId) {
|
||||
spanCount++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return [spanCount, 1];
|
||||
} else {
|
||||
// 这不是具有相同paymentId的第一行,返回0表示不显示
|
||||
return [0, 0];
|
||||
}
|
||||
}
|
||||
// 其他列不合并
|
||||
return [1, 1];
|
||||
}
|
||||
|
||||
// function printCharge(row) {
|
||||
// // 打印功能实现
|
||||
// let rows = [];
|
||||
// chargeList.value.forEach((item, index) => {
|
||||
// if (item.paymentId === row.paymentId) {
|
||||
// rows.push(item);
|
||||
// }
|
||||
// });
|
||||
// chargedItems.value = rows;
|
||||
// getChargeInfo({ paymentId: row.paymentId }).then((res) => {
|
||||
// proxy.$refs['chargeDialogRef'].printReceipt(res.data);
|
||||
// });
|
||||
// }
|
||||
function printCharge(row) {
|
||||
// 打印功能实现
|
||||
let rows = [];
|
||||
chargeList.value.forEach((item, index) => {
|
||||
if (item.paymentId === row.paymentId) {
|
||||
rows.push(item);
|
||||
}
|
||||
});
|
||||
chargedItems.value = rows;
|
||||
getChargeInfo({ paymentId: row.paymentId }).then((res) => {
|
||||
// 设置实收金额
|
||||
if (res.data && res.data.detail) {
|
||||
const amountDetail = res.data.detail?.find((item) => item.payEnum == 220000);
|
||||
if (amountDetail) {
|
||||
totalAmount.value = amountDetail.amount || 0;
|
||||
|
||||
// 为合并的行设置金额相关字段值
|
||||
rows.forEach((item) => {
|
||||
if (item.actualPrice === undefined || item.actualPrice === null) {
|
||||
item.actualPrice = 0;
|
||||
}
|
||||
if (item.discountAmount === undefined || item.discountAmount === null) {
|
||||
item.discountAmount = 0;
|
||||
}
|
||||
if (item.discountRate === undefined || item.discountRate === null) {
|
||||
item.discountRate = 100;
|
||||
}
|
||||
});
|
||||
}
|
||||
// 增强打印数据,包含选中行的完整信息
|
||||
const enhancedPrintData = {
|
||||
...res.data,
|
||||
selectedRow: row, // 添加选中行的完整数据
|
||||
chargedItems: rows, // 添加所有相关的收费项目
|
||||
};
|
||||
// 通知子组件更新内部状态
|
||||
// 通过 nextTick 确保 DOM 更新后再调用打印
|
||||
nextTick(() => {
|
||||
proxy.$refs['chargeDialogRef'].printReceipt(enhancedPrintData);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
:deep(.no-hover-column) .cell:hover {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
:deep(.el-table__body) tr:hover td.no-hover-column {
|
||||
background-color: inherit !important;
|
||||
}
|
||||
</style>
|
||||
97
openhis-ui-vue3/src/views/charge/clinicrefund/components/api.js
Executable file
97
openhis-ui-vue3/src/views/charge/clinicrefund/components/api.js
Executable file
@@ -0,0 +1,97 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
/**
|
||||
* 收费患者列表
|
||||
*/
|
||||
export function getList(queryParams) {
|
||||
return request({
|
||||
url: '/charge-manage/refund/encounter-patient-page',
|
||||
method: 'get',
|
||||
params: queryParams
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 患者退费账单
|
||||
*/
|
||||
export function getRefundList(params) {
|
||||
return request({
|
||||
url: '/charge-manage/refund/patient-refund',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 未退费账单列表
|
||||
*/
|
||||
export function getChargeItemIds(encounterId) {
|
||||
return request({
|
||||
url: '/charge-manage/refund/regenerate_charge?encounterId=' + encounterId,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 退费
|
||||
*/
|
||||
export function refund(data) {
|
||||
return request({
|
||||
url: '/payment/payment/uncharge',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
export function init() {
|
||||
return request({
|
||||
url: '/charge-manage/refund/init',
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验退药
|
||||
*/
|
||||
export function validReturnDrug(params) {
|
||||
return request({
|
||||
url: '/charge-manage/refund/verify_refund?chargeItemIdList=' + params,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取退款详情列表
|
||||
*/
|
||||
export function getReturnDetail(data) {
|
||||
return request({
|
||||
url: '/payment/payment/detail',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动退耗材
|
||||
*/
|
||||
export function renturnDispenseMedical(data) {
|
||||
return request({
|
||||
url: '/pharmacy-manage/return-medicine/medicine-return',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取退药列表
|
||||
*/
|
||||
export function getReturnMedicineList(data) {
|
||||
return request({
|
||||
url: '/pharmacy-manage/return-medicine/medicine-return-list',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
467
openhis-ui-vue3/src/views/charge/clinicrefund/components/refundDialog.vue
Executable file
467
openhis-ui-vue3/src/views/charge/clinicrefund/components/refundDialog.vue
Executable file
@@ -0,0 +1,467 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
title="确认退费"
|
||||
v-model="props.open"
|
||||
width="700px"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
@close="close"
|
||||
>
|
||||
<div>
|
||||
<el-text size="large" style="display: block; margin-bottom: 15px">
|
||||
退费日期:{{ currentDate }}
|
||||
</el-text>
|
||||
<el-text size="large">费用性质:{{ getFeeTypeText }}</el-text>
|
||||
<div class="amount-row">
|
||||
<el-text size="large">应退金额:</el-text>
|
||||
<el-text size="large" type="primary" class="amount">
|
||||
{{ props.totalAmount.toFixed(2) + ' 元' }}
|
||||
</el-text>
|
||||
</div>
|
||||
|
||||
<!-- 自费支付 -->
|
||||
<div class="payment-container">
|
||||
<div v-for="(item, index) in formData.selfPay" :key="index" class="payment-item">
|
||||
<span>退费方式:</span>
|
||||
<el-select
|
||||
v-model="item.payEnum"
|
||||
placeholder="选择退费方式"
|
||||
style="width: 160px"
|
||||
@change="clearAmount(index)"
|
||||
>
|
||||
<el-option
|
||||
v-for="payEnum in selfPayMethods"
|
||||
:key="payEnum.value"
|
||||
:label="payEnum.label"
|
||||
:value="payEnum.value"
|
||||
:disabled="isMethodDisabled(payEnum.value)"
|
||||
/>
|
||||
</el-select>
|
||||
<span>退费金额:</span>
|
||||
<div class="suffix-wrapper">
|
||||
<el-input-number
|
||||
v-model="item.amount"
|
||||
:precision="2"
|
||||
:min="0"
|
||||
:max="getMax(index)"
|
||||
:controls="false"
|
||||
placeholder="金额"
|
||||
class="amount-input"
|
||||
@change="handleAmountChange"
|
||||
/>
|
||||
<span class="suffix-text">元</span>
|
||||
</div>
|
||||
<el-button
|
||||
type="danger"
|
||||
circle
|
||||
:icon="Delete"
|
||||
@click="removePayment(index)"
|
||||
v-if="index > 0"
|
||||
/>
|
||||
</div>
|
||||
<div class="payment-container" style="position: relative">
|
||||
<span style="position: absolute; top: 5px">退费原因:</span>
|
||||
<el-input
|
||||
type="textarea"
|
||||
:rows="2"
|
||||
v-model="reason"
|
||||
placeholder="退费原因"
|
||||
class="reason-textarea"
|
||||
@change="handleAmountChange"
|
||||
/>
|
||||
</div>
|
||||
<div class="add-payment">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click="addPayment"
|
||||
:disabled="formData.selfPay.length >= 4 || remainingAmount <= 0"
|
||||
>
|
||||
添加退费方式
|
||||
</el-button>
|
||||
<el-text v-if="remainingAmount <= 0" type="danger" class="tip">
|
||||
金额已满足应退,不可继续添加
|
||||
</el-text>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<el-table :data="props.details" max-height="200" border>
|
||||
<el-table-column prop="payEnum_dictText" label="支付类型" align="center" />
|
||||
<el-table-column
|
||||
prop="amount"
|
||||
label="金额"
|
||||
header-align="center"
|
||||
align="right"
|
||||
width="200"
|
||||
>
|
||||
<template #default="scope">
|
||||
{{ scope.row.amount ? scope.row.amount + ' 元' : '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<!-- 金额汇总 -->
|
||||
<div class="summary">
|
||||
<el-space :size="30">
|
||||
<div class="summary-item">
|
||||
<el-text type="info">实退合计:</el-text>
|
||||
<el-text type="success">{{ displayAmount + ' 元' }}</el-text>
|
||||
</div>
|
||||
<!-- <div class="summary-item">
|
||||
<el-text type="info">应找零:</el-text>
|
||||
<el-text type="warning">{{ returnedAmount + ' 元' }}</el-text>
|
||||
</div> -->
|
||||
</el-space>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="submit">确 定</el-button>
|
||||
<el-button @click="close">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {getReturnMedicineList, refund, renturnDispenseMedical} from './api';
|
||||
import {computed, getCurrentInstance, reactive, ref, watch} from 'vue';
|
||||
import {Delete} from '@element-plus/icons-vue';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
const props = defineProps({
|
||||
open: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
totalAmount: {
|
||||
type: Number,
|
||||
default: 0.0,
|
||||
},
|
||||
category: {
|
||||
type: String,
|
||||
},
|
||||
paymentId: {
|
||||
type: String,
|
||||
},
|
||||
patientInfo: {
|
||||
type: Object,
|
||||
default: undefined,
|
||||
},
|
||||
chargeItemIds: {
|
||||
type: [],
|
||||
default: [],
|
||||
},
|
||||
medicineReturnList: {
|
||||
type: [],
|
||||
default: [],
|
||||
},
|
||||
details: {
|
||||
type: Object,
|
||||
default: undefined,
|
||||
},
|
||||
medfee_paymtd_code: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
feeType: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const reason = ref('');
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
const formData = reactive({
|
||||
totalAmount: 0,
|
||||
selfPay: [{ payEnum: 220100, amount: 0.0, payLevelEnum: 2 }],
|
||||
medicalInsurance: {
|
||||
account: '',
|
||||
poolPay: 0,
|
||||
personalPay: 0,
|
||||
},
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.totalAmount,
|
||||
(newValue) => {
|
||||
formData.totalAmount = newValue;
|
||||
formData.selfPay[0].amount = newValue;
|
||||
}
|
||||
);
|
||||
|
||||
const emit = defineEmits(['close']);
|
||||
|
||||
function submit() {
|
||||
console.log(props.chargeItemIds);
|
||||
console.log(
|
||||
displayAmount.value,
|
||||
parseFloat(displayAmount.value),
|
||||
formData.totalAmount,
|
||||
formData,
|
||||
'feeRefund'
|
||||
);
|
||||
//比较时,将金额都转换为两位小数的字符串再转换为浮点数,避免浮点数精度问题
|
||||
if (parseFloat(displayAmount.value) < parseFloat(formData.totalAmount.toFixed(2))) {
|
||||
proxy.$modal.msgError('请输入正确的金额');
|
||||
return;
|
||||
}
|
||||
if (userStore.fixmedinsCode == '1123123') {
|
||||
getReturnMedicineList({ encounterId: props.patientInfo.encounterId, refundStatus: 11 }).then(
|
||||
(res) => {
|
||||
let returnMedicineList = [];
|
||||
returnMedicineList = res.data
|
||||
.filter((item) => {
|
||||
return item.serviceTable == 'wor_device_request';
|
||||
})
|
||||
.map((item) => {
|
||||
return {
|
||||
requestId: item.requestId,
|
||||
dispenseId: item.dispenseId,
|
||||
tableName: 'wor_device_request',
|
||||
};
|
||||
});
|
||||
renturnDispenseMedical(returnMedicineList).then((res) => {
|
||||
if (res.code == 200) {
|
||||
refund({
|
||||
paymentEnum: 0,
|
||||
kindEnum: 1,
|
||||
patientId: props.patientInfo.patientId,
|
||||
id: props.paymentId,
|
||||
encounterId: props.patientInfo.encounterId,
|
||||
chargeItemIds: props.chargeItemIds,
|
||||
paymentDetails: formData.selfPay,
|
||||
reason: reason.value,
|
||||
ybFlag: '0',
|
||||
eleFlag: '0',
|
||||
// returnedAmount: parseFloat(returnedAmount.value),
|
||||
}).then((res) => {
|
||||
if (res.code == 200) {
|
||||
emit('close', 'success');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
} else {
|
||||
refund({
|
||||
paymentEnum: 0,
|
||||
kindEnum: 1,
|
||||
patientId: props.patientInfo.patientId,
|
||||
id: props.paymentId,
|
||||
encounterId: props.patientInfo.encounterId,
|
||||
chargeItemIds: props.chargeItemIds,
|
||||
paymentDetails: formData.selfPay,
|
||||
reason: reason.value,
|
||||
ybFlag: '0',
|
||||
eleFlag: '0',
|
||||
// returnedAmount: parseFloat(returnedAmount.value),
|
||||
}).then((res) => {
|
||||
if (res.code == 200) {
|
||||
// 长春市朝阳区中医院自动退耗材
|
||||
|
||||
emit('close', 'success');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const currentDate = ref(new Date().toLocaleString());
|
||||
|
||||
const selfPayMethods = [
|
||||
{ label: '现金', value: 220400 },
|
||||
{ label: '微信', value: 220100 },
|
||||
{ label: '支付宝', value: 220200 },
|
||||
{ label: '银联', value: 220300 },
|
||||
];
|
||||
|
||||
// 计算剩余可输入金额
|
||||
const remainingAmount = computed(() => {
|
||||
return (
|
||||
formData.totalAmount - formData.selfPay.reduce((sum, item) => sum + Number(item.amount), 0)
|
||||
);
|
||||
});
|
||||
|
||||
// 获取单个支付方式的最大可输入金额
|
||||
const getMax = (index) => {
|
||||
const otherSum = formData.selfPay.reduce(
|
||||
(sum, item, i) => (i !== index ? sum + Number(item.amount) : sum),
|
||||
0
|
||||
);
|
||||
if (formData.selfPay[index].payEnum == 220400) {
|
||||
return formData.totalAmount + 100 - otherSum;
|
||||
}
|
||||
return formData.totalAmount - otherSum;
|
||||
};
|
||||
|
||||
// 检查支付方式是否已使用
|
||||
const isMethodDisabled = (payEnum) => {
|
||||
return formData.selfPay.some((item) => item.payEnum === payEnum);
|
||||
};
|
||||
|
||||
const handleAmountChange = () => {
|
||||
// 不需要在这里直接设置 returnedAmount,依赖 computed 属性
|
||||
};
|
||||
|
||||
const addPayment = () => {
|
||||
if (remainingAmount.value <= 0) {
|
||||
return;
|
||||
}
|
||||
formData.selfPay.push({ payEnum: '', amount: remainingAmount.value });
|
||||
};
|
||||
|
||||
const removePayment = (index) => {
|
||||
formData.selfPay.splice(index, 1);
|
||||
};
|
||||
|
||||
const clearAmount = (index) => {
|
||||
// formData.selfPay[index].amount = 0;
|
||||
};
|
||||
|
||||
// 计算属性
|
||||
const displayAmount = computed(() => {
|
||||
return formData.selfPay.reduce((sum, item) => sum + (Number(item.amount) || 0), 0).toFixed(2);
|
||||
});
|
||||
|
||||
const returnedAmount = computed(() => {
|
||||
const display = parseFloat(displayAmount.value);
|
||||
if (isNaN(display) || display <= 0) {
|
||||
return '0.00';
|
||||
}
|
||||
const returned = display - formData.totalAmount;
|
||||
return returned >= 0 ? returned.toFixed(2) : '0.00';
|
||||
});
|
||||
|
||||
function close() {
|
||||
emit('close');
|
||||
}
|
||||
|
||||
// 获取费用性质文本
|
||||
const getFeeTypeText = computed(() => {
|
||||
if (!props.medfee_paymtd_code || !Array.isArray(props.medfee_paymtd_code)) {
|
||||
return '自费';
|
||||
}
|
||||
// 如果有feeType,根据feeType查找对应的文本
|
||||
if (props.feeType) {
|
||||
const dict = props.medfee_paymtd_code.find(item => item.value === props.feeType);
|
||||
return dict ? dict.label : '自费';
|
||||
}
|
||||
// 如果只有一个选项,直接返回第一个选项的文本
|
||||
if (props.medfee_paymtd_code.length === 1) {
|
||||
return props.medfee_paymtd_code[0].label || '自费';
|
||||
}
|
||||
return '自费';
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.pagination-container .el-pagination) {
|
||||
right: 20px !important;
|
||||
}
|
||||
.charge-container {
|
||||
max-width: 600px;
|
||||
margin: 20px auto;
|
||||
padding: 20px 30px;
|
||||
}
|
||||
|
||||
.header {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.amount-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.amount {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.payment-type {
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.payment-container {
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.payment-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.amount-input {
|
||||
width: 140px;
|
||||
}
|
||||
|
||||
.reason-textarea {
|
||||
margin-left: 80px;
|
||||
width: 59%;
|
||||
}
|
||||
|
||||
.add-payment {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.tip {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.summary {
|
||||
margin: 25px 0;
|
||||
padding: 15px;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.summary-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
text-align: center;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
.el-text.el-text--success {
|
||||
font-size: 18px !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.el-text.el-text--warning {
|
||||
font-size: 18px !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
.suffix-wrapper {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.suffix-text {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: #999;
|
||||
pointer-events: none; /* 避免点击干扰 */
|
||||
}
|
||||
|
||||
/* 调整输入框内边距 */
|
||||
.amount-input .el-input__inner {
|
||||
padding-right: 30px !important;
|
||||
}
|
||||
</style>
|
||||
350
openhis-ui-vue3/src/views/charge/clinicrefund/index.vue
Executable file
350
openhis-ui-vue3/src/views/charge/clinicrefund/index.vue
Executable file
@@ -0,0 +1,350 @@
|
||||
<template>
|
||||
<div style="display: flex; justify-content: space-between" class="app-container">
|
||||
<el-card style="width: 30%">
|
||||
<template #header>
|
||||
<span style="vertical-align: middle">患者列表</span>
|
||||
</template>
|
||||
<div style="width: 100%">
|
||||
<el-input
|
||||
v-model="queryParams.patientName"
|
||||
placeholder="请输入患者名"
|
||||
clearable
|
||||
style="width: 49%; margin-bottom: 10px; margin-right: 10px"
|
||||
@keyup.enter="getPatientList"
|
||||
>
|
||||
<template #append>
|
||||
<el-button icon="Search" @click="getPatientList" />
|
||||
</template>
|
||||
</el-input>
|
||||
<el-select
|
||||
v-model="queryParams.statusEnum"
|
||||
style="width: 49%; margin-bottom: 10px"
|
||||
placeholder="收费状态"
|
||||
@change="getPatientList"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in chargeOption"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-date-picker
|
||||
v-model="maxBillDate"
|
||||
type="daterange"
|
||||
range-separator="~"
|
||||
start-placeholder="开始时间"
|
||||
end-placeholder="结束时间"
|
||||
placement="bottom"
|
||||
:clearable="false"
|
||||
value-format="YYYY-MM-DD"
|
||||
style="width: 84%; margin-bottom: 10px; margin-right: 10px"
|
||||
/>
|
||||
<el-button type="primary" style="margin-bottom: 10px" @click="getPatientList">
|
||||
搜索
|
||||
</el-button>
|
||||
<el-table
|
||||
ref="patientListRef"
|
||||
height="630"
|
||||
:data="patientList"
|
||||
row-key="encounterId"
|
||||
@cell-click="clickRow"
|
||||
highlight-current-row
|
||||
width=""
|
||||
>
|
||||
<el-table-column label="病历号" align="center" prop="encounterBusNo" />
|
||||
<el-table-column label="姓名" align="center" prop="patientName" />
|
||||
<!-- <el-table-column label="时间" align="center" prop="startTime">
|
||||
<template #default="scope">
|
||||
{{ formatDate(scope.row.startTime) }}
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<el-table-column label="收费状态" align="center" prop="statusEnum_enumText" />
|
||||
</el-table>
|
||||
</div>
|
||||
</el-card>
|
||||
<div style="width: 69%">
|
||||
<el-card style="margin-bottom: 20px; height: 15%">
|
||||
<template #header>
|
||||
<span style="vertical-align: middle">基本信息</span>
|
||||
</template>
|
||||
<el-descriptions :column="4">
|
||||
<el-descriptions-item label="就诊号:">
|
||||
{{ patientInfo.encounterId }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="姓名:">
|
||||
{{ patientInfo.patientName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="性别:">
|
||||
{{ patientInfo.genderEnum_enumText }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="年龄:">
|
||||
{{ patientInfo.age }}
|
||||
</el-descriptions-item>
|
||||
<!-- <el-descriptions-item label="合同类型:">
|
||||
{{ patientInfo.categoryEnum_enumText }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="结算时间:">
|
||||
{{ patientInfo.billDate ? formatDate(patientInfo.billDate) : '' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="账单总额:">
|
||||
{{ patientInfo.totalAmount ? patientInfo.totalAmount.toFixed(2) + ' 元' : '' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="医保支付:">
|
||||
{{ patientInfo.insurancePrice }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="自费金额:">
|
||||
{{ patientInfo.selfAmount ? patientInfo.selfAmount.toFixed(2) + ' 元' : '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="支付方式:">
|
||||
{{ patientInfo.typeCode_dictText }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="发票号:">
|
||||
{{ patientInfo.idCard }}
|
||||
</el-descriptions-item> -->
|
||||
<!-- <el-descriptions-item label="手机号">{{ patientInfo.name }}</el-descriptions-item>
|
||||
<el-descriptions-item label="出生日期">{{ patientInfo.name }}</el-descriptions-item> -->
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
<el-card style="height: 83%">
|
||||
<template #header>
|
||||
<span style="vertical-align: middle">退费单据</span>
|
||||
</template>
|
||||
<!-- <el-button type="primary" @click="handleRefund()" :disabled="buttonDisabled">
|
||||
确认退费
|
||||
</el-button> -->
|
||||
<el-table
|
||||
ref="chargeListRef"
|
||||
height="510"
|
||||
:data="chargeList"
|
||||
row-key="encounterId"
|
||||
v-loading="chargeLoading"
|
||||
:span-method="spanMethod"
|
||||
class="no-hover-table"
|
||||
border
|
||||
width=""
|
||||
>
|
||||
<!-- <el-table-column type="selection" :selectable="checkSelectable" width="55" /> -->
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" @click="handleRefund(scope.row)">退费</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="paymentId" label="支付单据号" align="center" />
|
||||
<el-table-column label="项目单据号" align="center" prop="busNo" width="150" />
|
||||
<el-table-column label="项目名称" align="center" prop="itemName" />
|
||||
<el-table-column
|
||||
label="收费状态"
|
||||
align="center"
|
||||
prop="chargeStatus_enumText"
|
||||
width="100"
|
||||
/>
|
||||
<el-table-column label="数量" align="center" width="100">
|
||||
<template #default="scope">
|
||||
{{ scope.row.quantityValue + ' ' + scope.row.quantityUnit_dictText }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="付款总额"
|
||||
align="right"
|
||||
prop="totalPrice"
|
||||
header-align="center"
|
||||
width="100"
|
||||
>
|
||||
<template #default="scope">
|
||||
{{ scope.row.totalPrice.toFixed(2) + ' 元' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column label="处方号" align="center" prop="prescriptionNo" /> -->
|
||||
<el-table-column label="收款人" align="center" prop="entererName" width="120" />
|
||||
</el-table>
|
||||
</el-card>
|
||||
</div>
|
||||
<RefundDialog
|
||||
:open="openDialog"
|
||||
@close="handleClose"
|
||||
:totalAmount="totalAmount"
|
||||
:patientInfo="patientInfo"
|
||||
:paymentId="paymentId"
|
||||
:chargeItemIds="chargeItemIdList"
|
||||
:details="details"
|
||||
:medfee_paymtd_code="medfee_paymtd_code"
|
||||
:feeType="patientInfo.medfeePaymtdCode"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="ClinicCharge">
|
||||
import {getChargeItemIds, getList, getRefundList, getReturnDetail, init, validReturnDrug,} from './components/api';
|
||||
import {formatDateStr} from '@/utils/index';
|
||||
import RefundDialog from './components/refundDialog.vue';
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
// 获取费用性质字典
|
||||
const { medfee_paymtd_code } = proxy.useDict('medfee_paymtd_code');
|
||||
const queryParams = ref({
|
||||
pageNum: 1,
|
||||
pageSize: 50,
|
||||
statusEnum: 7,
|
||||
});
|
||||
const spanMap = ref({});
|
||||
const patientList = ref([]);
|
||||
const patientInfo = ref({});
|
||||
const chargeList = ref([]);
|
||||
const totalAmount = ref(0);
|
||||
const chargeOption = ref([]);
|
||||
const chargeLoading = ref(false);
|
||||
const openDialog = ref(false);
|
||||
const chargeItemIdList = ref([]);
|
||||
const details = ref({});
|
||||
const encounterId = ref('');
|
||||
const paymentId = ref('');
|
||||
const maxBillDate = ref([
|
||||
formatDateStr(new Date(), 'YYYY-MM-DD'),
|
||||
formatDateStr(new Date(), 'YYYY-MM-DD'),
|
||||
]);
|
||||
getPatientList();
|
||||
initOptions();
|
||||
/**
|
||||
* 患者列表
|
||||
*/
|
||||
function getPatientList() {
|
||||
if (maxBillDate.value.length > 0) {
|
||||
queryParams.value.maxBillDateSTime = maxBillDate.value[0] + ' 00:00:00';
|
||||
queryParams.value.maxBillDateETime = maxBillDate.value[1] + ' 23:59:59';
|
||||
} else {
|
||||
queryParams.value.maxBillDateSTime = undefined;
|
||||
queryParams.value.maxBillDateETime = undefined;
|
||||
}
|
||||
getList(queryParams.value).then((res) => {
|
||||
patientList.value = res.data.records;
|
||||
});
|
||||
}
|
||||
|
||||
function initOptions() {
|
||||
init().then((res) => {
|
||||
chargeOption.value = res.data.chargeItemStatusOptions;
|
||||
});
|
||||
}
|
||||
|
||||
// 生成合并行
|
||||
const generateSpanMap = () => {
|
||||
spanMap.value = {};
|
||||
let currentId = null;
|
||||
let startIndex = 0;
|
||||
|
||||
chargeList.value.forEach((row, index) => {
|
||||
if (row.paymentId !== currentId) {
|
||||
if (currentId !== null) {
|
||||
spanMap.value[currentId] = {
|
||||
start: startIndex,
|
||||
count: index - startIndex,
|
||||
};
|
||||
}
|
||||
currentId = row.paymentId;
|
||||
startIndex = index;
|
||||
}
|
||||
});
|
||||
|
||||
// 处理最后一个分组
|
||||
if (currentId !== null) {
|
||||
spanMap.value[currentId] = {
|
||||
start: startIndex,
|
||||
count: chargeList.value.length - startIndex,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// 合并方法(同时处理多选列和paymentId列)
|
||||
const spanMethod = ({ row, column, rowIndex, columnIndex }) => {
|
||||
if (columnIndex <= 1) {
|
||||
// 合并前两列
|
||||
const group = spanMap.value[row.paymentId];
|
||||
if (!group) return;
|
||||
|
||||
if (rowIndex === group.start) {
|
||||
return { rowspan: group.count, colspan: 1 };
|
||||
} else {
|
||||
return { rowspan: 0, colspan: 0 };
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 点击患者列表行 获取处方列表
|
||||
*/
|
||||
function clickRow(row) {
|
||||
patientInfo.value = row;
|
||||
chargeLoading.value = true;
|
||||
encounterId.value = row.encounterId;
|
||||
getRefundList({
|
||||
encounterId: row.encounterId,
|
||||
billDateSTime: maxBillDate.value[0] + ' 00:00:00',
|
||||
billDateETime: maxBillDate.value[1] + ' 23:59:59',
|
||||
}).then((res) => {
|
||||
chargeList.value = res.data;
|
||||
spanMap.value = {};
|
||||
chargeList.value.sort((a, b) => a.paymentId.localeCompare(b.paymentId));
|
||||
console.log(chargeList.value);
|
||||
generateSpanMap();
|
||||
setTimeout(() => {
|
||||
chargeLoading.value = false;
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
|
||||
function handleRefund(row) {
|
||||
// totalAmount.value = chargeList.value
|
||||
// .filter((item) => {
|
||||
// return item.paymentId === row.paymentId;
|
||||
// })
|
||||
// .reduce((accumulator, currentRow) => {
|
||||
// return new Decimal(accumulator).add(new Decimal(currentRow.totalPrice || 0));
|
||||
// }, 0);
|
||||
getReturnDetail({ id: row.paymentId }).then((res) => {
|
||||
if (res.data?.length > 0) {
|
||||
totalAmount.value =
|
||||
(res.data.find((item) => item.payEnum === 220000)?.amount ?? 0) -
|
||||
(res.data.find((item) => item.payEnum === 220500)?.amount ?? 0);
|
||||
}
|
||||
details.value = res.data?.filter((item) => {
|
||||
return item.amount > 0;
|
||||
}) || [];
|
||||
});
|
||||
paymentId.value = row.paymentId;
|
||||
patientInfo.value.patientId = row.patientId;
|
||||
getChargeItemIds(row.encounterId).then((res) => {
|
||||
chargeItemIdList.value = res.data;
|
||||
validReturnDrug(row.chargeItemIds.split(',')).then((res) => {
|
||||
if (res.code == 200) {
|
||||
openDialog.value = true;
|
||||
} else {
|
||||
proxy.$modal.msgWarning(res.msg);
|
||||
}
|
||||
});
|
||||
});
|
||||
// refund(
|
||||
// chargeList.value.map((item) => {
|
||||
// item.id;
|
||||
// })
|
||||
// ).then((res) => {
|
||||
// if (res.code == 200) {
|
||||
// proxy.$modal.msgSuccess('操作成功');
|
||||
// }
|
||||
// getPatientList();
|
||||
// });
|
||||
}
|
||||
|
||||
function handleClose(value) {
|
||||
openDialog.value = false;
|
||||
if (value == 'success') {
|
||||
proxy.$modal.msgSuccess('操作成功');
|
||||
clickRow(patientInfo.value);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
:deep(.no-hover-table) .el-table__body tr:hover > td {
|
||||
background: inherit !important;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,502 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
title="确认收费"
|
||||
v-model="props.open"
|
||||
@close="close"
|
||||
width="700px"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
>
|
||||
<div v-loading="dialogLoading">
|
||||
<el-text size="large" style="display: block; margin-bottom: 15px">
|
||||
收费日期:{{ currentDate }}
|
||||
</el-text>
|
||||
<el-text size="large">费用性质:{{ getFeeTypeText }}</el-text>
|
||||
<div class="amount-row">
|
||||
<el-text size="large">应收金额:</el-text>
|
||||
<el-text size="large" type="primary" class="amount">
|
||||
{{ props.totalAmount.toFixed(2) + ' 元' }}
|
||||
</el-text>
|
||||
</div>
|
||||
|
||||
<!-- 自费支付 -->
|
||||
<div class="payment-container">
|
||||
<div v-for="(item, index) in formData.selfPay" :key="index" class="payment-item">
|
||||
<span>支付方式:</span>
|
||||
<el-select
|
||||
v-model="item.payEnum"
|
||||
placeholder="选择支付方式"
|
||||
style="width: 160px"
|
||||
@change="clearAmount(index)"
|
||||
>
|
||||
<el-option
|
||||
v-for="payEnum in selfPayMethods"
|
||||
:key="payEnum.value"
|
||||
:label="payEnum.label"
|
||||
:value="payEnum.value"
|
||||
:disabled="isMethodDisabled(payEnum)"
|
||||
/>
|
||||
</el-select>
|
||||
<span>支付金额:</span>
|
||||
<div class="suffix-wrapper">
|
||||
<el-input-number
|
||||
v-model="item.amount"
|
||||
:precision="2"
|
||||
:min="0"
|
||||
:max="getMax(index)"
|
||||
:controls="false"
|
||||
placeholder="金额"
|
||||
class="amount-input"
|
||||
@change="handleAmountChange"
|
||||
/>
|
||||
<span class="suffix-text">元</span>
|
||||
</div>
|
||||
<el-button
|
||||
type="danger"
|
||||
circle
|
||||
:icon="Delete"
|
||||
@click="removePayment(index)"
|
||||
v-if="index > 0"
|
||||
/>
|
||||
</div>
|
||||
<div class="add-payment">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click="addPayment"
|
||||
:disabled="formData.selfPay.length >= 4 || remainingAmount <= 0"
|
||||
>
|
||||
添加支付方式
|
||||
</el-button>
|
||||
<el-text v-if="remainingAmount <= 0" type="danger" class="tip">
|
||||
金额已满足应收,不可继续添加
|
||||
</el-text>
|
||||
</div>
|
||||
</div>
|
||||
<div class="payment-item">
|
||||
<span>{{ payTypeText }}支付:</span>
|
||||
<el-input
|
||||
ref="txtCodeRef"
|
||||
v-model="txtCode"
|
||||
style="width: 300px"
|
||||
:placeholder="payTypePlaceholder"
|
||||
/>
|
||||
<el-button link type="primary" @click="handleWxPay()">扫码支付</el-button>
|
||||
<el-button link type="primary" @click="getWxPayResult()">查看结果</el-button>
|
||||
</div>
|
||||
<!-- 金额汇总 -->
|
||||
<div class="summary">
|
||||
<el-space :size="30">
|
||||
<div class="summary-item">
|
||||
<el-text type="info">实收合计:</el-text>
|
||||
<el-text type="success">{{ displayAmount + ' 元' }}</el-text>
|
||||
</div>
|
||||
<div class="summary-item">
|
||||
<el-text type="info">应找零:</el-text>
|
||||
<el-text type="warning">{{ returnedAmount + ' 元' }}</el-text>
|
||||
</div>
|
||||
</el-space>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="throttledGetList" :disabled="dialogLoading"
|
||||
>确 定</el-button
|
||||
>
|
||||
<el-button @click="close" :disabled="dialogLoading">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {savePayment, wxPay, WxPayResult} from './outpatientregistration';
|
||||
import {computed, getCurrentInstance, nextTick, reactive, ref, watch} from 'vue';
|
||||
import {Delete} from '@element-plus/icons-vue';
|
||||
import {debounce} from 'lodash-es';
|
||||
import printUtils, {PRINT_TEMPLATE, printRegistrationReceipt} from '@/utils/printUtils';
|
||||
|
||||
// 获取费用性质文本
|
||||
const getFeeTypeText = computed(() => {
|
||||
if (!props.medfee_paymtd_code || !Array.isArray(props.medfee_paymtd_code)) {
|
||||
return '';
|
||||
}
|
||||
// 如果有feeType,根据feeType查找对应的文本
|
||||
if (props.feeType) {
|
||||
const dict = props.medfee_paymtd_code.find(item => item.value === props.feeType);
|
||||
return dict ? dict.label : '';
|
||||
}
|
||||
// 如果只有一个选项,直接返回第一个选项的文本
|
||||
if (props.medfee_paymtd_code.length === 1) {
|
||||
return props.medfee_paymtd_code[0]?.label || '';
|
||||
}
|
||||
return '';
|
||||
});
|
||||
|
||||
const props = defineProps({
|
||||
open: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
totalAmount: {
|
||||
type: Number,
|
||||
default: 0.0,
|
||||
},
|
||||
patientInfo: {
|
||||
type: Object,
|
||||
default: undefined,
|
||||
},
|
||||
chargeItemIds: {
|
||||
type: [],
|
||||
default: [],
|
||||
},
|
||||
chrgBchnoList: {
|
||||
type: [],
|
||||
default: [],
|
||||
},
|
||||
chrgBchno: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
registerBusNo: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
transformedData: {
|
||||
type: Object,
|
||||
default: undefined,
|
||||
},
|
||||
orgId: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
orgName: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const dialogLoading = ref(false);
|
||||
const txtCode = ref('');
|
||||
const throttledGetList = debounce(submit, 300);
|
||||
const formData = reactive({
|
||||
totalAmount: 0,
|
||||
selfPay: [{ payEnum: 220100, amount: 0.0, payLevelEnum: 2 }],
|
||||
medicalInsurance: {
|
||||
account: '',
|
||||
poolPay: 0,
|
||||
personalPay: 0,
|
||||
},
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.totalAmount,
|
||||
(newValue) => {
|
||||
nextTick(() => {
|
||||
formData.totalAmount = newValue;
|
||||
formData.selfPay[0].amount = newValue;
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
const emit = defineEmits(['close']);
|
||||
|
||||
// 根据 printUtils 实现的打印方法 - 使用与补打挂号相同的模板 (去掉"补打"字样)
|
||||
async function printReceipt(param) {
|
||||
console.log('打印挂号收据数据:', param);
|
||||
console.log('患者信息:', props.patientInfo);
|
||||
|
||||
try {
|
||||
// 构造打印数据 - 使用与补打挂号相同的格式
|
||||
const printData = {
|
||||
patientName: props.patientInfo?.patientName || props.patientInfo?.name || '',
|
||||
cardNo: props.patientInfo?.busNo || param.busNo || '',
|
||||
idCard: param.idCard || '',
|
||||
phone: props.patientInfo?.phone || '',
|
||||
organizationName: props.orgName || props.patientInfo?.organizationName || '',
|
||||
practitionerName: props.patientInfo?.practitionerName || '',
|
||||
healthcareName: props.patientInfo?.healthcareName || '',
|
||||
visitTime: new Date().toLocaleString(),
|
||||
price: param.totalPrice || props.totalAmount || 0,
|
||||
activityPrice: 0,
|
||||
medicalRecordFee: 0,
|
||||
totalPrice: param.totalPrice || props.totalAmount || 0,
|
||||
serialNo: props.patientInfo?.encounterId || param.encounterId || '',
|
||||
encounterId: props.patientInfo?.encounterId || param.encounterId || '',
|
||||
printTime: new Date().toLocaleString(),
|
||||
};
|
||||
|
||||
console.log('printReceipt printData', printData);
|
||||
|
||||
// 使用与补打挂号相同的打印模板 (不带"补打"字样)
|
||||
await printRegistrationReceipt(printData);
|
||||
console.log('打印成功');
|
||||
} catch (error) {
|
||||
console.error('打印失败:', error);
|
||||
proxy.$modal.msgError('打印失败:' + error.message);
|
||||
}
|
||||
}
|
||||
function handleWxPay() {
|
||||
console.log('开始微信支付,当前支付详情:', formData.selfPay);
|
||||
console.log(
|
||||
'支付金额详情:',
|
||||
formData.selfPay.map((item) => ({ payEnum: item.payEnum, amount: item.amount }))
|
||||
);
|
||||
wxPay({
|
||||
txtCode: txtCode.value,
|
||||
//chargeItemIds: props.chargeItemIds,
|
||||
//encounterId: props.patientInfo.encounterId,
|
||||
id: props.paymentId,
|
||||
paymentDetails: formData.selfPay,
|
||||
// ybMdtrtCertType: props.userCardInfo.psnCertType,
|
||||
// busiCardInfo: props.userCardInfo.busiCardInfo,
|
||||
})
|
||||
.then((response) => {
|
||||
console.log('微信支付请求成功:', response);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('微信支付请求失败:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function getWxPayResult() {
|
||||
WxPayResult({
|
||||
txtCode: txtCode.value,
|
||||
chargeItemIds: props.chargeItemIds,
|
||||
encounterId: props.patientInfo.encounterId,
|
||||
id: props.paymentId,
|
||||
paymentDetails: formData.selfPay,
|
||||
ybMdtrtCertType: props.userCardInfo.psnCertType,
|
||||
busiCardInfo: props.userCardInfo.busiCardInfo,
|
||||
});
|
||||
}
|
||||
|
||||
function submit() {
|
||||
if (parseFloat(displayAmount.value) < formData.totalAmount) {
|
||||
proxy.$modal.msgError('请输入正确的结算金额');
|
||||
return;
|
||||
}
|
||||
dialogLoading.value = true;
|
||||
// 根据费用性质动态设置合同编号
|
||||
if (props.transformedData && props.transformedData.accountFormData) {
|
||||
// 直接使用传入的feeType作为contractNo
|
||||
// 如果feeType存在就使用,否则使用patientInfo中的medfeePaymtdCode,最后默认使用'0000'
|
||||
props.transformedData.accountFormData.contractNo = props.feeType || props.patientInfo?.medfeePaymtdCode || '0000';
|
||||
}
|
||||
savePayment({
|
||||
outpatientRegistrationAddParam: props.transformedData,
|
||||
chrgBchno: props.chrgBchno,
|
||||
busNo: props.registerBusNo,
|
||||
paymentDetails: formData.selfPay,
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.code == 200) {
|
||||
printReceipt(res.data);
|
||||
formData.selfPay = [{ payEnum: 220100, amount: 0.0, payLevelEnum: 2 }];
|
||||
emit('close', 'success');
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
dialogLoading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
const currentDate = ref(new Date().toLocaleString());
|
||||
|
||||
const selfPayMethods = [
|
||||
{ label: '现金', value: 220400, isWebPay: false },
|
||||
{ label: '微信', value: 220100, isWebPay: true },
|
||||
{ label: '支付宝', value: 220200, isWebPay: true },
|
||||
{ label: '银联', value: 220300, isWebPay: true },
|
||||
];
|
||||
|
||||
// 计算剩余可输入金额
|
||||
const remainingAmount = computed(() => {
|
||||
return (
|
||||
formData.totalAmount - formData.selfPay.reduce((sum, item) => sum + Number(item.amount), 0)
|
||||
);
|
||||
});
|
||||
|
||||
// 获取单个支付方式的最大可输入金额
|
||||
const getMax = (index) => {
|
||||
const otherSum = formData.selfPay.reduce(
|
||||
(sum, item, i) => (i !== index ? sum + Number(item.amount) : sum),
|
||||
0
|
||||
);
|
||||
if (formData.selfPay[index].payEnum == 220400) {
|
||||
return formData.totalAmount + 100 - otherSum;
|
||||
}
|
||||
return formData.totalAmount - otherSum;
|
||||
};
|
||||
|
||||
// 检查支付方式是否已使用
|
||||
const isMethodDisabled = (option) => {
|
||||
if (formData.selfPay.length > 1) {
|
||||
// 禁用已被选择的相同方式,避免重复选择
|
||||
const selectedEnums = formData.selfPay.map((item) => item.payEnum);
|
||||
debugger;
|
||||
if (selectedEnums.includes(option.value)) {
|
||||
return true;
|
||||
}
|
||||
// 若已经选择了任一线上支付方式,则其他线上方式不可再选,仅允许现金等线下方式
|
||||
const hasSelectedWebPay = selectedEnums.some((val) => {
|
||||
const found = selfPayMethods.find((m) => m.value === val);
|
||||
return found ? found.isWebPay === true : false;
|
||||
});
|
||||
if (hasSelectedWebPay && option.isWebPay) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
const handleAmountChange = () => {
|
||||
// 不需要在这里直接设置 returnedAmount,依赖 computed 属性
|
||||
};
|
||||
|
||||
const addPayment = () => {
|
||||
if (remainingAmount.value <= 0) {
|
||||
return;
|
||||
}
|
||||
formData.selfPay.push({ payEnum: '', amount: remainingAmount.value });
|
||||
};
|
||||
|
||||
const removePayment = (index) => {
|
||||
formData.selfPay.splice(index, 1);
|
||||
};
|
||||
const payTypeText = ref('微信');
|
||||
const payTypePlaceholder = computed(() => {
|
||||
if (payTypeText.value === '现金') {
|
||||
return '请输入现金金额';
|
||||
}
|
||||
return payTypeText.value + '支付二维码';
|
||||
});
|
||||
const clearAmount = (index) => {
|
||||
// formData.selfPay[index].amount = 0;
|
||||
const selectedOption = selfPayMethods.find(
|
||||
(item) => item.value === formData.selfPay[index].payEnum
|
||||
);
|
||||
if (selectedOption) {
|
||||
payTypeText.value = selectedOption.label;
|
||||
}
|
||||
};
|
||||
|
||||
// 计算属性
|
||||
const displayAmount = computed(() => {
|
||||
return formData.selfPay.reduce((sum, item) => sum + (Number(item.amount) || 0), 0).toFixed(2);
|
||||
});
|
||||
|
||||
const returnedAmount = computed(() => {
|
||||
const display = parseFloat(displayAmount.value);
|
||||
if (isNaN(display) || display <= 0) {
|
||||
return '0.00';
|
||||
}
|
||||
const returned = display - formData.totalAmount;
|
||||
return returned >= 0 ? returned.toFixed(2) : '0.00';
|
||||
});
|
||||
|
||||
function close() {
|
||||
//清空表单数据
|
||||
txtCode.value = '';
|
||||
emit('close', 'cancel');
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
:deep(.pagination-container .el-pagination) {
|
||||
right: 20px !important;
|
||||
}
|
||||
.charge-container {
|
||||
max-width: 600px;
|
||||
margin: 20px auto;
|
||||
padding: 20px 30px;
|
||||
}
|
||||
|
||||
.header {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.amount-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.amount {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.payment-type {
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.payment-container {
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.payment-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.amount-input {
|
||||
width: 140px;
|
||||
}
|
||||
|
||||
.add-payment {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.tip {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.summary {
|
||||
margin: 25px 0;
|
||||
padding: 15px;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.summary-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
text-align: center;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
.el-text.el-text--success {
|
||||
font-size: 18px !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.el-text.el-text--warning {
|
||||
font-size: 18px !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
.suffix-wrapper {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
.suffix-text {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: #999;
|
||||
pointer-events: none; /* 避免点击干扰 */
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,265 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 查询初期所需数据
|
||||
export function getInit() {
|
||||
return request({
|
||||
url: '/charge-manage/register/init',
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
// 查询患者信息
|
||||
export function getOutpatientRegistrationList(query) {
|
||||
return request({
|
||||
url: '/charge-manage/register/patient-metadata',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
// 查询费用性质
|
||||
export function getContractList() {
|
||||
return request({
|
||||
url: '/app-common/contract-list',
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
// 查询诊断信息
|
||||
export function getConditionDefinitionMetadata(query) {
|
||||
return request({
|
||||
url: '/charge-manage/register/condition-definition-metadata',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
// // 查询就诊位置
|
||||
// export function getLocationTree(query) {
|
||||
// return request({
|
||||
// url: '/charge-manage/register/location-tree',
|
||||
// method: 'get',
|
||||
// params: query
|
||||
// })
|
||||
// }
|
||||
|
||||
// 查询就诊科室
|
||||
export function getLocationTree(query) {
|
||||
return request({
|
||||
url: '/charge-manage/register/org-list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
// 根据位置id筛选医生
|
||||
export function getPractitionerMetadata(query) {
|
||||
return request({
|
||||
url: '/charge-manage/register/practitioner-metadata',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
// 根据机构id筛选服务项目
|
||||
export function getHealthcareMetadata(query) {
|
||||
return request({
|
||||
url: '/charge-manage/register/healthcare-metadata',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
// 更新患者手机号
|
||||
export function updatePatientPhone(data) {
|
||||
return request({
|
||||
url: '/patient-manage/information/update-patient-phone',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
// 门诊挂号查询
|
||||
export function getOutpatientRegistrationCurrent(query) {
|
||||
return request({
|
||||
url: '/charge-manage/register/current-day-encounter',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
// 新增门诊挂号信息
|
||||
export function addOutpatientRegistration(data) {
|
||||
return request({
|
||||
url: '/payment/payment/reg-pre-pay',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
// 新增病人信息
|
||||
export function addPatient(data) {
|
||||
return request({
|
||||
url: '/patient-manage/information/patient-information',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
export function listmaritalstatus() {
|
||||
return request({
|
||||
url: '/patientmanage/information/list-maritalstatus',
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
export function listoccupationtype() {
|
||||
return request({
|
||||
url: '/patientmanage/information/list-occupationtype',
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
export function lisadministrativegender() {
|
||||
return request({
|
||||
url: '/patientmanage/information/list-administrativegender',
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
export function listbloodtypeabo() {
|
||||
return request({
|
||||
url: '/patientmanage/information/list-bloodtypeabo',
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
export function listbloodtypearh() {
|
||||
return request({
|
||||
url: '/patientmanage/information/list-bloodtypearh',
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
export function listfamilyrelationshiptype() {
|
||||
return request({
|
||||
url: '/patientmanage/information/list-familyrelationshiptype',
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
// 查询患者相关
|
||||
export function patientlLists() {
|
||||
return request({
|
||||
url: '/patient-manage/information/init',
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
// 患者退号
|
||||
export function returnRegister(encounterId) {
|
||||
return request({
|
||||
url: '/charge-manage/register/return?encounterId=' + encounterId,
|
||||
method: 'put',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 收费
|
||||
*/
|
||||
export function savePayment(data) {
|
||||
return request({
|
||||
url: '/payment/payment/reg-pay',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 收费预结算
|
||||
*/
|
||||
export function precharge(data) {
|
||||
return request({
|
||||
url: '/payment/payment/precharge',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 退费
|
||||
*/
|
||||
export function refund(data) {
|
||||
return request({
|
||||
url: '/payment/payment/uncharge',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 退费预检(挂号预取消)
|
||||
* GET /payment/payment/pre-cancel-reg?encounterId=xxx
|
||||
*/
|
||||
export function preCancelReg(encounterId) {
|
||||
return request({
|
||||
url: '/payment/payment/pre-cancel-reg',
|
||||
method: 'get',
|
||||
params: { encounterId },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消挂号
|
||||
*/
|
||||
export function cancelRegister(data) {
|
||||
return request({
|
||||
url: '/charge-manage/register/return',
|
||||
method: 'put',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
export function gerPreInfo(userMaessage) {
|
||||
return request({
|
||||
url: '/yb-request/per-info',
|
||||
method: 'post',
|
||||
params: userMaessage,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信支付
|
||||
*/
|
||||
export function wxPay(data) {
|
||||
return request({
|
||||
url: '/three-part/pay/pay-for',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信支付
|
||||
*/
|
||||
export function WxPayResult(data) {
|
||||
return request({
|
||||
url: '/three-part/pay/pay-query',
|
||||
method: 'get',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 补打挂号
|
||||
*/
|
||||
export function reprintRegistration(data) {
|
||||
return request({
|
||||
url: '/charge-manage/register/reprint',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,184 @@
|
||||
<template>
|
||||
<!-- <div class="app-container"> -->
|
||||
<el-dialog :title="title" v-model="visible" width="800px" append-to-body>
|
||||
<el-table
|
||||
:data="patientInfoList"
|
||||
@selection-change="handleSelectionChange"
|
||||
width="90%"
|
||||
@cell-dblclick="handleCellDblClick"
|
||||
>
|
||||
<el-table-column type="selection" width="50" align="center" />
|
||||
<el-table-column
|
||||
label="患者姓名"
|
||||
align="center"
|
||||
key="name"
|
||||
prop="name"
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
<el-table-column
|
||||
label="性别"
|
||||
align="center"
|
||||
key="genderEnum_enumText"
|
||||
prop="genderEnum_enumText"
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
<el-table-column
|
||||
label="身份证号"
|
||||
align="center"
|
||||
key="idCard"
|
||||
prop="idCard"
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
<el-table-column
|
||||
label="电话"
|
||||
align="center"
|
||||
key="phone"
|
||||
prop="phone"
|
||||
:show-overflow-tooltip="true"
|
||||
width="100"
|
||||
/>
|
||||
<el-table-column
|
||||
label="生日"
|
||||
align="center"
|
||||
key="birthDate"
|
||||
prop="birthDate"
|
||||
:show-overflow-tooltip="true"
|
||||
width="50"
|
||||
/>
|
||||
<el-table-column
|
||||
label="年龄"
|
||||
align="center"
|
||||
key="age"
|
||||
:show-overflow-tooltip="true"
|
||||
>
|
||||
<template #default="scope">
|
||||
{{ scope.row.age ? `${scope.row.age}岁` : '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<!-- </div> -->
|
||||
</template>
|
||||
|
||||
<script setup name="PatientInfoDialog">
|
||||
import {getOutpatientRegistrationList,} from "./outpatientregistration";
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
|
||||
const patientInfoList = ref([]);
|
||||
const selectedData = ref([]); // 存储选择的行数据
|
||||
const single = ref(true);
|
||||
const multiple = ref(true);
|
||||
const total = ref(0);
|
||||
const title = ref("病人信息");
|
||||
const visible = ref(false);
|
||||
const emits = defineEmits(['submit']); // 声明自定义事件
|
||||
|
||||
const data = reactive({
|
||||
form: {},
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
searchKey: undefined, // 品名/商品名/英文品名/编码/拼音
|
||||
},
|
||||
rules: {},
|
||||
});
|
||||
|
||||
const { queryParams, form, rules } = toRefs(data);
|
||||
|
||||
const props = defineProps({
|
||||
patientInfoData: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({}), // 提供默认值
|
||||
},
|
||||
searchInfo: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: "",
|
||||
},
|
||||
});
|
||||
|
||||
// 显示弹框
|
||||
function show() {
|
||||
patientInfoList.value = props.patientInfoData.records;
|
||||
total.value = props.patientInfoData.total;
|
||||
console.log(props.patientInfoData, "props.patientInfoData");
|
||||
visible.value = true;
|
||||
}
|
||||
|
||||
/** 查询病种目录列表 */
|
||||
function getList() {
|
||||
const query = {
|
||||
searchKey: props.searchInfo,
|
||||
pageNo: queryParams.value.pageNo,
|
||||
pageSize: queryParams.value.pageSize,
|
||||
};
|
||||
getOutpatientRegistrationList(query).then((res) => {
|
||||
if (res.data.records.length > 0) {
|
||||
patientInfoList.value = res.data.records;
|
||||
total.value = res.data.total;
|
||||
console.log(patientInfoList.value, "patientInfoList.value");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** 选择条数 */
|
||||
function handleSelectionChange(selection) {
|
||||
console.log(selection, "selection");
|
||||
selectedData.value = selection.map((item) => ({ ...item })); // 存储选择的行数据
|
||||
single.value = selection.length != 1;
|
||||
multiple.value = !selection.length;
|
||||
}
|
||||
|
||||
/** 取消按钮 */
|
||||
function cancel() {
|
||||
visible.value = false;
|
||||
patientInfoList.value = [];
|
||||
}
|
||||
|
||||
/** 提交按钮 */
|
||||
function submitForm() {
|
||||
if (selectedData.value.length > 1) {
|
||||
proxy.$modal.msgSuccess("只能选中一条数据操作!");
|
||||
} else if (selectedData.value.length === 1) {
|
||||
console.log(selectedData.value[0], "selectedData.value");
|
||||
const data = selectedData.value[0];
|
||||
// 将表单数据发送给父组件
|
||||
emits("submit", data);
|
||||
}
|
||||
visible.value = false;
|
||||
}
|
||||
// 双击数据时触发的方法
|
||||
function handleCellDblClick(row, column, cell, event) {
|
||||
emits("submit", row);
|
||||
visible.value = false;
|
||||
// 获取整条数据
|
||||
console.log('双击的行数据:', row);
|
||||
// 根据需求进行进一步操作
|
||||
}
|
||||
defineExpose({
|
||||
show,
|
||||
});
|
||||
</script>
|
||||
<style scoped>
|
||||
.el-form--inline .el-form-item {
|
||||
display: inline-flex;
|
||||
vertical-align: middle;
|
||||
margin-right: 10px !important;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-table
|
||||
height="400"
|
||||
:data="patientList"
|
||||
row-key="id"
|
||||
@cell-click="clickRow"
|
||||
>
|
||||
<el-table-column label="姓名" align="center" prop="name" />
|
||||
<el-table-column label="就诊卡号" align="center" prop="identifierNo" />
|
||||
<el-table-column label="性别" align="center" prop="genderEnum_enumText" />
|
||||
<el-table-column label="证件号" align="center" prop="idCard" />
|
||||
<el-table-column label="联系电话" align="center" prop="phone" />
|
||||
<el-table-column label="年龄" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.age ? `${scope.row.age}` : '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {getOutpatientRegistrationList} from "./outpatientregistration";
|
||||
|
||||
const props = defineProps({
|
||||
searchkey: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["selsectPatient"]);
|
||||
const total = ref(0);
|
||||
const queryParams = ref({
|
||||
pageNum: 1,
|
||||
pageSize: 50,
|
||||
});
|
||||
const patientList = ref([]);
|
||||
|
||||
watch(
|
||||
() => props.searchkey,
|
||||
(newValue) => {
|
||||
queryParams.value.searchKey = newValue;
|
||||
getList();
|
||||
},
|
||||
{ immdiate: true }
|
||||
);
|
||||
|
||||
getList();
|
||||
function getList() {
|
||||
getOutpatientRegistrationList(queryParams.value).then((res) => {
|
||||
patientList.value = res.data.records;
|
||||
total.value = res.data.total;
|
||||
});
|
||||
}
|
||||
|
||||
function clickRow(row) {
|
||||
emit("selsectPatient", row);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,525 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:title="eventType == '1' ? '确认退费' : '挂号详情'"
|
||||
v-model="props.open"
|
||||
width="700px"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
@close="close"
|
||||
>
|
||||
<div v-loading="loading">
|
||||
<el-text size="large" style="display: block; margin-bottom: 15px">
|
||||
退费日期:{{ currentDate }}
|
||||
</el-text>
|
||||
<el-text size="large">费用性质:{{ props.category || '自费' }}</el-text>
|
||||
<div class="amount-row">
|
||||
<el-text size="large">应退金额:</el-text>
|
||||
<el-text size="large" type="primary" class="amount">
|
||||
{{ (calculatedTotalAmount || 0) + ' 元' }}
|
||||
</el-text>
|
||||
</div>
|
||||
<div class="amount-row" v-if="calculatedReturnAmount > 0">
|
||||
<el-text size="large">退费金额:</el-text>
|
||||
<el-text size="large" type="primary" class="amount">
|
||||
{{ (calculatedReturnAmount || 0) + ' 元' }}
|
||||
</el-text>
|
||||
</div>
|
||||
|
||||
<!-- 退费方式列表(从接口数据中筛选) -->
|
||||
<div class="payment-container">
|
||||
<div v-for="(item, index) in refundMethodsFromApi" :key="index" class="payment-item">
|
||||
<span>退费方式:</span>
|
||||
<el-input :value="getPayMethodLabel(item.payEnum)" readonly style="width: 160px" />
|
||||
<span>退费金额:</span>
|
||||
<div class="suffix-wrapper">
|
||||
<el-input-number
|
||||
:model-value="(Number(item.amount) || 0) - (Number(item.returnAmount) || 0)"
|
||||
:precision="2"
|
||||
:controls="false"
|
||||
disabled
|
||||
class="amount-input"
|
||||
/>
|
||||
<span class="suffix-text">元</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="payment-container" style="position: relative">
|
||||
<span style="position: absolute; top: 5px">退费原因:</span>
|
||||
<el-input
|
||||
type="textarea"
|
||||
:rows="2"
|
||||
v-model="reason"
|
||||
placeholder="退费原因"
|
||||
class="reason-textarea"
|
||||
:disabled="eventType == '1' ? false : true"
|
||||
/>
|
||||
</div>
|
||||
<!-- 添加退费方式功能暂时注释 -->
|
||||
<!-- <div class="add-payment">
|
||||
<el-button type="primary" plain @click="addPayment" :disabled="canAddPayment">
|
||||
添加退费方式
|
||||
</el-button>
|
||||
<el-text v-if="canAddPayment" type="danger" class="tip">
|
||||
退费金额已等于应退金额,不可继续添加
|
||||
</el-text>
|
||||
</div> -->
|
||||
</div>
|
||||
<!-- 金额汇总 -->
|
||||
<div class="summary">
|
||||
<el-space :size="30">
|
||||
<div class="summary-item">
|
||||
<el-text type="info">实退合计:</el-text>
|
||||
<el-text type="success">{{
|
||||
displayAmount > 0 ? displayAmount + ' 元' : props.totalAmount + ' 元'
|
||||
}}</el-text>
|
||||
</div>
|
||||
<!-- <div class="summary-item">
|
||||
<el-text type="info">应找零:</el-text>
|
||||
<el-text type="warning">{{ returnedAmount + ' 元' }}</el-text>
|
||||
</div> -->
|
||||
</el-space>
|
||||
</div>
|
||||
|
||||
<!-- 退费明细表格 -->
|
||||
<div v-if="preCancelData && preCancelData.length > 0" class="pre-cancel-table-wrapper">
|
||||
<el-table :data="preCancelData" border stripe max-height="300" style="width: 100%">
|
||||
<el-table-column prop="payEnum_dictText" label="支付方式" min-width="200" />
|
||||
<el-table-column prop="amount" label="金额" width="120" align="right">
|
||||
<template #default="{ row }">
|
||||
{{ row.amount ? Number(row.amount) : '0.00' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="returnAmount" label="退费金额" width="120" align="right">
|
||||
<template #default="{ row }">
|
||||
{{ row.returnAmount ? Number(row.returnAmount) : '0.00' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="chargeAmount" label="收费金额" min-width="120" align="right">
|
||||
<template #default="{ row }">
|
||||
{{ row.chargeAmount ? Number(row.chargeAmount) : '0.00' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button v-if="eventType == 1" type="primary" @click="submit">确 定</el-button>
|
||||
<el-button @click="close">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {cancelRegister, preCancelReg} from './outpatientregistration';
|
||||
import {computed, getCurrentInstance, reactive, ref, watch} from 'vue';
|
||||
import useUserStore from '@/store/modules/user.js'
|
||||
//获取当前登陆用户的信息
|
||||
const userStore = useUserStore();
|
||||
|
||||
// 获取费用性质文本
|
||||
const getFeeTypeText = computed(() => {
|
||||
// 优先使用从挂号记录传递过来的费用性质名称
|
||||
if (props.contractName) {
|
||||
return props.contractName;
|
||||
}
|
||||
|
||||
// 如果没有传递名称,则根据费用性质代码查找
|
||||
if (props.feeType && props.medfee_paymtd_code && Array.isArray(props.medfee_paymtd_code)) {
|
||||
const dictItem = props.medfee_paymtd_code.find(item => item.value === props.feeType);
|
||||
return dictItem ? dictItem.label : '自费';
|
||||
}
|
||||
|
||||
return '自费'; // 默认值
|
||||
});
|
||||
|
||||
const props = defineProps({
|
||||
open: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
totalAmount: {
|
||||
type: Number,
|
||||
default: 0.0,
|
||||
},
|
||||
category: {
|
||||
type: String,
|
||||
},
|
||||
paymentId: {
|
||||
type: String,
|
||||
},
|
||||
patientInfo: {
|
||||
type: Object,
|
||||
default: undefined,
|
||||
},
|
||||
chargeItemIds: {
|
||||
type: [],
|
||||
default: [],
|
||||
},
|
||||
eventType: {
|
||||
type: String,
|
||||
default: 1,
|
||||
},
|
||||
});
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const reason = ref('');
|
||||
const preCancelData = ref([]);
|
||||
const loading = ref(false);
|
||||
|
||||
const formData = reactive({
|
||||
totalAmount: 0,
|
||||
selfPay: [{ payEnum: 220100, amount: 0.0, payLevelEnum: 2 }],
|
||||
medicalInsurance: {
|
||||
account: '',
|
||||
poolPay: 0,
|
||||
personalPay: 0,
|
||||
},
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.totalAmount,
|
||||
(newValue) => {
|
||||
formData.totalAmount = newValue;
|
||||
formData.selfPay[0].amount = newValue;
|
||||
}
|
||||
);
|
||||
|
||||
const emit = defineEmits(['close']);
|
||||
|
||||
watch(
|
||||
() => props.open,
|
||||
async (val) => {
|
||||
if (val && props.patientInfo && props.patientInfo.encounterId) {
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await preCancelReg(props.patientInfo.encounterId);
|
||||
if (res && res.code === 200 && res.data) {
|
||||
preCancelData.value = res.data;
|
||||
// 计算应退金额并更新表单数据
|
||||
const targetPayEnums = [220500, 220400, 220100, 220200, 220300];
|
||||
const sum = res.data
|
||||
?.filter((item) => targetPayEnums.includes(item.payEnum))
|
||||
.reduce((total, item) => total + (Number(item.amount) || 0), 0);
|
||||
if (sum > 0) {
|
||||
formData.totalAmount = sum;
|
||||
// 如果第一个退费方式的金额为0或等于原来的totalAmount,则自动填充
|
||||
if (
|
||||
formData.selfPay[0].amount === 0 ||
|
||||
formData.selfPay[0].amount === props.totalAmount
|
||||
) {
|
||||
formData.selfPay[0].amount = sum;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('pre-cancel-reg error', err);
|
||||
preCancelData.value = [];
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
} else {
|
||||
preCancelData.value = [];
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
function submit() {
|
||||
console.log(props.chargeItemIds);
|
||||
|
||||
// if (parseFloat(displayAmount.value) < formData.totalAmount) {
|
||||
// proxy.$modal.msgError('请输入正确的金额');
|
||||
// return;
|
||||
// }
|
||||
cancelRegister({
|
||||
paymentEnum: 0,
|
||||
kindEnum: 1,
|
||||
patientId: props.patientInfo.patientId,
|
||||
id: props.paymentId,
|
||||
encounterId: props.patientInfo.encounterId,
|
||||
chargeItemIds: [],
|
||||
paymentDetails: formData.selfPay,
|
||||
reason: reason.value,
|
||||
ybFlag: '1',
|
||||
eleFlag: '0',
|
||||
// 退号操作记录信息
|
||||
returnDate: new Date().toISOString(), // 退号操作日期
|
||||
operatorId: userStore.id, // 退号操作工号(用户ID)
|
||||
operatorName: userStore.name, // 退号操作人姓名
|
||||
refundAmount: calculatedTotalAmount.value, // 退款金额
|
||||
// 原挂号信息
|
||||
registerTime: props.registerInfo?.registerTime || '', // 原挂号时间
|
||||
registerAmount: props.registerInfo?.totalPrice || props.totalAmount, // 原挂号金额
|
||||
// 患者信息
|
||||
patientName: props.registerInfo?.patientName || '', // 患者姓名
|
||||
patientAge: props.registerInfo?.age || '', // 患者年龄
|
||||
patientGender: props.registerInfo?.genderEnum_enumText || '', // 患者性别
|
||||
// returnedAmount: parseFloat(returnedAmount.value),
|
||||
}).then((res) => {
|
||||
if (res.code == 200) {
|
||||
emit('close', 'success');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const currentDate = ref(new Date().toLocaleString());
|
||||
|
||||
const selfPayMethods = [
|
||||
{ label: '现金', value: 220400 },
|
||||
{ label: '微信', value: 220100 },
|
||||
{ label: '支付宝', value: 220200 },
|
||||
{ label: '银联', value: 220300 },
|
||||
];
|
||||
|
||||
const getMax = (index) => {
|
||||
const otherSum = formData.selfPay.reduce(
|
||||
(sum, item, i) => (i !== index ? sum + (Number(item.amount) || 0) : sum),
|
||||
0
|
||||
);
|
||||
const maxAmount = calculatedTotalAmount.value - otherSum;
|
||||
if (formData.selfPay[index].payEnum == 220400) {
|
||||
return maxAmount + 100;
|
||||
}
|
||||
return maxAmount;
|
||||
};
|
||||
|
||||
// 检查支付方式是否已使用
|
||||
const isMethodDisabled = (payEnum) => {
|
||||
return formData.selfPay.some((item) => item.payEnum === payEnum);
|
||||
};
|
||||
|
||||
const handleAmountChange = () => {
|
||||
// 不需要在这里直接设置 returnedAmount,依赖 computed 属性
|
||||
};
|
||||
|
||||
const addPayment = () => {
|
||||
if (canAddPayment.value) {
|
||||
return;
|
||||
}
|
||||
// 添加新的退费方式,初始金额为0,由用户输入
|
||||
formData.selfPay.push({ payEnum: '', amount: 0 });
|
||||
};
|
||||
|
||||
const removePayment = (index) => {
|
||||
formData.selfPay.splice(index, 1);
|
||||
};
|
||||
|
||||
const clearAmount = (index) => {
|
||||
// formData.selfPay[index].amount = 0;
|
||||
};
|
||||
|
||||
// 计算属性 - 实退合计(使用接口返回的退费方式数据)
|
||||
const displayAmount = computed(() => {
|
||||
if (!preCancelData.value || preCancelData.value.length === 0) {
|
||||
return '0.00';
|
||||
}
|
||||
const targetPayEnums = [220500, 220400, 220100, 220200, 220300];
|
||||
const sum = preCancelData.value
|
||||
?.filter((item) => targetPayEnums.includes(item.payEnum))
|
||||
.reduce((sum, item) => sum + (Number(item.amount) || 0), 0);
|
||||
return sum?.toFixed(2) ?? '0.00';
|
||||
});
|
||||
|
||||
const returnedAmount = computed(() => {
|
||||
const display = parseFloat(displayAmount.value);
|
||||
if (isNaN(display) || display <= 0) {
|
||||
return '0.00';
|
||||
}
|
||||
const returned = display - formData.totalAmount;
|
||||
return returned >= 0 ? returned.toFixed(2) : '0.00';
|
||||
});
|
||||
|
||||
const calculatedTotalAmount = computed(() => {
|
||||
if (!preCancelData.value || preCancelData.value.length === 0) {
|
||||
return props.totalAmount || 0;
|
||||
}
|
||||
const targetPayEnums = [220500, 220400, 220100, 220200, 220300];
|
||||
// 应退金额 = (amount - returnAmount) 的总和,即剩余应退金额
|
||||
const sum = preCancelData.value
|
||||
?.filter((item) => targetPayEnums.includes(item.payEnum))
|
||||
.reduce(
|
||||
(total, item) => total + ((Number(item.amount) || 0) - (Number(item.returnAmount) || 0)),
|
||||
0
|
||||
);
|
||||
return sum > 0 ? sum : props.totalAmount || 0;
|
||||
});
|
||||
|
||||
const calculatedReturnAmount = computed(() => {
|
||||
if (!preCancelData.value || preCancelData.value.length === 0) {
|
||||
return 0;
|
||||
}
|
||||
const targetPayEnums = [220500, 220400, 220100, 220200, 220300];
|
||||
const sum = preCancelData.value
|
||||
?.filter((item) => targetPayEnums.includes(item.payEnum))
|
||||
.reduce((total, item) => total + (Number(item.returnAmount) || 0), 0);
|
||||
return sum || 0;
|
||||
});
|
||||
|
||||
// 从接口数据中筛选符合条件的退费方式
|
||||
const refundMethodsFromApi = computed(() => {
|
||||
if (!preCancelData.value || preCancelData.value.length === 0) {
|
||||
return [];
|
||||
}
|
||||
const targetPayEnums = [220500, 220400, 220100, 220200, 220300];
|
||||
return preCancelData.value?.filter(
|
||||
(item) =>
|
||||
targetPayEnums.includes(item.payEnum) &&
|
||||
item.payEnum_dictText &&
|
||||
item.payEnum_dictText.trim() !== ''
|
||||
) || [];
|
||||
});
|
||||
|
||||
// 根据 payEnum 获取支付方式标签
|
||||
const getPayMethodLabel = (payEnum) => {
|
||||
const method = selfPayMethods.find((m) => m.value === payEnum);
|
||||
if (method) {
|
||||
return method.label;
|
||||
}
|
||||
// 如果找不到,尝试从接口返回的 dictText 中获取
|
||||
const apiItem = preCancelData.value?.find((item) => item.payEnum === payEnum);
|
||||
return apiItem?.payEnum_dictText || `支付方式${payEnum}`;
|
||||
};
|
||||
|
||||
// 计算所有退费方式的总和
|
||||
const totalRefundAmount = computed(() => {
|
||||
return refundMethodsFromApi.value?.reduce((sum, item) => sum + (Number(item.amount) || 0), 0) ?? 0;
|
||||
});
|
||||
|
||||
// 计算剩余可输入金额(应退金额 - 已输入的退费金额总和)
|
||||
const remainingAmount = computed(() => {
|
||||
return calculatedTotalAmount.value - totalRefundAmount.value;
|
||||
});
|
||||
|
||||
// 判断是否可以添加退费方式:退费金额总和等于或大于应退金额时不能添加
|
||||
const canAddPayment = computed(() => {
|
||||
return totalRefundAmount.value >= calculatedTotalAmount.value || formData.selfPay.length >= 10;
|
||||
});
|
||||
|
||||
function close() {
|
||||
emit('close');
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.pagination-container .el-pagination) {
|
||||
right: 20px !important;
|
||||
}
|
||||
.charge-container {
|
||||
max-width: 600px;
|
||||
margin: 20px auto;
|
||||
padding: 20px 30px;
|
||||
}
|
||||
|
||||
.header {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.amount-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.amount {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.payment-type {
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.payment-container {
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.payment-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.amount-input {
|
||||
width: 140px;
|
||||
}
|
||||
|
||||
.add-payment {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
.reason-textarea {
|
||||
margin-left: 80px;
|
||||
width: 59%;
|
||||
}
|
||||
.tip {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.summary {
|
||||
margin: 25px 0;
|
||||
padding: 15px;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.summary-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
text-align: center;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
.el-text.el-text--success {
|
||||
font-size: 18px !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.el-text.el-text--warning {
|
||||
font-size: 18px !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
.suffix-wrapper {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.suffix-text {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: #999;
|
||||
pointer-events: none; /* 避免点击干扰 */
|
||||
}
|
||||
|
||||
/* 调整输入框内边距 */
|
||||
.amount-input .el-input__inner {
|
||||
padding-right: 30px !important;
|
||||
}
|
||||
|
||||
.pre-cancel-table-wrapper {
|
||||
margin-top: 20px;
|
||||
width: 100%;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
|
||||
:deep(.el-table) {
|
||||
width: 100%;
|
||||
|
||||
.el-table__body-wrapper {
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,671 @@
|
||||
<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">
|
||||
<template #default="scope">
|
||||
{{ scope.row.organizationName ? scope.row.organizationName.trim() || '-' : '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="医生姓名" prop="practitionerName" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.practitionerName ? scope.row.practitionerName.trim() || '-' : '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="流水号" prop="encounterNo" align="center">
|
||||
<template #default="scope">
|
||||
{{ calculateSerialNo(scope.row) }}
|
||||
</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>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {getCurrentInstance, reactive, ref, watch, nextTick, onMounted} from 'vue';
|
||||
import {getOutpatientRegistrationCurrent, reprintRegistration} from './outpatientregistration';
|
||||
import {parseTime} from '@/utils/his';
|
||||
import {formatDateStr} from '@/utils/index';
|
||||
import {hiprint} from 'vue-plugin-hiprint';
|
||||
import outpatientRegistrationTemplate from '@/components/Print/OutpatientRegistration.json';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const userStore = useUserStore();
|
||||
|
||||
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 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 || [];
|
||||
|
||||
// 过滤掉挂号科室或医生姓名为空的记录
|
||||
records = records.filter(record => {
|
||||
const orgName = record.organizationName ? record.organizationName.trim() : '';
|
||||
const pracName = record.practitionerName ? record.practitionerName.trim() : '';
|
||||
// 只保留挂号科室和医生姓名都不为空的记录
|
||||
return orgName && pracName;
|
||||
});
|
||||
|
||||
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';
|
||||
|
||||
// 流水号 - 使用 calculateSerialNo 函数计算
|
||||
form.serialNo = calculateSerialNo(row);
|
||||
|
||||
// 合计 - 优先使用 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 || row.organizationName || '';
|
||||
|
||||
// 预约状态 - 从 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}`;
|
||||
}
|
||||
|
||||
// 计算流水号:直接使用挂号记录表的主键ID(encounterId)
|
||||
function calculateSerialNo(row) {
|
||||
if (!row) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
// 直接使用主键ID作为流水号
|
||||
if (row.encounterId != null && row.encounterId !== undefined) {
|
||||
return String(row.encounterId);
|
||||
} else if (row.id != null && row.id !== undefined) {
|
||||
// 兼容其他可能的ID字段名
|
||||
return String(row.id);
|
||||
} else {
|
||||
return '-';
|
||||
}
|
||||
}
|
||||
|
||||
// 提交补打挂号
|
||||
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 = '';
|
||||
}
|
||||
|
||||
// 显示打印预览(使用 hiprint 打印)
|
||||
function showPrintPreview() {
|
||||
loading.value = false;
|
||||
|
||||
console.log('showPrintPreview form:', form);
|
||||
console.log('showPrintPreview currentRecord:', currentRecord.value);
|
||||
|
||||
if (!form.name && currentRecord.value) {
|
||||
console.log('重新填充表单数据...');
|
||||
fillForm(currentRecord.value);
|
||||
}
|
||||
|
||||
// 使用 hiprint 打印
|
||||
printByHiprint();
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 hiprint 打印门诊挂号单(补打)
|
||||
*/
|
||||
function printByHiprint() {
|
||||
try {
|
||||
// 构建打印数据
|
||||
const printData = {
|
||||
patientName: form.name || '-',
|
||||
sex: form.gender || '-',
|
||||
age: form.age || '-',
|
||||
personType: '自费',
|
||||
busNo: form.cardNo || '-',
|
||||
organizationName: form.organizationName || '-',
|
||||
practitionerName: form.practitionerName || '-',
|
||||
healthcareName: '挂号',
|
||||
chargeTime: form.printTime || formatDateStr(new Date(), 'YYYY-MM-DD HH:mm:ss'),
|
||||
cashier: userStore.name || '',
|
||||
chargeItem: [
|
||||
{
|
||||
chargeItemName: '挂号费',
|
||||
quantityValue: '1',
|
||||
totalPrice: parseFloat(form.price || 0).toFixed(2),
|
||||
dirClass: 1
|
||||
},
|
||||
...(parseFloat(form.activityPrice || 0) > 0 ? [{
|
||||
chargeItemName: '诊疗费',
|
||||
quantityValue: '1',
|
||||
totalPrice: parseFloat(form.activityPrice || 0).toFixed(2),
|
||||
dirClass: 1
|
||||
}] : []),
|
||||
...(parseFloat(form.medicalRecordFee || 0) > 0 ? [{
|
||||
chargeItemName: '病历费',
|
||||
quantityValue: '1',
|
||||
totalPrice: parseFloat(form.medicalRecordFee || 0).toFixed(2),
|
||||
dirClass: 1
|
||||
}] : [])
|
||||
],
|
||||
displayAmount123: '¥' + parseFloat(form.totalPrice || 0).toFixed(2),
|
||||
FULAMT_OWNPAY_AMT: '¥' + parseFloat(form.totalPrice || 0).toFixed(2),
|
||||
SELF_CASH_VALUE: '¥' + parseFloat(form.totalPrice || 0).toFixed(2),
|
||||
pictureUrl: ''
|
||||
};
|
||||
|
||||
const result = {
|
||||
data: [printData]
|
||||
};
|
||||
|
||||
console.log('补打挂号打印数据:', printData);
|
||||
|
||||
// 处理模板(替换医院名称)
|
||||
const printElements = JSON.parse(
|
||||
JSON.stringify(outpatientRegistrationTemplate).replace(/{{HOSPITAL_NAME}}/g, userStore.hospitalName)
|
||||
);
|
||||
|
||||
// 创建 hiprint 模板并打印
|
||||
const hiprintTemplate = new hiprint.PrintTemplate({ template: printElements });
|
||||
|
||||
// 打印成功回调
|
||||
hiprintTemplate.on('printSuccess', function (e) {
|
||||
console.log('补打挂号单打印成功', e);
|
||||
proxy.$modal.msgSuccess('打印成功');
|
||||
dialogVisible.value = false;
|
||||
});
|
||||
|
||||
// 打印失败回调
|
||||
hiprintTemplate.on('printError', function (e) {
|
||||
console.error('补打挂号单打印失败', e);
|
||||
proxy.$modal.msgError('打印失败:' + (e.message || '未知错误'));
|
||||
});
|
||||
|
||||
// 执行打印
|
||||
hiprintTemplate.print2(result.data[0], {
|
||||
title: '门诊挂号单(补打)',
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('hiprint 打印挂号单失败:', error);
|
||||
proxy.$modal.msgError('打印失败:' + (error.message || '未知错误'));
|
||||
}
|
||||
}
|
||||
|
||||
// 选择挂号记录
|
||||
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;
|
||||
}
|
||||
|
||||
</style>
|
||||
2039
openhis-ui-vue3/src/views/charge/outpatientregistration/index.vue
Executable file
2039
openhis-ui-vue3/src/views/charge/outpatientregistration/index.vue
Executable file
File diff suppressed because it is too large
Load Diff
42
openhis-ui-vue3/src/views/charge/patientCardRenewal/components/api.js
Executable file
42
openhis-ui-vue3/src/views/charge/patientCardRenewal/components/api.js
Executable file
@@ -0,0 +1,42 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
/**
|
||||
* 执行患者换卡操作
|
||||
* @param {Object} params - 换卡参数
|
||||
* @param {string} params.oldCardNo - 旧门诊号码
|
||||
* @param {string} params.newCardNo - 新门诊号码
|
||||
* @param {string} params.patientId - 患者ID
|
||||
* @param {string} params.reason - 换卡原因
|
||||
* @param {string} params.remark - 备注信息
|
||||
* @returns {Promise} 请求结果
|
||||
*/
|
||||
export const doCardRenewal = (params) => {
|
||||
return request({
|
||||
url: '/charge/patientCardRenewal/renewCard',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询患者信息 - 复用门诊挂号的API
|
||||
* @param {Object} params - 查询参数
|
||||
* @param {string} params.searchKey - 搜索关键字(姓名、身份证号、手机号等)
|
||||
* @param {number} params.pageNo - 当前页码
|
||||
* @param {number} params.pageSize - 每页大小
|
||||
* @returns {Promise} 请求结果
|
||||
*/
|
||||
export const getPatientList = (params) => {
|
||||
// 构建searchKey参数,将姓名、身份证号、手机号组合成一个搜索关键字
|
||||
const searchKey = params.patientName || params.idCard || params.phoneNumber || '';
|
||||
|
||||
return request({
|
||||
url: '/charge-manage/register/patient-metadata',
|
||||
method: 'get',
|
||||
params: {
|
||||
searchKey: searchKey,
|
||||
pageNo: params.pageNo || 1,
|
||||
pageSize: params.pageSize || 10
|
||||
}
|
||||
})
|
||||
}
|
||||
757
openhis-ui-vue3/src/views/charge/patientCardRenewal/index.vue
Executable file
757
openhis-ui-vue3/src/views/charge/patientCardRenewal/index.vue
Executable file
@@ -0,0 +1,757 @@
|
||||
<template>
|
||||
<div class="card-renewal-container">
|
||||
<!-- 标题栏 -->
|
||||
<div class="title-bar">
|
||||
<h2>换卡处理</h2>
|
||||
</div>
|
||||
|
||||
<!-- 按钮栏 - 修改为水平排放 -->
|
||||
<div class="button-bar">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="large"
|
||||
@click="handlePatientSearch"
|
||||
:loading="loading"
|
||||
icon="el-icon-search"
|
||||
style="min-width: 140px;"
|
||||
>
|
||||
病人查询(Q)
|
||||
</el-button>
|
||||
|
||||
<el-button
|
||||
type="success"
|
||||
size="large"
|
||||
@click="handleConfirm"
|
||||
:loading="loading"
|
||||
:disabled="!patientInfo"
|
||||
style="min-width: 140px;"
|
||||
>
|
||||
确定 (O)
|
||||
</el-button>
|
||||
|
||||
<el-button
|
||||
type="danger"
|
||||
size="large"
|
||||
@click="handleClose"
|
||||
:disabled="loading"
|
||||
style="min-width: 140px;"
|
||||
>
|
||||
关闭 (C)
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 查询条件 -->
|
||||
<div class="search-section">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<div class="input-item">
|
||||
<label>病人姓名:</label>
|
||||
<el-input
|
||||
v-model="searchForm.patientName"
|
||||
placeholder="请输入"
|
||||
@keyup.enter="handlePatientSearch"
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="input-item">
|
||||
<label>身份证号码:</label>
|
||||
<el-input
|
||||
v-model="searchForm.idCard"
|
||||
placeholder="请输入"
|
||||
@keyup.enter="handlePatientSearch"
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="input-item">
|
||||
<label>手机号码:</label>
|
||||
<el-input
|
||||
v-model="searchForm.phoneNumber"
|
||||
placeholder="请输入"
|
||||
@keyup.enter="handlePatientSearch"
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<!-- 患者信息显示 -->
|
||||
<div class="patient-info-section">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<div class="info-item">
|
||||
<label>门诊号码</label>
|
||||
<div class="info-value">{{ patientInfo?.outpatientNo || '' }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="info-item">
|
||||
<label>病人姓名</label>
|
||||
<div class="info-value">{{ patientInfo?.patientName || '' }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="info-item">
|
||||
<label>身份证号码</label>
|
||||
<div class="info-value">{{ patientInfo?.idCard || '' }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20" style="margin-top: 15px;">
|
||||
<el-col :span="8">
|
||||
<div class="info-item">
|
||||
<label>手机号码</label>
|
||||
<div class="info-value">{{ patientInfo?.phoneNumber || '' }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="info-item">
|
||||
<label>性别</label>
|
||||
<div class="info-value">{{ patientInfo?.gender || '' }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="info-item">
|
||||
<label>年龄</label>
|
||||
<div class="info-value">{{ patientInfo?.age || '' }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<!-- 新门诊号码输入 -->
|
||||
<div class="new-number-section">
|
||||
<div class="input-item">
|
||||
<label>新门诊号码:</label>
|
||||
<el-input
|
||||
v-model="renewalForm.newOutpatientNo"
|
||||
placeholder="请输入新门诊号码"
|
||||
@keyup.enter="handleConfirm"
|
||||
style="width: 250px;"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 按钮区域已移除 -->
|
||||
|
||||
<!-- 患者列表对话框 -->
|
||||
<el-dialog
|
||||
v-model="showPatientList"
|
||||
:title="null"
|
||||
width="800px"
|
||||
:close-on-click-modal="false"
|
||||
class="custom-patient-dialog"
|
||||
>
|
||||
<!-- 自定义标题栏和按钮区域 -->
|
||||
<template #header>
|
||||
<div style="width: 100%; background-color: #e6f4ff;">
|
||||
<!-- 标题行 -->
|
||||
<div style="display: flex; justify-content: flex-start; align-items: center; padding: 10px 20px;">
|
||||
<h3 style="margin: 0; font-size: 16px; font-weight: 500; color: #303133;">病人档案查询</h3>
|
||||
</div>
|
||||
<!-- 按钮行 -->
|
||||
<div style="display: flex; justify-content: flex-start; gap: 10px; padding: 10px 20px; background-color: #e6f4ff;">
|
||||
<el-button type="primary" @click="confirmSelectPatient" style="background-color: #409eff; border-color: #409eff; padding: 8px 16px; font-size: 14px;">确认(Q)</el-button>
|
||||
<el-button @click="showPatientList = false; selectedPatient = null" style="background-color: #f56c6c; border-color: #f56c6c; color: white; padding: 8px 16px; font-size: 14px;">关闭(C)</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-table
|
||||
:data="patientList"
|
||||
style="width: 100%"
|
||||
@row-click="selectPatient"
|
||||
:row-key="row => row.identifierNo || row.patientId || row.cardNo"
|
||||
:current-row-key="selectedPatient?.identifierNo || selectedPatient?.patientId || selectedPatient?.cardNo"
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column label="序号" width="60" type="index">
|
||||
</el-table-column>
|
||||
<el-table-column label="病人姓名" width="120">
|
||||
<template #default="scope">
|
||||
{{ scope.row.patientName || scope.row.name || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="门诊号码" width="120">
|
||||
<template #default="scope">
|
||||
{{ scope.row.identifierNo || scope.row.cardNo || scope.row.card_number || scope.row.就诊卡号 || scope.row.outpatientNumber || scope.row.outpatientNo || scope.row.门诊号码 || scope.row.卡号 || scope.row.card || scope.row.patientNo || scope.row.patient_id || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="身份证号码" width="200">
|
||||
<template #default="scope">
|
||||
{{ scope.row.idCard || scope.row.id_card || scope.row.idNo || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="手机号码" width="120">
|
||||
<template #default="scope">
|
||||
{{ scope.row.phoneNumber || scope.row.phone || scope.row.mobile || scope.row.mobilePhone || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="性别" width="80">
|
||||
<template #default="scope">
|
||||
{{ scope.row.genderEnum_enumText || scope.row.gender || scope.row.sex || scope.row.性别 || scope.row.xb || scope.row.sexCode || scope.row.GENDER || scope.row.SEX || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="年龄" width="80">
|
||||
<template #default="scope">
|
||||
{{ scope.row.age || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="出生年月" width="120">
|
||||
<template #default="scope">
|
||||
{{ formatDate(scope.row.birthDate || scope.row.birthday || scope.row.出生日期) || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</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="[5, 10, 20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 移除底部按钮 -->
|
||||
<template #footer>
|
||||
<span></span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 换卡成功提示 -->
|
||||
<el-dialog
|
||||
v-model="renewalSuccessVisible"
|
||||
title="换卡成功"
|
||||
width="400px"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<div style="text-align: center; padding: 20px;">
|
||||
<div class="success-icon">✓</div>
|
||||
<p style="margin-top: 15px; font-size: 16px;">患者换卡操作已成功完成!</p>
|
||||
<p style="margin-top: 10px;">新门诊号码:{{ renewalForm.newOutpatientNo }}</p>
|
||||
</div>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="renewalSuccessVisible = false; resetForm">确定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {getCurrentInstance, onMounted, onUnmounted, reactive, ref} from 'vue'
|
||||
import {ElMessage, ElMessageBox} from 'element-plus'
|
||||
import {useRouter} from 'vue-router'
|
||||
import {doCardRenewal, getPatientList} from './components/api.js';
|
||||
|
||||
// 获取路由实例
|
||||
const router = useRouter();
|
||||
// 获取当前组件实例以访问全局属性
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
// 搜索表单
|
||||
const searchForm = reactive({
|
||||
patientName: '',
|
||||
idCard: '',
|
||||
phoneNumber: ''
|
||||
})
|
||||
|
||||
// 患者信息
|
||||
const patientInfo = ref(null)
|
||||
|
||||
// 患者列表
|
||||
const patientList = ref([])
|
||||
const showPatientList = ref(false)
|
||||
const selectedPatient = ref(null)
|
||||
// 分页相关状态
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(5)
|
||||
const total = ref(0)
|
||||
|
||||
// 换卡表单
|
||||
const renewalForm = reactive({
|
||||
newOutpatientNo: ''
|
||||
})
|
||||
|
||||
// 加载状态
|
||||
const loading = ref(false)
|
||||
|
||||
// 成功弹窗显示状态
|
||||
const renewalSuccessVisible = ref(false)
|
||||
|
||||
// 分页大小变化处理
|
||||
const handleSizeChange = (newSize) => {
|
||||
pageSize.value = newSize
|
||||
currentPage.value = 1 // 重置为第一页
|
||||
selectedPatient.value = null // 切换分页时重置选中状态
|
||||
if (showPatientList.value) {
|
||||
handlePatientSearch() // 重新查询
|
||||
}
|
||||
}
|
||||
|
||||
// 当前页码变化处理
|
||||
const handleCurrentChange = (newPage) => {
|
||||
currentPage.value = newPage
|
||||
selectedPatient.value = null // 切换分页时重置选中状态
|
||||
if (showPatientList.value) {
|
||||
handlePatientSearch() // 重新查询
|
||||
}
|
||||
}
|
||||
|
||||
// 查询患者信息
|
||||
const handlePatientSearch = async () => {
|
||||
// 检查是否至少填写了一个查询条件
|
||||
if (!searchForm.patientName && !searchForm.idCard && !searchForm.phoneNumber) {
|
||||
ElMessage.warning('请至少输入一个查询条件')
|
||||
return
|
||||
}
|
||||
|
||||
loading.value = true
|
||||
try {
|
||||
// 构建查询参数,包含分页信息
|
||||
const queryParams = {
|
||||
patientName: searchForm.patientName || '',
|
||||
idCard: searchForm.idCard || '',
|
||||
phoneNumber: searchForm.phoneNumber || '',
|
||||
pageNo: currentPage.value,
|
||||
pageSize: pageSize.value
|
||||
}
|
||||
|
||||
// 调用复用的门诊挂号API获取患者列表
|
||||
const response = await getPatientList(queryParams)
|
||||
|
||||
if (response && response.code === 200) {
|
||||
// 检查是否有查询结果
|
||||
if (response.data && response.data.records && response.data.records.length > 0) {
|
||||
// 更新总条数
|
||||
total.value = response.data.total || 0
|
||||
selectedPatient.value = null // 查询时重置选中状态
|
||||
|
||||
// 如果只有一条记录且是第一页,自动选中并展示到页面
|
||||
if (response.data.records.length === 1 && currentPage.value === 1) {
|
||||
const patient = response.data.records[0]
|
||||
// 确保patient对象中同时包含id和patientId字段
|
||||
if (patient.id && !patient.patientId) {
|
||||
patient.patientId = patient.id;
|
||||
}
|
||||
|
||||
// 设置为选中状态并自动确认,将患者信息展示到页面
|
||||
selectedPatient.value = patient
|
||||
confirmSelectPatient() // 自动调用确认选择方法,将患者信息展示到页面
|
||||
ElMessage.success('已自动选中唯一患者')
|
||||
} else {
|
||||
// 如果有多条记录或不是第一页,显示患者列表供选择
|
||||
// 确保每条患者记录都包含patientId字段,优先使用id字段
|
||||
patientList.value = response.data.records.map(patient => ({
|
||||
...patient,
|
||||
patientId: patient.patientId || patient.id
|
||||
}))
|
||||
showPatientList.value = true
|
||||
}
|
||||
} else {
|
||||
// 无数据时重置总条数
|
||||
total.value = 0
|
||||
ElMessage.warning('未查询到患者信息')
|
||||
}
|
||||
} else {
|
||||
ElMessage.error('查询失败:' + (response?.msg || '未知错误'))
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
// 使用公共错误处理函数处理错误信息
|
||||
const errorMessage = processErrorMessage(error, '查询失败,请稍后重试');
|
||||
ElMessage.error(errorMessage);
|
||||
// 可以在这里添加错误监控或日志记录
|
||||
console.error('患者查询错误:', error);
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 确定换卡
|
||||
const handleConfirm = async () => {
|
||||
if (!patientInfo.value) {
|
||||
ElMessage.warning('请先查询患者信息')
|
||||
return
|
||||
}
|
||||
|
||||
if (!renewalForm.newOutpatientNo) {
|
||||
ElMessage.warning('请输入新门诊号码')
|
||||
return
|
||||
}
|
||||
|
||||
if (renewalForm.newOutpatientNo === patientInfo.value.outpatientNo) {
|
||||
ElMessage.warning('新门诊号码不能与原号码相同')
|
||||
return
|
||||
}
|
||||
|
||||
loading.value = true
|
||||
try {
|
||||
// 构建换卡请求参数,注意参数名称与API接口保持一致
|
||||
const params = {
|
||||
oldCardNo: patientInfo.value.outpatientNo,
|
||||
newCardNo: renewalForm.newOutpatientNo,
|
||||
patientId: patientInfo.value.patientId,
|
||||
reason: '患者换卡',
|
||||
remark: `从${patientInfo.value.outpatientNo}更换到${renewalForm.newOutpatientNo}`
|
||||
}
|
||||
|
||||
// 调用真实的换卡接口
|
||||
const res = await doCardRenewal(params)
|
||||
|
||||
if (res && res.code === 200) {
|
||||
renewalSuccessVisible.value = true
|
||||
// 更新患者信息中的门诊号码为新号码
|
||||
if (patientInfo.value) {
|
||||
patientInfo.value.outpatientNo = renewalForm.newOutpatientNo
|
||||
}
|
||||
ElMessage.success('换卡成功!')
|
||||
} else {
|
||||
ElMessage.error('换卡失败:' + (res?.msg || '未知错误'))
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
ElMessage.error('换卡失败,卡号已存在')
|
||||
// 可以在这里添加错误监控或日志记录
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭窗口,同时关闭标签页并返回上一级页面
|
||||
const handleClose = () => {
|
||||
// 显示确认对话框
|
||||
ElMessageBox.confirm('确定要关闭此页面吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
// 用户确认后,使用全局$tab对象关闭当前标签页
|
||||
if (proxy && proxy.$tab) {
|
||||
proxy.$tab.closePage()
|
||||
} else {
|
||||
// 降级处理:如果$tab不可用,仍然使用router.back()
|
||||
router.back()
|
||||
}
|
||||
}).catch(() => {
|
||||
// 用户取消操作,不执行任何操作
|
||||
// 可以选择显示一个提示消息
|
||||
ElMessage.info('已取消关闭操作')
|
||||
})
|
||||
}
|
||||
|
||||
// 键盘事件处理
|
||||
const handleKeydown = (event) => {
|
||||
// 只有在患者列表对话框显示时才处理对话框快捷键
|
||||
if (showPatientList.value) {
|
||||
// 忽略在输入框中按下的按键
|
||||
if (event.target.tagName === 'INPUT' || event.target.tagName === 'TEXTAREA') {
|
||||
return
|
||||
}
|
||||
|
||||
const key = event.key.toLowerCase()
|
||||
if (key === 'q') {
|
||||
event.preventDefault()
|
||||
confirmSelectPatient()
|
||||
} else if (key === 'c') {
|
||||
event.preventDefault()
|
||||
showPatientList.value = false
|
||||
selectedPatient.value = null
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Alt + Q 查询
|
||||
if (event.altKey && event.key.toLowerCase() === 'q') {
|
||||
event.preventDefault()
|
||||
handlePatientSearch()
|
||||
}
|
||||
// Alt + O 确定
|
||||
if (event.altKey && event.key.toLowerCase() === 'o') {
|
||||
event.preventDefault()
|
||||
handleConfirm()
|
||||
}
|
||||
// Alt + C 关闭
|
||||
if (event.altKey && event.key.toLowerCase() === 'c') {
|
||||
event.preventDefault()
|
||||
handleClose()
|
||||
}
|
||||
}
|
||||
|
||||
// 组件挂载时添加键盘事件监听
|
||||
onMounted(() => {
|
||||
document.addEventListener('keydown', handleKeydown)
|
||||
|
||||
// 初始化患者信息为空
|
||||
})
|
||||
|
||||
// 组件卸载时移除键盘事件监听
|
||||
onUnmounted(() => {
|
||||
document.removeEventListener('keydown', handleKeydown)
|
||||
})
|
||||
|
||||
// 移除了调试功能
|
||||
|
||||
// 选择患者(仅设置选中状态)
|
||||
const selectPatient = (row) => {
|
||||
selectedPatient.value = row
|
||||
ElMessage.warning('已选择患者,请点击确定')
|
||||
}
|
||||
|
||||
// 确认选择患者
|
||||
const confirmSelectPatient = () => {
|
||||
if (!selectedPatient.value) {
|
||||
ElMessage.warning('请先选择患者')
|
||||
return
|
||||
}
|
||||
|
||||
const row = selectedPatient.value
|
||||
// 获取门诊号码,优先使用identifierNo
|
||||
const outpatientNo = row.identifierNo || row.cardNo || row.card_number || row.就诊卡号 || row.outpatientNumber || row.outpatientNo || row.门诊号码 || row.卡号 || row.card || row.patientNo || row.patient_id;
|
||||
// 获取性别,优先使用genderEnum_enumText
|
||||
const gender = row.genderEnum_enumText || row.gender || row.sex || row.性别 || row.xb || row.sexCode || row.GENDER || row.SEX;
|
||||
|
||||
patientInfo.value = {
|
||||
outpatientNo: outpatientNo,
|
||||
patientName: row.patientName || row.name,
|
||||
idCard: row.idCard || row.id_card || row.idNo,
|
||||
phoneNumber: row.phoneNumber || row.phone || row.mobile || row.mobilePhone,
|
||||
gender: gender,
|
||||
age: row.age,
|
||||
patientId: row.patientId || row.id || outpatientNo
|
||||
}
|
||||
|
||||
showPatientList.value = false
|
||||
ElMessage.success('已选择患者:' + (row.patientName || row.name))
|
||||
// 重置选中状态
|
||||
selectedPatient.value = null
|
||||
}
|
||||
|
||||
// 重置表单
|
||||
const resetForm = () => {
|
||||
searchForm.patientName = ''
|
||||
searchForm.idCard = ''
|
||||
searchForm.phoneNumber = ''
|
||||
patientInfo.value = null
|
||||
patientList.value = []
|
||||
showPatientList.value = false
|
||||
selectedPatient.value = null
|
||||
renewalForm.newOutpatientNo = ''
|
||||
// 重置分页状态
|
||||
currentPage.value = 1
|
||||
pageSize.value = 5
|
||||
total.value = 0
|
||||
}
|
||||
|
||||
// 格式化日期为YYYY-MM-DD格式
|
||||
const formatDate = (date) => {
|
||||
if (!date) return ''
|
||||
// 如果已经是YYYY-MM-DD格式,直接返回
|
||||
if (typeof date === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
||||
return date
|
||||
}
|
||||
// 处理日期对象或其他格式
|
||||
const d = new Date(date)
|
||||
if (isNaN(d.getTime())) return ''
|
||||
const year = d.getFullYear()
|
||||
const month = String(d.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(d.getDate()).padStart(2, '0')
|
||||
return `${year}-${month}-${day}`
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 自定义对话框样式 */
|
||||
.custom-patient-dialog .el-dialog__header {
|
||||
padding: 0;
|
||||
border-bottom: none;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/* 隐藏默认的header样式 */
|
||||
.custom-header {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.custom-patient-dialog .el-dialog__body {
|
||||
padding: 0;
|
||||
max-height: 60vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* 隐藏默认底部区域 */
|
||||
.custom-patient-dialog .el-dialog__footer {
|
||||
padding: 0;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.dialog-footer .el-button {
|
||||
min-width: 80px;
|
||||
background-color: #f56c6c;
|
||||
border-color: #f56c6c;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* 表格样式 */
|
||||
.el-dialog__body {
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.el-table {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.el-table th {
|
||||
background-color: #f5f7fa;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.el-table td {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* 表格样式优化 */
|
||||
.el-table {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.el-table th {
|
||||
background-color: #f5f7fa;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.el-table td {
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.el-table tr:hover > td {
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
|
||||
.el-table--striped .el-table__body tr:nth-child(2n) {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
/* 分页样式优化 */
|
||||
.el-pagination {
|
||||
margin-top: 10px;
|
||||
padding: 10px 20px;
|
||||
background-color: #fafafa;
|
||||
border-top: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.card-renewal-container {
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 10px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.title-bar {
|
||||
background: #409eff;
|
||||
color: white;
|
||||
padding: 10px 15px;
|
||||
margin: -10px -10px 15px -10px;
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
|
||||
.title-bar h2 {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.button-bar {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
padding: 15px;
|
||||
background-color: #f5f7fa;
|
||||
border: 1px solid #ebeef5;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.button-bar .el-button {
|
||||
font-weight: 500;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.button-bar .el-button:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.search-section {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.input-item {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.input-item label {
|
||||
display: inline-block;
|
||||
width: 100px;
|
||||
text-align: right;
|
||||
margin-right: 10px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.patient-info-section {
|
||||
background: #f5f7fa;
|
||||
padding: 15px;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.info-item label {
|
||||
display: block;
|
||||
color: #606266;
|
||||
font-size: 14px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.new-number-section {
|
||||
margin-top: 20px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.success-icon {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background: #67c23a;
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 30px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
</style>
|
||||
342
openhis-ui-vue3/src/views/charge/patientSearch/PatientSearch.vue
Executable file
342
openhis-ui-vue3/src/views/charge/patientSearch/PatientSearch.vue
Executable file
@@ -0,0 +1,342 @@
|
||||
<template>
|
||||
<div class="patient-search-container">
|
||||
<!-- 标题栏 -->
|
||||
<div class="title-bar">
|
||||
<h2>病人档案查询</h2>
|
||||
<div class="button-bar">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleQuery"
|
||||
:loading="loading"
|
||||
size="large"
|
||||
icon="el-icon-check"
|
||||
>
|
||||
确认(Q)
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
@click="handleClose"
|
||||
size="large"
|
||||
icon="el-icon-close"
|
||||
>
|
||||
关闭(C)
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 查询表单 -->
|
||||
<div class="search-form">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<div class="form-item">
|
||||
<label>病人姓名:</label>
|
||||
<el-input
|
||||
v-model="searchForm.patientName"
|
||||
placeholder="请输入病人姓名"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="form-item">
|
||||
<label>身份证号码:</label>
|
||||
<el-input
|
||||
v-model="searchForm.idCard"
|
||||
placeholder="请输入身份证号码"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="form-item">
|
||||
<label>手机号码:</label>
|
||||
<el-input
|
||||
v-model="searchForm.phoneNumber"
|
||||
placeholder="请输入手机号码"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<!-- 查询结果表格 -->
|
||||
<div class="result-table">
|
||||
<el-table
|
||||
:data="patientList"
|
||||
style="width: 100%"
|
||||
stripe
|
||||
@row-click="handleRowClick"
|
||||
highlight-current-row
|
||||
row-key="id"
|
||||
:current-row-key="selectedPatient?.id"
|
||||
>
|
||||
<el-table-column label="序号" type="index" width="80" align="center">
|
||||
</el-table-column>
|
||||
<el-table-column label="病人姓名" width="120" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.patientName }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="门诊号码" width="150" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.outpatientNo || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="身份证号码" width="200" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.idCard || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="手机号码" width="120" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.phoneNumber || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="性别" width="80" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.gender }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="年龄" width="80" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.age }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="出生年月" width="120" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.birthDate }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {computed, onMounted, onUnmounted, reactive, ref, watch} from 'vue'
|
||||
import {ElMessage} from 'element-plus'
|
||||
import {getOutpatientRegistrationList} from '../outpatientregistration/components/outpatientregistration'
|
||||
|
||||
// 搜索表单
|
||||
const searchForm = reactive({
|
||||
patientName: '',
|
||||
idCard: '',
|
||||
phoneNumber: ''
|
||||
})
|
||||
|
||||
// 患者列表
|
||||
const patientList = ref([])
|
||||
|
||||
// 加载状态
|
||||
const loading = ref(false)
|
||||
|
||||
// API调用相关变量
|
||||
const queryParams = ref({
|
||||
pageNum: 1,
|
||||
pageSize: 50
|
||||
})
|
||||
|
||||
// 当前选中的患者
|
||||
const selectedPatient = ref(null)
|
||||
|
||||
// 定义事件
|
||||
const emit = defineEmits(['selectPatient', 'close'])
|
||||
|
||||
// 计算搜索关键字,合并三个字段为一个searchKey
|
||||
const searchKey = computed(() => {
|
||||
return searchForm.patientName || searchForm.idCard || searchForm.phoneNumber
|
||||
})
|
||||
|
||||
// 监听搜索关键字变化,自动查询
|
||||
watch(searchKey, (newValue) => {
|
||||
// 当搜索关键字变化时,延迟查询,避免频繁请求
|
||||
const timer = setTimeout(() => {
|
||||
if (newValue) {
|
||||
queryParams.value.searchKey = newValue
|
||||
handleQuery()
|
||||
}
|
||||
}, 300)
|
||||
return () => clearTimeout(timer)
|
||||
})
|
||||
|
||||
// 处理行点击
|
||||
const handleRowClick = (row) => {
|
||||
selectedPatient.value = row
|
||||
ElMessage.success(`已选择患者:${row.patientName}`)
|
||||
}
|
||||
|
||||
// 查询患者信息和确认选择
|
||||
const handleQuery = async () => {
|
||||
// 如果已经选中了患者,则确认选择
|
||||
if (selectedPatient.value) {
|
||||
// 发射选择患者事件
|
||||
emit('selectPatient', selectedPatient.value)
|
||||
ElMessage.success(`已确认选择患者:${selectedPatient.value.patientName}`)
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否至少填写了一个查询条件
|
||||
if (!searchKey.value) {
|
||||
ElMessage.warning('请至少输入一个查询条件')
|
||||
return
|
||||
}
|
||||
|
||||
loading.value = true
|
||||
try {
|
||||
// 调用门诊挂号的API获取患者列表
|
||||
const response = await getOutpatientRegistrationList(queryParams.value)
|
||||
|
||||
if (response.data && response.data.records) {
|
||||
// 映射字段,使其与表格展示需求匹配
|
||||
patientList.value = response.data.records.map(record => ({
|
||||
id: record.id,
|
||||
patientName: record.name,
|
||||
outpatientNo: record.identifierNo,
|
||||
idCard: record.idCard,
|
||||
phoneNumber: record.phone,
|
||||
gender: record.genderEnum_enumText || '-',
|
||||
age: record.age || '-',
|
||||
birthDate: record.birthDate || '-' // 如果后端没有提供,需要计算或显示为'-'
|
||||
}))
|
||||
|
||||
if (patientList.value.length === 0) {
|
||||
ElMessage.warning('未找到符合条件的患者信息')
|
||||
}
|
||||
} else {
|
||||
ElMessage.error('查询失败')
|
||||
patientList.value = []
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('查询失败,请稍后重试')
|
||||
console.error('查询失败:', error)
|
||||
patientList.value = []
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭窗口
|
||||
const handleClose = () => {
|
||||
// 发射关闭事件
|
||||
emit('close')
|
||||
}
|
||||
|
||||
// 键盘事件处理
|
||||
const handleKeydown = (event) => {
|
||||
// Alt + Q 查询
|
||||
if (event.altKey && event.key.toLowerCase() === 'q') {
|
||||
event.preventDefault()
|
||||
handleQuery()
|
||||
}
|
||||
// Alt + C 关闭
|
||||
if (event.altKey && event.key.toLowerCase() === 'c') {
|
||||
event.preventDefault()
|
||||
handleClose()
|
||||
}
|
||||
}
|
||||
|
||||
// 组件挂载时添加键盘事件监听
|
||||
onMounted(() => {
|
||||
document.addEventListener('keydown', handleKeydown)
|
||||
})
|
||||
|
||||
// 组件卸载时移除键盘事件监听
|
||||
onUnmounted(() => {
|
||||
document.removeEventListener('keydown', handleKeydown)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.patient-search-container {
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
border: 1px solid #b3d4ff;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.title-bar {
|
||||
background-color: #d6e9ff;
|
||||
padding: 10px 20px;
|
||||
border-bottom: 1px solid #b3d4ff;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.title-bar h2 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.button-bar {
|
||||
padding: 10px 20px;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.button-bar .el-button {
|
||||
padding: 12px 24px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.search-form {
|
||||
padding: 20px;
|
||||
border-bottom: 1px solid #dcdfe6;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
margin-bottom: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.form-item label {
|
||||
display: inline-block;
|
||||
width: 100px;
|
||||
text-align: right;
|
||||
margin-right: 10px;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.form-item .el-input {
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
.result-table {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.el-table {
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.el-table th {
|
||||
background-color: #f2f6fc;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
border-bottom: 1px solid #e6e8eb;
|
||||
}
|
||||
|
||||
.el-table td {
|
||||
padding: 10px 0;
|
||||
font-size: 14px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.el-table--striped .el-table__body tr:nth-child(2n) {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.el-table__row:hover {
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
</style>
|
||||
48
openhis-ui-vue3/src/views/charge/patientSearch/api.js
Executable file
48
openhis-ui-vue3/src/views/charge/patientSearch/api.js
Executable file
@@ -0,0 +1,48 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
/**
|
||||
* 获取门诊患者信息列表
|
||||
* 复用门诊挂号的API来查询患者信息
|
||||
*/
|
||||
export const getOutpatientRegistrationList = (params) => {
|
||||
// 调用门诊挂号的API获取患者信息
|
||||
return request({
|
||||
url: '/api/outpatient/registration/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID获取患者详情
|
||||
*/
|
||||
export const getPatientById = (id) => {
|
||||
return request({
|
||||
url: `/api/outpatient/registration/${id}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据条件查询患者信息
|
||||
* 复用门诊挂号API进行查询
|
||||
*/
|
||||
export const getPatientList = (params) => {
|
||||
// 复用门诊挂号的API
|
||||
return request({
|
||||
url: '/api/outpatient/registration/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据门诊号码获取患者详细信息
|
||||
*/
|
||||
export const getPatientByOutpatientNo = (outpatientNo) => {
|
||||
return request({
|
||||
url: '/api/outpatient/registration/list',
|
||||
method: 'get',
|
||||
params: { identifierNo: outpatientNo }
|
||||
})
|
||||
}
|
||||
2
openhis-ui-vue3/src/views/charge/registerRecords/index.vue
Executable file
2
openhis-ui-vue3/src/views/charge/registerRecords/index.vue
Executable file
@@ -0,0 +1,2 @@
|
||||
<template>
|
||||
</template>
|
||||
2
openhis-ui-vue3/src/views/charge/schedule/index.vue
Executable file
2
openhis-ui-vue3/src/views/charge/schedule/index.vue
Executable file
@@ -0,0 +1,2 @@
|
||||
<template>
|
||||
</template>
|
||||
502
openhis-ui-vue3/src/views/charge/surgerycharge/index.vue
Executable file
502
openhis-ui-vue3/src/views/charge/surgerycharge/index.vue
Executable file
@@ -0,0 +1,502 @@
|
||||
<template>
|
||||
<div style="display: flex; justify-content: space-between" class="app-container" v-loading="loading"
|
||||
:element-loading-text="loadingText">
|
||||
<!-- 左侧:患者基本信息区 -->
|
||||
<el-card style="width: 30%">
|
||||
<template #header>
|
||||
<span style="vertical-align: middle">患者基本信息</span>
|
||||
</template>
|
||||
<el-descriptions :column="1" border>
|
||||
<el-descriptions-item label="病历号">{{ patientInfo.encounterBusNo }}</el-descriptions-item>
|
||||
<el-descriptions-item label="姓名">{{ patientInfo.patientName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="性别">{{ patientInfo.genderEnum_enumText }}</el-descriptions-item>
|
||||
<el-descriptions-item label="年龄">{{ patientInfo.age }}</el-descriptions-item>
|
||||
<el-descriptions-item label="科室">{{ patientInfo.organizationName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="就诊时间">
|
||||
{{ formatDateStr(patientInfo.receptionTime, 'YYYY-MM-DD HH:mm:ss') }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="手术单号">{{ surgeryInfo.surgeryNo }}</el-descriptions-item>
|
||||
<el-descriptions-item label="手术名称">{{ surgeryInfo.surgeryName }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
|
||||
<!-- 右侧:收费项目区 -->
|
||||
<div style="width: 69%">
|
||||
<el-card style="min-width: 1100px">
|
||||
<template #header>
|
||||
<span style="vertical-align: middle">收费项目</span>
|
||||
</template>
|
||||
<div style="margin-bottom: 10px">
|
||||
<el-button type="primary" @click="confirmCharge()" :disabled="buttonDisabled">
|
||||
确认收费
|
||||
</el-button>
|
||||
<el-button type="primary" plain @click="handleReadCard('01')" style="width: 65px">
|
||||
电子凭证
|
||||
</el-button>
|
||||
<el-button type="primary" plain @click="handleReadCard('03')" style="width: 65px">
|
||||
医保卡
|
||||
</el-button>
|
||||
<span style="float: right">
|
||||
合计金额:{{ totalAmounts ? totalAmounts.toFixed(2) : 0 }}元
|
||||
</span>
|
||||
</div>
|
||||
<el-table
|
||||
ref="chargeListRef"
|
||||
height="530"
|
||||
:data="chargeList"
|
||||
row-key="id"
|
||||
@selection-change="handleSelectionChange"
|
||||
v-loading="chargeLoading"
|
||||
:span-method="objectSpanMethod"
|
||||
border
|
||||
>
|
||||
<el-table-column type="selection" :selectable="checkSelectable" width="55" />
|
||||
<el-table-column label="单据号" align="center" prop="busNo" width="180" />
|
||||
<el-table-column label="收费项目" align="center" prop="itemName" width="200" />
|
||||
<el-table-column label="数量" align="center" prop="quantityValue" width="80" />
|
||||
<el-table-column label="医疗类型" align="center" prop="medTypeCode_dictText" />
|
||||
<el-table-column label="医保编码" align="center" prop="ybNo" />
|
||||
<el-table-column label="费用性质" align="center" prop="contractName" />
|
||||
<el-table-column label="收费状态" align="center" prop="statusEnum_enumText" width="150">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.statusEnum === 1" disable-transitions>
|
||||
{{ scope.row.statusEnum_enumText }}
|
||||
</el-tag>
|
||||
<el-tag v-else-if="scope.row.statusEnum === 5" type="success" disable-transitions>
|
||||
{{ scope.row.statusEnum_enumText }}
|
||||
</el-tag>
|
||||
<el-tag v-else-if="scope.row.statusEnum === 8" type="danger" disable-transitions>
|
||||
{{ scope.row.statusEnum_enumText }}
|
||||
</el-tag>
|
||||
<el-tag v-else type="warning" disable-transitions>
|
||||
{{ scope.row.statusEnum_enumText }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="金额" align="right" prop="totalPrice" header-align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.totalPrice.toFixed(2) + ' 元' || '0.00' + ' 元' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="收款人" align="center" prop="entererId_dictText" />
|
||||
<el-table-column
|
||||
label="操作"
|
||||
align="center"
|
||||
fixed="right"
|
||||
header-align="center"
|
||||
class-name="no-hover-column"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
:disabled="!scope.row.paymentId"
|
||||
link
|
||||
type="primary"
|
||||
@click="printCharge(scope.row)"
|
||||
>
|
||||
打印
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<!-- 收费对话框 -->
|
||||
<ChargeDialog
|
||||
ref="chargeDialogRef"
|
||||
:open="openDialog"
|
||||
@close="handleClose"
|
||||
:category="patientInfo.categoryEnum"
|
||||
:totalAmount="totalAmount"
|
||||
:patientInfo="patientInfo"
|
||||
:chargeItemIds="chargeItemIdList"
|
||||
:consumablesIdList="consumablesIdList"
|
||||
:chrgBchnoList="chrgBchnoList"
|
||||
:userCardInfo="userCardInfo"
|
||||
:paymentId="paymentId"
|
||||
:details="details"
|
||||
:chargedItems="chargedItems"
|
||||
:feeType="patientInfo.medfeePaymtdCode"
|
||||
:medfee_paymtd_code="medfee_paymtd_code"
|
||||
@refresh="getChargeList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="SurgeryCharge">
|
||||
import {
|
||||
getChargeList,
|
||||
precharge,
|
||||
getChargeInfo,
|
||||
} from '../cliniccharge/components/api';
|
||||
import {invokeYbPlugin5000, invokeYbPlugin5001} from '@/api/public';
|
||||
import ChargeDialog from '../cliniccharge/components/chargeDialog.vue';
|
||||
import {formatDateStr} from '@/utils';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
import Decimal from 'decimal.js';
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const userStore = useUserStore();
|
||||
const { medfee_paymtd_code } = proxy.useDict('medfee_paymtd_code');
|
||||
|
||||
// Props: 从手术安排界面传入的患者信息和手术信息
|
||||
const props = defineProps({
|
||||
patientInfo: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: () => ({})
|
||||
},
|
||||
surgeryInfo: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: () => ({})
|
||||
}
|
||||
});
|
||||
|
||||
// 数据定义
|
||||
const totalAmounts = ref(0);
|
||||
const selectedRows = ref([]);
|
||||
const chargeList = ref([]);
|
||||
const chargeItemIdList = ref([]);
|
||||
const chrgBchnoList = ref([]);
|
||||
const chargeLoading = ref(false);
|
||||
const encounterId = ref('');
|
||||
const paymentId = ref('');
|
||||
const openDialog = ref(false);
|
||||
const totalAmount = ref(0);
|
||||
const chargeListRef = ref();
|
||||
const details = ref({});
|
||||
const buttonDisabled = computed(() => {
|
||||
return Object.keys(props.patientInfo).length === 0;
|
||||
});
|
||||
const chargedItems = ref([]);
|
||||
const consumablesIdList = ref([]);
|
||||
const userCardInfo = ref({});
|
||||
const readCardLoading = ref(false);
|
||||
const loadingText = ref('');
|
||||
const loading = ref(false);
|
||||
|
||||
// Watch
|
||||
watch(
|
||||
() => selectedRows.value,
|
||||
(newVlaue) => {
|
||||
if (newVlaue && newVlaue.length > 0) {
|
||||
handleTotalAmount();
|
||||
} else {
|
||||
totalAmounts.value = 0;
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
watch(
|
||||
() => chargeList.value,
|
||||
(newVlaue) => {
|
||||
if (newVlaue && newVlaue.length > 0) {
|
||||
handleTotalAmount();
|
||||
} else {
|
||||
totalAmounts.value = 0;
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
if (props.patientInfo && props.patientInfo.encounterId) {
|
||||
encounterId.value = props.patientInfo.encounterId;
|
||||
fetchChargeList();
|
||||
}
|
||||
});
|
||||
|
||||
// 方法
|
||||
function handleSelectionChange(selection) {
|
||||
selectedRows.value = selection;
|
||||
}
|
||||
|
||||
function handleTotalAmount() {
|
||||
if (selectedRows.value.length == 0) {
|
||||
totalAmounts.value = chargeList.value.reduce((accumulator, currentRow) => {
|
||||
return new Decimal(accumulator).add(currentRow.totalPrice.toFixed(2) || 0);
|
||||
}, new Decimal(0));
|
||||
} else {
|
||||
totalAmounts.value = selectedRows.value.reduce((accumulator, currentRow) => {
|
||||
return new Decimal(accumulator).add(currentRow.totalPrice.toFixed(2) || 0);
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// 获取收费项目列表(只显示该手术已计费的项目)
|
||||
function fetchChargeList() {
|
||||
if (!props.patientInfo.encounterId) {
|
||||
return;
|
||||
}
|
||||
chargeLoading.value = true;
|
||||
// 调用门诊划价的getChargeList接口,传入encounterId
|
||||
// 只显示generateSourceEnum=2(手术计费)且sourceBillNo=手术单号的费用项
|
||||
getChargeList(props.patientInfo.encounterId).then((res) => {
|
||||
// 过滤出手术计费的收费项目
|
||||
chargeList.value = (res.data || []).filter(item =>
|
||||
item.generateSourceEnum === 2 && item.sourceBillNo === props.surgeryInfo.surgeryNo
|
||||
);
|
||||
setTimeout(() => {
|
||||
chargeLoading.value = false;
|
||||
// 默认选中所有未收费的项目
|
||||
if (chargeListRef.value) {
|
||||
chargeListRef.value.toggleAllSelection();
|
||||
}
|
||||
}, 100);
|
||||
}).catch(() => {
|
||||
chargeLoading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
function checkSelectable(row, index) {
|
||||
// 已结算时禁用选择框
|
||||
return row.statusEnum === 1;
|
||||
}
|
||||
|
||||
function handleClose(value, msg) {
|
||||
openDialog.value = false;
|
||||
if (value == 'success') {
|
||||
proxy.$modal.msgSuccess(msg);
|
||||
fetchChargeList();
|
||||
}
|
||||
}
|
||||
|
||||
// 确认收费
|
||||
function confirmCharge() {
|
||||
let selectRows = chargeListRef.value.getSelectionRows();
|
||||
if (selectRows.length == 0) {
|
||||
proxy.$modal.msgWarning('请选择一条收费项目');
|
||||
return;
|
||||
}
|
||||
chargeItemIdList.value = selectRows.map((item) => {
|
||||
return item.id;
|
||||
});
|
||||
consumablesIdList.value = selectRows
|
||||
.filter((item) => {
|
||||
return item.serviceTable == 'wor_device_request';
|
||||
})
|
||||
.map((item) => {
|
||||
return item.id;
|
||||
});
|
||||
chargedItems.value = selectRows;
|
||||
|
||||
precharge({
|
||||
patientId: props.patientInfo.patientId,
|
||||
encounterId: props.patientInfo.encounterId,
|
||||
chargeItemIds: chargeItemIdList.value,
|
||||
// 传递手术计费标识
|
||||
generateSourceEnum: 2,
|
||||
sourceBillNo: props.surgeryInfo.surgeryNo,
|
||||
}).then((res) => {
|
||||
if (res.code == 200 && res.data) {
|
||||
paymentId.value = res.data.paymentId;
|
||||
chrgBchnoList.value = res.data.chrgBchnoList;
|
||||
totalAmount.value = res.data.details?.find((item) => item.payEnum == 220000)?.amount ?? 0;
|
||||
details.value = res.data.details?.filter((item) => {
|
||||
return item.amount > 0;
|
||||
}) || [];
|
||||
openDialog.value = true;
|
||||
} else {
|
||||
proxy.$modal.msgError(res?.msg || '预结算失败');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 读卡功能
|
||||
async function handleReadCard(value) {
|
||||
try {
|
||||
let jsonResult;
|
||||
let cardInfo;
|
||||
let userMessage = undefined;
|
||||
switch (value) {
|
||||
case '01': // 电子凭证
|
||||
await invokeYbPlugin5000({
|
||||
FunctionId: 3,
|
||||
url: 'http://10.47.0.67:8089/localcfc/api/hsecfc/localQrCodeQuery',
|
||||
orgId: 'H22010200672',
|
||||
businessType: '01101',
|
||||
operatorId: userStore.id.toString(),
|
||||
operatorName: userStore.name,
|
||||
officeId: 'D83',
|
||||
officeName: '财务科',
|
||||
})
|
||||
.then((res) => {
|
||||
readCardLoading.value = true;
|
||||
loadingText.value = '正在读取...';
|
||||
jsonResult = res.data;
|
||||
})
|
||||
.catch(() => {
|
||||
readCardLoading.value = false;
|
||||
})
|
||||
.finally(() => {
|
||||
readCardLoading.value = false;
|
||||
});
|
||||
cardInfo = JSON.parse(JSON.stringify(jsonResult));
|
||||
let message = JSON.parse(cardInfo.data);
|
||||
userMessage = {
|
||||
certType: '02',
|
||||
certNo: message.data.idNo,
|
||||
psnCertType: '02',
|
||||
};
|
||||
userCardInfo.value = {
|
||||
certType: '01',
|
||||
certNo: message.data.idNo,
|
||||
psnCertType: '01',
|
||||
busiCardInfo: message.data.ecToken,
|
||||
};
|
||||
break;
|
||||
case '03': // 医保卡
|
||||
readCardLoading.value = true;
|
||||
loadingText.value = '正在读取...';
|
||||
await invokeYbPlugin5001(
|
||||
JSON.stringify({
|
||||
FunctionId: 1,
|
||||
IP: 'ddjk.jlhs.gov.cn',
|
||||
PORT: 20215,
|
||||
TIMEOUT: 60,
|
||||
SFZ_DRIVER_TYPE: 1,
|
||||
})
|
||||
)
|
||||
.then((res) => {
|
||||
jsonResult = JSON.stringify(res.data);
|
||||
})
|
||||
.finally(() => {
|
||||
readCardLoading.value = false;
|
||||
});
|
||||
let message1 = JSON.parse(jsonResult);
|
||||
userMessage = {
|
||||
certType: '02',
|
||||
certNo: message1.SocialSecurityNumber,
|
||||
psnCertType: '02',
|
||||
};
|
||||
userCardInfo.value = {
|
||||
certType: '02',
|
||||
certNo: message1.SocialSecurityNumber,
|
||||
psnCertType: '02',
|
||||
busiCardInfo: message1.BusiCardInfo,
|
||||
};
|
||||
break;
|
||||
}
|
||||
readCardLoading.value = false;
|
||||
if (userMessage.certNo) {
|
||||
let selectRows = chargeListRef.value.getSelectionRows();
|
||||
if (selectRows.length == 0) {
|
||||
proxy.$modal.msgWarning('请选择一条收费项目');
|
||||
return;
|
||||
}
|
||||
chargeItemIdList.value = selectRows.map((item) => {
|
||||
return item.id;
|
||||
});
|
||||
totalAmount.value = selectRows.reduce((accumulator, currentRow) => {
|
||||
return accumulator + (currentRow.totalPrice || 0);
|
||||
}, 0);
|
||||
precharge({
|
||||
patientId: props.patientInfo.patientId,
|
||||
encounterId: props.patientInfo.encounterId,
|
||||
chargeItemIds: chargeItemIdList.value,
|
||||
ybMdtrtCertType: userCardInfo.value.psnCertType,
|
||||
busiCardInfo: userCardInfo.value.busiCardInfo,
|
||||
generateSourceEnum: 2,
|
||||
sourceBillNo: props.surgeryInfo.surgeryNo,
|
||||
}).then((res) => {
|
||||
if (res.code == 200 && res.data) {
|
||||
paymentId.value = res.data.paymentId;
|
||||
totalAmount.value = res.data.details?.find((item) => item.payEnum == 220000)?.amount ?? 0;
|
||||
details.value = res.data.details || [];
|
||||
chargeItemIdList.value = selectRows.map((item) => {
|
||||
return item.id;
|
||||
});
|
||||
chargedItems.value = selectRows;
|
||||
consumablesIdList.value = selectRows
|
||||
.filter((item) => {
|
||||
return item.serviceTable == 'wor_device_request';
|
||||
})
|
||||
.map((item) => {
|
||||
return item.id;
|
||||
});
|
||||
openDialog.value = true;
|
||||
} else {
|
||||
proxy.$modal.msgError(res?.msg || '预结算失败');
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('调用失败:', error);
|
||||
readCardLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 行合并方法
|
||||
function objectSpanMethod({ row, column, rowIndex, columnIndex }) {
|
||||
if (columnIndex === 10) {
|
||||
if (!row.paymentId) {
|
||||
return [1,1];
|
||||
}
|
||||
let spanCount = 1;
|
||||
if (rowIndex === 0 || chargeList.value[rowIndex - 1].paymentId !== row.paymentId) {
|
||||
for (let i = rowIndex + 1; i < chargeList.value.length; i++) {
|
||||
if (chargeList.value[i].paymentId === row.paymentId) {
|
||||
spanCount++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return [spanCount, 1];
|
||||
} else {
|
||||
return [0, 0];
|
||||
}
|
||||
}
|
||||
return [1, 1];
|
||||
}
|
||||
|
||||
// 打印功能
|
||||
function printCharge(row) {
|
||||
let rows = [];
|
||||
chargeList.value.forEach((item, index) => {
|
||||
if (item.paymentId === row.paymentId) {
|
||||
rows.push(item);
|
||||
}
|
||||
});
|
||||
chargedItems.value = rows;
|
||||
getChargeInfo({ paymentId: row.paymentId }).then((res) => {
|
||||
if (res.data && res.data.detail) {
|
||||
const amountDetail = res.data.detail?.find((item) => item.payEnum == 220000);
|
||||
if (amountDetail) {
|
||||
totalAmount.value = amountDetail.amount || 0;
|
||||
rows.forEach((item) => {
|
||||
if (item.actualPrice === undefined || item.actualPrice === null) {
|
||||
item.actualPrice = 0;
|
||||
}
|
||||
if (item.discountAmount === undefined || item.discountAmount === null) {
|
||||
item.discountAmount = 0;
|
||||
}
|
||||
if (item.discountRate === undefined || item.discountRate === null) {
|
||||
item.discountRate = 100;
|
||||
}
|
||||
});
|
||||
}
|
||||
const enhancedPrintData = {
|
||||
...res.data,
|
||||
selectedRow: row,
|
||||
chargedItems: rows,
|
||||
};
|
||||
nextTick(() => {
|
||||
proxy.$refs['chargeDialogRef'].printReceipt(enhancedPrintData);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
:deep(.no-hover-column) .cell:hover {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
:deep(.el-table__body) tr:hover td.no-hover-column {
|
||||
background-color: inherit !important;
|
||||
}
|
||||
</style>
|
||||
38
openhis-ui-vue3/src/views/charge/threePayRecord/components/api.js
Executable file
38
openhis-ui-vue3/src/views/charge/threePayRecord/components/api.js
Executable file
@@ -0,0 +1,38 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 获取网银支付参数列表
|
||||
export function getList (data) {
|
||||
return request ({
|
||||
url: '/three-part/pay/page',
|
||||
method: 'get',
|
||||
params:data,
|
||||
});
|
||||
}
|
||||
|
||||
export function getPayinfo (data) {
|
||||
return request ({
|
||||
url: '/three-part/pay/pay-query?paymentId='+data.paymentId,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
export function returnfee (data) {
|
||||
return request ({
|
||||
url: '/three-part/pay/return-bill?paymentId='+data.paymentId,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
export function returnFeednext (data) {
|
||||
return request ({
|
||||
url: '/three-part/pay/return-goods?paymentId='+data.paymentId,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
export function returnResult (data) {
|
||||
return request ({
|
||||
url: '/three-part/pay/return-query?id='+data.id,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
120
openhis-ui-vue3/src/views/charge/threePayRecord/index.vue
Executable file
120
openhis-ui-vue3/src/views/charge/threePayRecord/index.vue
Executable file
@@ -0,0 +1,120 @@
|
||||
<template>
|
||||
<div class="app-continer">
|
||||
<el-form :model="queryParams" ref="queryRef" :inline="true">
|
||||
<el-form-item label="患者姓名" prop="patientName">
|
||||
<el-input v-model="queryParams.searchKey" placeholder="请输入患者姓名" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-table :data="recordList" v-loading="loading" border ref="tableRef">
|
||||
<el-table-column label="患者姓名" align="center" prop="patientName" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="支付单号" align="center" prop="paymentBusNo" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="交易金额(元)" align="right" prop="txnAmt" header-align="center" width="100"
|
||||
:show-overflow-tooltip="true">
|
||||
</el-table-column>
|
||||
<el-table-column label="交易类型" align="center" prop="tranType" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="支付方式" align="center" prop="payType" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="交易时间" align="center" prop="txnTime" :show-overflow-tooltip="true">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.txnTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="原交易类型" align="center" prop="orgTranType" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="原交易类型" align="center" prop="orgTranType" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="第三方优惠说明" align="center" prop="otherMsg" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="错误信息" align="center" prop="errMsg" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="查询结果" align="center" prop="queryResult" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="查询结果说明" align="center" prop="queryResultMsg" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="操作" align="center" prop="paymentEnum_enumText" width="340">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" link :disabled="!scope.row.paymentId"
|
||||
@click="getPayInfo(scope.row.paymentId)">支付结果查询</el-button>
|
||||
<el-button type="warning" link :disabled="!scope.row.paymentId"
|
||||
@click="returnFee(scope.row.paymentId)">退费</el-button>
|
||||
<el-button type="danger" link auto-insert-space :disabled="!scope.row.paymentId"
|
||||
@click="returnFeeNext(scope.row.paymentId)">隔天退费</el-button>
|
||||
<el-button type="success" link @click="returnFeeResultQuery(scope.row.id)">退费结果查询</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
|
||||
@pagination="getLists" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="ClinicRecord">
|
||||
const { proxy } = getCurrentInstance();
|
||||
import {getList, getPayinfo, returnfee, returnFeednext, returnResult} from './components/api.js';
|
||||
|
||||
const total = ref(0);
|
||||
const queryParams = ref({
|
||||
pageNo: 1,
|
||||
pageSize: 100,
|
||||
searchKey: '',
|
||||
});
|
||||
const recordList = ref([]);
|
||||
const loading = ref(false);
|
||||
const getPayInfo = (paymentId) => {
|
||||
console
|
||||
getPayinfo({ paymentId }).then((res) => {
|
||||
proxy.$message.success('支付结果查询成功');
|
||||
console.log(res);
|
||||
});
|
||||
};
|
||||
const returnFee = (paymentId) => {
|
||||
returnfee({ paymentId }).then((res) => {
|
||||
proxy.$message.success('退费成功');
|
||||
console.log(res);
|
||||
});
|
||||
};
|
||||
const returnFeeNext = (paymentId) => {
|
||||
returnFeednext({ paymentId }).then((res) => {
|
||||
proxy.$message.success('隔天退费成功');
|
||||
console.log(res);
|
||||
});
|
||||
};
|
||||
const returnFeeResultQuery = (id) => {
|
||||
returnResult({ id }).then((res) => {
|
||||
proxy.$message.success(res.data);
|
||||
console.log(res);
|
||||
});
|
||||
};
|
||||
const handleQuery = () => {
|
||||
//queryParams.value.pageNum = 1;
|
||||
getList(queryParams.value);
|
||||
};
|
||||
const resetQuery = () => {
|
||||
proxy.resetForm('queryRef');
|
||||
handleQuery();
|
||||
};
|
||||
const getLists = async () => {
|
||||
loading.value = true;
|
||||
getList(queryParams.value).then((res) => {
|
||||
loading.value = false;
|
||||
recordList.value = res.data.records;
|
||||
total.value = res.data.total;
|
||||
});
|
||||
};
|
||||
getLists();
|
||||
</script>
|
||||
<style scoped>
|
||||
.app-continer {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.el-dialog {
|
||||
height: 90vh !important;
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.el-textarea__inner {
|
||||
resize: none;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user