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

423 lines
10 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<el-dialog
title="确认退费"
v-model="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 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 { cancelRegister } from './outpatientregistration';
import { computed, watch, reactive, ref, getCurrentInstance } from 'vue';
import { Delete } from '@element-plus/icons-vue';
import useUserStore from '@/store/modules/user';
import { formatDateStr } from '@/utils/index';
// 获取费用性质文本
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: [],
},
medfee_paymtd_code: {
type: Array,
default: () => [],
},
feeType: {
type: String,
default: '',
},
contractName: {
type: String,
default: '', // 新增:接收费用性质名称
},
registerInfo: {
type: Object,
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);
if (parseFloat(displayAmount.value) < formData.totalAmount) {
proxy.$modal.msgError('请输入正确的金额');
return;
}
// 获取当前时间作为退号操作日期
const returnDate = formatDateStr(new Date(), 'YYYY-MM-DD HH:mm:ss');
// 获取当前用户信息作为操作工号(使用用户管理中的用户账号)
// userStore.name 对应后端的 userName用户账号如 'admin'
const operatorId = userStore.name || null; // 退号操作工号(用户账号)
const operatorName = userStore.nickName || userStore.name || ''; // 退号操作人姓名
// 计算退款总金额
const refundAmount = formData.selfPay.reduce((sum, item) => sum + (Number(item.amount) || 0), 0);
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: returnDate, // 退号操作日期
operatorId: operatorId, // 退号操作工号用户ID
operatorName: operatorName, // 退号操作人姓名
refundAmount: refundAmount, // 退款金额
// 原挂号信息
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 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');
}
</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;
}
</style>