Files
his/openhis-ui-vue3/src/views/inHospitalManagement/charge/register/components/patientRegister.vue
chenqi abc0674531 ```
docs(release-notes): 添加住院护士站划价功能说明和发版记录

- 新增住院护士站划价服务流程说明文档,详细描述了从参数预处理到结果响应的五大阶段流程
- 包含耗材类医嘱和诊疗活动类医嘱的差异化处理逻辑
- 添加完整的发版内容记录,涵盖新增菜单功能和各模块优化点
- 记录了住院相关功能的新增和门诊业务流程的修复
```
2025-12-25 14:13:14 +08:00

681 lines
20 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
v-model="dialogVisible"
top="6vh"
:width="width"
:title="props.title"
@open="openAct"
@closed="closedAct"
:z-index="20"
destroy-on-close
>
<el-scrollbar height="650px">
<PatientInfoComp
:patientInfo="props.patientInfo"
:inHospitalInfo="props.inHospitalInfo"
:registrationType="props.registrationType"
:initOptions="initOptions"
:noFile="noFile"
ref="patientInfoRef"
:is-registered="props.isRegistered"
@onChangFeeType="onChangFeeType"
@carReading="onCarRead"
/>
<!-- <PatientRelationList
class="relationList"
:patCode="patientInfo.code"
ref="PatientRelationListRef"
/> -->
<!--联系人组件 -->
<RegisterForm
:code="code"
ref="RegisterFormRef"
:patientInfo="patientApiInfo"
:initOptions="initOptions"
:alreadyEdit="alreadyEdit"
:inHospitalInfo="inHospitalInfo"
:noFile="noFile"
:is-registered="props.isRegistered"
/>
</el-scrollbar>
<template v-slot:footer>
<div class="advance-container">
<div v-if="currentFeeType !== 'hipCash'" class="payment-item">
<span>{{ payType() }}支付</span>
<el-input
ref="txtCodeRef"
v-model="txtCode"
style="width: 300px; margin-left: 10px"
:placeholder="payType() + '支付码'"
/>
<el-button link type="primary" @click="handleWxPay()" style="margin-left: 10px"
>扫码支付</el-button
>
<el-button link type="primary" @click="getWxPayResult()">查看结果</el-button>
</div>
<el-space>
<div>缴费预交金</div>
<el-input
style="width: 142px"
placeholder="请输入"
v-model="advance"
@input="handleAdvanceInput"
:formatter="handleAdvanceFormatter"
:parser="handleAdvanceParser"
:disabled="alreadyEdit"
></el-input>
<div
class="feeType"
:class="currentFeeType == typeitem.type ? 'activeFeeType' : ''"
v-for="typeitem in feeTypeOptions"
:key="typeitem.type"
@click="
() => {
!alreadyEdit && (currentFeeType = typeitem.type);
payEnum = typeitem.payEnum;
}
"
:style="{ cursor: alreadyEdit ? 'not-allowed' : 'pointer' }"
>
<svg-icon
:icon-class="typeitem.type"
:color="currentFeeType == typeitem.type ? '#13C0B3' : '#666666'"
height="18px"
width="18px"
style="margin-right: 4px"
/>
{{ typeitem.label }}
</div>
</el-space>
</div>
<el-button size="fixed" class="margin-left-auto" @click="cancelAct">取消 </el-button>
<el-button v-if="!props.isRegistered" size="fixed" type="primary" @click="handleSubmit">
登记
</el-button>
</template>
</el-dialog>
</template>
<script setup>
const { proxy } = getCurrentInstance();
import { ElMessageBox } from 'element-plus';
import PatientInfoComp from './patientInfo.vue';
import RegisterForm from './registerForm.vue';
import { noFilesRegister, registerInHospital, getProvincesAndCities } from './api';
import { getInit } from '../../../../doctorstation/components/api';
import { useRouter } from 'vue-router';
import { wxPay, WxPayResult } from '../../../../charge/cliniccharge/components/api';
import printUtils from '@/utils/printUtils';
const txtCode = ref('');
const router = useRouter();
const emits = defineEmits(['okAct', 'cancelAct']);
const props = defineProps({
title: '',
registrationType: {
type: [String, Boolean, Number], // 根据实际类型调整
default: null, // 或者 false、'' 等
},
patientInfo: {
type: Object,
},
inHospitalInfo: {
type: Object,
},
alreadyEdit: {
type: Boolean,
default: false,
},
noFile: {
type: Boolean,
default: false,
},
isRegistered: {
type: Boolean,
default: false, // false 表示待登记true 表示已登记
},
});
watch(
() => props.registrationType,
(newValue) => {
console.log('registrationType changed:', newValue);
},
{ immediate: true }
);
const dialogVisible = defineModel('dialogVisible', {
type: Boolean,
default: false,
});
const code = defineModel('code');
import { ElMessage } from 'element-plus';
const width = '1128px';
const patientApiInfo = ref({});
const initOptions = ref({});
const payEnum = ref(220400);
/* 取消 */
const cancelAct = () => {
emits('cancelAct');
};
const patientInfoRef = ref();
/* 预交金 */
const advancePaymentVisible = ref(false);
const jumpToYbRegisterEdit = () => {
router
.push({
path: '/ybmanagement/ybInhospital/ybregisterEdit',
query: {
encounterId: '1993854019030441985',
},
})
.catch((error) => {
console.error('跳转医保登记页面失败:', error);
});
};
/* 登记 */
const handleSubmit = () => {
let params = {
inHospitalInfo: {},
payEnum: 0,
};
params.inHospitalInfo.payEnum = payEnum.value;
params.payEnum = payEnum.value;
console.log('params==========>', JSON.stringify(patientInfoRef?.value.getPatientForm()));
if (props.noFile) {
const paramsDic = patientInfoRef?.value.getPatientForm();
const paramsDic1 = RegisterFormRef.value.submitForm;
if (!paramsDic?.name) {
ElMessage({
type: 'error',
message: '请输入患者姓名',
});
return;
} else if (!paramsDic?.phone) {
ElMessage({
type: 'error',
message: '请输入联系方式',
});
return;
} else if (!paramsDic?.age) {
ElMessage({
type: 'error',
message: '请输入年龄',
});
return;
} else if (!paramsDic1?.inHospitalOrgId) {
ElMessage({
type: 'error',
message: '请选择入院科室',
});
return;
} else if (!paramsDic1?.wardLocationId) {
ElMessage({
type: 'error',
message: '请选择入院病区',
});
return;
} else if (!paramsDic1?.diagnosisDefinitionId) {
ElMessage({
type: 'error',
message: '请选择入院诊断',
});
return;
}
// else if (!paramsDic1?.diagnosisDesc) {
// ElMessage({
// type: 'error',
// message: '请输入诊断描述',
// });
// return;
// }
RegisterFormRef.value.validateData(async () => {
params.inHospitalInfo = RegisterFormRef.value.submitForm;
params.inHospitalInfo.payEnum = payEnum.value;
params.patientInformation = patientInfoRef?.value.getPatientForm();
if (params.patientInformation.idCard) {
// 验证身份证号长度是否为18位
const idCard = params.patientInformation.idCard.toString();
if (idCard.length === 18) {
params.patientInformation.birthDate =
idCard.substring(6, 10) +
'-' +
idCard.substring(10, 12) +
'-' +
idCard.substring(12, 14);
}
}
console.log('params', params);
params.inHospitalInfo.balanceAmount = advance.value;
const performRegistration = () => {
noFilesRegister(params).then((res) => {
if (res.code == 200) {
ElMessage.success(res.msg);
advancePaymentVisible.value = true;
ElMessage.success(res.msg);
// 打印预交金收据
printDepositReceipt(props.patientInfo, params.inHospitalInfo);
cancelAct();
// 询问是否需要医保登记
// ElMessageBox.confirm('是否需要进行医保登记?', '医保登记确认', {
// confirmButtonText: '确认',
// cancelButtonText: '取消',
// type: 'info',
// })
// .then(() => {
// // 准备传递的数据
// const cardData = {
// patientInfo: params.patientInformation,
// inHospitalInfo: params.inHospitalInfo,
// encounterId: params.inHospitalInfo.encounterId,
// };
// // 跳转到医保登记页面
// try {
// router
// .push({
// path: '/ybmanagement/ybInhospital/ybregisterEdit',
// query: {
// encounterId: props.patientInfo.encounterId,
// cardData: encodeURIComponent(JSON.stringify(cardData)),
// cardType: 'inHospital',
// operationType: 'HospitalizationRegistration',
// },
// })
// .then(() => {
// console.log('路由跳转成功');
// })
// .catch((error) => {
// console.error('路由跳转失败:', error);
// ElMessage.error('跳转到医保登记页面失败');
// });
// } catch (error) {
// console.error('跳转异常:', error);
// }
// })
// .catch(() => {
// // 用户取消医保登记,关闭当前弹窗
// emits('okAct');
// });
} else {
ElMessage.error(res.msg);
}
});
};
if (advance.value == 0) {
ElMessageBox.confirm('住院预交金额未填写,确认登记吗', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
performRegistration();
})
.catch(() => {});
} else {
performRegistration();
}
});
} else {
params.balanceAmount = advance.value;
params.patientId = props.patientInfo.patientId;
RegisterFormRef.value.validateData(async () => {
params = { ...params, ...RegisterFormRef.value.submitForm };
const performRegistration = () => {
console.log('params', params);
registerInHospital(params).then((res) => {
if (res.code == 200) {
ElMessage.success(res.msg);
advancePaymentVisible.value = true;
// 打印预交金收据
printDepositReceipt(
props.patientInfo,
params,
RegisterFormRef.value.medicalInsuranceTitle
);
// 自费不需要弹医保
if (params.contractNo != '0000') {
// 询问是否需要医保登记
ElMessageBox.confirm('是否需要进行医保登记?', '医保登记确认', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'info',
})
.then(() => {
// 准备传递的数据
const cardData = {
patientInfo: props.patientInfo,
inHospitalInfo: params,
};
// 跳转到医保登记页面
try {
router
.push({
path: '/ybmanagement/ybInhospital/ybregisterEdit',
query: {
encounterId: props.patientInfo.encounterId,
cardData: encodeURIComponent(JSON.stringify(cardData)),
cardType: 'inHospital',
operationType: 'HospitalizationRegistration',
certType: props.patientInfo.certType,
},
})
.then(() => {
console.log('路由跳转成功');
})
.catch((error) => {
console.error('路由跳转失败:', error);
ElMessage.error('跳转到医保登记页面失败');
});
} catch (error) {
console.error('跳转异常:', error);
}
})
.catch(() => {
// 用户取消医保登记,关闭当前弹窗
emits('okAct');
});
}
cancelAct();
} else {
ElMessage.error(res.msg);
}
});
};
if (advance.value == 0) {
ElMessageBox.confirm('住院预交金额未填写,确认登记吗', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
performRegistration();
})
.catch(() => {});
} else {
performRegistration();
}
});
}
};
const openAct = () => {
console.log(props.patientInfo, 'patientRegister.vue');
console.log(props.inHospitalInfo, 'inHospitalInfo.vue');
/* 初始化数据 */
advance.value = props.inHospitalInfo.balanceAmount || 0;
advancePaymentVisible.value = false;
RegisterFormRef.value.init();
};
const closedAct = () => {
dialogVisible.value = false;
if (patientInfoRef.value?.isEditing) {
patientInfoRef.value.isEditing = false;
}
};
onMounted(() => {
getInit().then((res) => {
console.log('getInit=========>', JSON.stringify(res.data));
initOptions.value = res.data;
});
});
/* 登记 */
const RegisterFormRef = ref();
const feeTypeOptions = reactive([
{
type: 'hipCash',
payEnum: 220400,
label: '现金',
},
{
type: 'hipAlipay',
payEnum: 220200,
label: '支付宝',
},
{
type: 'wechat',
payEnum: 220100,
label: '微信',
},
{
type: 'hipPayCard',
payEnum: 220300,
label: '银行卡',
},
]);
const advance = ref('0.00');
const currentFeeType = ref('hipCash');
/* 预交金录入框格式 */
const handleAdvanceInput = (value) => {
if (value.length === 1 && value === '.') {
value = '0.';
} else {
advance.value = value.replace(/[^\d.]/g, '').replace(/^(\d*\.\d{2}).*$/, '$1');
}
};
const handleAdvanceFormatter = (value) => {
return `¥ ${value}`;
};
const handleAdvanceParser = (value) => {
return value.replace(/\$\s?|(,*)/g, '');
};
const medicalInsuranceVisible = ref(false);
const medicalInsuranceTitle = ref('');
/* 患者费别变更 */
const onChangFeeType = () => {
medicalInsuranceTitle.value = '医保信息'; //医保信息、医保登记
medicalInsuranceVisible.value = true;
};
/* 打印预交金收据 */
const printDepositReceipt = async (patientInfo, inHospitalInfo, medicalInsuranceTitle) => {
try {
// 构造支付方式详情文本
const paymentDetails = `现金 ${
currentFeeType.value === 'hipCash' ? advance.value || '0.00' : '0.00'
} 微信 ${currentFeeType.value === 'wechat' ? advance.value || '0.00' : '0.00'} 支付宝 ${
currentFeeType.value === 'hipAlipay' ? advance.value || '0.00' : '0.00'
} 银行 ${currentFeeType.value === 'hipPayCard' ? advance.value || '0.00' : '0.00'}`;
// 构造打印数据
const printData = {
// 患者基本信息
patientName: patientInfo.patientName || '', // 姓名
patientId: patientInfo.idCard || patientInfo.patientCode || '', // ID号
contractName: patientInfo.contractName || '自费', // 医保类别
// 住院信息
encounterNo: inHospitalInfo.encounterNo || '', // 住院号
inHospitalOrgName: inHospitalInfo.inHospitalOrgName || '', // 机构名称
// 费用信息
balanceAmount: advance.value || '0.00', // 金额
amountInWords: convertToChineseNumber(advance.value || '0.00'), // 人民币大写
// 支付方式详情
paymentDetails: paymentDetails,
// 时间信息
currentTime: new Date().toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
}),
// 其他信息
cashier: userStore?.nickName || '', // 收款人(收费员)
medicalInsuranceTitle: medicalInsuranceTitle || '', // 医保标题信息
};
console.log(printData, 'dayin 预交金printData');
// 直接导入并使用指定的预交金打印模板
const templateModule = await import('@/components/Print/AdvancePayment.json');
let template = templateModule.default || templateModule;
// 使用printUtils执行打印
await printUtils.executePrint(printData, template);
console.log('预交金收据打印成功');
} catch (error) {
console.error('打印失败:', error);
ElMessage.error('打印失败: ' + error.message);
}
};
/* 将数字转换为人民币大写 */
const convertToChineseNumber = (amount) => {
// 数字转大写
const digits = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];
const units = ['', '拾', '佰', '仟', '万', '拾', '佰', '仟', '亿'];
const decimalUnits = ['角', '分'];
let [integer, decimal] = amount.toString().split('.');
decimal = decimal || '00';
decimal = decimal.padEnd(2, '0').substring(0, 2);
let result = '';
// 处理整数部分
if (parseInt(integer) === 0) {
result += '零元';
} else {
for (let i = 0; i < integer.length; i++) {
const digit = parseInt(integer[i]);
const position = integer.length - i - 1;
if (digit !== 0) {
result += digits[digit] + units[position];
} else {
// 避免连续的零
if (i > 0 && parseInt(integer[i - 1]) !== 0) {
result += digits[digit];
}
// 但需要保留万、亿等单位
if (position % 4 === 0 && position > 0) {
result += units[position];
}
}
}
result += '元';
}
// 处理小数部分
if (parseInt(decimal) === 0) {
result += '整';
} else {
if (parseInt(decimal[0]) > 0) {
result += digits[parseInt(decimal[0])] + decimalUnits[0];
}
if (parseInt(decimal[1]) > 0) {
result += digits[parseInt(decimal[1])] + decimalUnits[1];
}
}
return result;
};
/* 导入用户信息 */
import useUserStore from '@/store/modules/user';
const userStore = useUserStore();
function handleWxPay() {
wxPay({
// 支付码
txtCode: txtCode.value,
// 收费项id 住院怎么给
chargeItemIds: props.chargeItemIds,
encounterId: props.patientInfo.encounterId,
// 支付id 住院怎么给
id: props.paymentId,
// 支付详情 住院怎么给 格式[{ payEnum: 220100, amount: 0.0, payLevelEnum: 2 }]
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,
});
}
// 根据不同支付方式,显示不同的支付方式详情
const payType = () => {
switch (currentFeeType.value) {
case 'hipCash':
return '现金';
case 'hipAlipay':
return '支付宝';
case 'wechat':
return '微信卡';
case 'hipPayCard':
return '银行卡';
default:
return '';
}
};
// 读卡操作
const onCarRead = (a) => {
console.log('读卡操作:', a);
};
</script>
<style lang="scss" scoped>
.patientRegister-container {
height: 700px;
overflow-y: auto;
}
.advance-container {
width: 660px;
display: flex;
flex-direction: column;
.payment-item {
display: flex;
align-items: center;
margin-bottom: 12px;
}
.feeType {
display: flex;
align-items: center;
height: 32px;
padding: 0px 8px;
color: #666666;
border-radius: 4px;
cursor: pointer;
:deep(.svg-icon) {
color: #666666;
}
}
.activeFeeType {
color: #13c0b3;
background: rgba(19, 192, 179, 0.1);
:deep(.svg-icon) {
color: #13c0b3;
}
}
}
</style>