版本更新

This commit is contained in:
Zhang.WH
2025-09-03 15:54:41 +08:00
parent 0b93d16b64
commit 8f82322d10
3290 changed files with 154339 additions and 23829 deletions

View File

@@ -0,0 +1,50 @@
import request from '@/utils/request'
// 获取预交金信息初期数据列表
export function getDepositInfo(query) {
return request({
url: '/inhospital-charge/advance-payment/advance-payment-info',
method: 'get',
params: query
})
}
// 获取预交金信息初期数据列表
export function getDepositInfoPage(params) {
return request({
url: '/inhospital-charge/advance-payment/advance-payment-flow',
method: 'get',
params: params
})
}
// 获取患者信息 分页显示
export function getPatientInfoPage(query) {
return request({
url: '/deposit-manage/deposit-patient-page',
method: 'get',
params: query
})
}
/**
* 收费
*/
export function savePayment(data) {
return request({
url: '/inhospital-charge/advance-payment/in-advance-payment',
method: 'post',
data: data
})
}
/**
* 退费
*/
export function refund(data) {
return request({
url: '/inhospital-charge/advance-payment/out-advance-payment',
method: 'post',
data: data
})
}

View File

@@ -0,0 +1,267 @@
<template>
<el-dialog
title="确认收费"
v-model="props.open"
width="700px"
append-to-body
destroy-on-close
@close="close"
>
<div>
<el-form
:model="form"
:rules="rules"
ref="chargeDialogRef"
label-width="110px"
label-position="left"
>
<el-text size="large">
<!-- <el-form-item label="费用性质:" prop="currentDate"> {{ '自费' }} </el-form-item> -->
</el-text>
<!-- 自费支付 -->
<div class="payment-container">
<!-- <el-form-item label="支付方式:" prop="payEnum" style="display: flex">
<el-select
v-model="form.payEnum"
placeholder="选择支付方式"
style="width: 160px"
@change="clearAmount(index)"
>
<el-option
v-for="payEnum in props.payLists"
:key="payEnum.value"
:label="payEnum.label"
:value="payEnum.value"
:disabled="isMethodDisabled(payEnum.value)"
/>
</el-select>
</el-form-item> -->
<el-form-item label="支付金额:" prop="amount">
<div class="suffix-wrapper">
<el-input-number
v-model="form.amount"
:precision="2"
:min="0"
:controls="false"
placeholder="金额"
class="amount-input"
@change="handleAmountChange"
/>
<span class="suffix-text"></span>
</div>
</el-form-item>
</div>
<!-- 金额汇总 -->
<div class="summary">
<el-space :size="30">
<div class="summary-item">
<el-form-item label="实收合计:" prop="displayAmount">
<el-text type="success">
{{ form.displayAmount ? form.displayAmount : 0 + ' 元' }}
</el-text>
</el-form-item>
</div>
</el-space>
</div>
</el-form>
</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 { savePayment } from './api';
import { computed, watch, reactive, ref, getCurrentInstance, nextTick } from 'vue';
const props = defineProps({
open: {
type: Boolean,
default: false,
},
totalAmount: {
type: Number,
default: 0.0,
},
patientInfo: {
type: Object,
default: undefined,
},
payLists: {
type: Array,
default: () => [],
},
});
const { proxy } = getCurrentInstance();
const data = reactive({
form: {},
rules: {},
});
const { queryParams, form, rules } = toRefs(data);
const emit = defineEmits(['close']);
const payMethods = ref(undefined);
async function submit() {
form.value.patientId = props.patientInfo.patientId;
form.value.encounterId = props.patientInfo.encounterId;
form.value.accountId = props.patientInfo.accountId;
console.log(props.patientInfo, 'patientInfo');
savePayment(form.value).then((res) => {
if (res.code == 200) {
reset();
emit('close', 'success');
}
});
}
/** 重置操作表单 */
function reset() {
form.value = {
patientId: undefined,
encounterId: undefined,
displayAmount: 0,
payEnum: undefined,
amount: undefined,
};
proxy.resetForm('chargeDialogRef');
}
// 检查支付方式是否已使用
const isMethodDisabled = (payEnum) => {
return null;
};
/**
* 处理金额变化事件
*
* 当表单中的金额发生变化时,将显示金额设置为实际金额
*/
function handleAmountChange() {
form.value.displayAmount = form.value.amount;
}
/**
* 变化支付方式事件
*
*/
function clearAmount() {
form.value.amount = 0;
}
function close() {
reset();
emit('close');
}
</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>

View File

@@ -0,0 +1,252 @@
<template>
<el-drawer v-model="drawerVisible" :title="title" :before-close="handleClose" size="70%">
<div class="drawer-content">
<!-- 筛选区域 -->
<el-form :inline="true" :model="queryParams" class="filter-form">
<el-form-item label="在院病区" prop="wardLocationId">
<el-select
v-model="queryParams.wardLocationId"
placeholder="请选择"
clearable
style="width: 160px"
>
<el-option
v-for="ward in wardListOptions"
:key="ward.value"
:label="ward.label"
:value="ward.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item prop="searchKey">
<el-input
v-model="queryParams.searchKey"
placeholder="请输入流水号/住院号/患者姓名"
style="width: 230px"
clearable
></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="getList">查询</el-button>
</el-form-item>
</el-form>
<!-- 表格区域 -->
<el-table
:data="patientData"
style="width: 100%"
class="patient-table"
:row-class-name="tableRowClassName"
border
>
<el-table-column type="index" align="center" label="序号" width="60" />
<el-table-column prop="patientName" align="center" label="姓名" />
<el-table-column prop="wardName" align="center" label="病区" />
<el-table-column prop="bedName" align="center" label="床号" />
<el-table-column prop="busNo" align="center" label="住院号" />
<el-table-column label="操作" width="80" align="center">
<template #default="scope">
<el-button link type="primary" size="small" @click.stop="viewPatient(scope.row)">
查看
</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="getList"
/>
</div>
</el-drawer>
</template>
<script setup>
import { reactive } from 'vue';
import { getDepositInfo } from './api';
// Props
const props = defineProps({
title: {
type: String,
default: '患者列表',
},
drawerVisible: {
type: Boolean,
default: false,
},
wardListOptions: {
type: Array,
default: () => [],
},
});
const data = reactive({
form: {},
queryParams: {
pageNo: 1,
pageSize: 10,
searchKey: undefined,
wardLocationId: undefined,
},
rules: {},
});
const { queryParams, form, rules } = toRefs(data);
// Emits
const emits = defineEmits(['confirm', 'cancel', 'patientSelected']);
const total = ref(0);
// // v-model for drawer visibility
// const drawerVisible = defineModel('drawerVisible', {
// type: Boolean,
// default: false,
// })
const drawerVisible = ref(false);
// 筛选表单
const filterForm = reactive({
ward: '综合外科病区',
searchText: '',
});
const patientData = ref([]); // 当前页显示的数据
const currentPage = ref(1);
const pageSize = ref(10); // 和图片中每页大约10-15条类似这里设为10
const wardListOptions = ref([]);
const selectedPatient = ref(null); // 用于存储选中的患者
// 行高亮相关
const tableRowClassName = ({ row }) => {
if (selectedPatient.value && row.id === selectedPatient.value.id) {
return 'selected-row';
}
return '';
};
const handleRowClick = (row) => {
selectedPatient.value = row;
// console.log('Selected patient:', row);
};
const handlePageChange = (page) => {
currentPage.value = page;
const start = (page - 1) * pageSize.value;
const end = start + pageSize.value;
// 重新从筛选后的或全部数据中获取当前页
const sourceData = allPatientData.filter((p) => {
const wardMatch = filterForm.ward ? p.ward === filterForm.ward : true;
const textMatch = filterForm.searchText
? p.patientName.includes(filterForm.searchText) ||
p.admissionNumber.includes(filterForm.searchText) ||
p.masterIndex.includes(filterForm.searchText)
: true;
return wardMatch && textMatch;
});
patientData.value = sourceData.slice(start, end);
};
/**
* 查看患者信息
*
* @param patient 患者对象
*/
function viewPatient(patient) {
console.log('View patient:', patient);
selectedPatient.value = patient; // 选中患者
emits('patientSelected', selectedPatient.value); // 发送选中的患者数据
drawerVisible.value = false;
reset(); // 重置筛选条件
// 可以在这里做一些操作比如高亮行或者如果“查看”是选择并关闭则触发confirm
}
// Drawer methods
function handleClose() {
drawerVisible.value = false;
reset();
}
const cancelClick = () => {
drawerVisible.value = false;
emits('cancel');
};
const confirmClick = () => {
if (selectedPatient.value) {
emits('patientSelected', selectedPatient.value); // 发送选中的患者数据
}
emits('confirm'); // 触发通用的confirm事件
drawerVisible.value = false;
};
/**
* 打开抽屉
*/
function show() {
console.log('show', props);
wardListOptions.value = props.wardListOptions;
drawerVisible.value = props.drawerVisible;
getList();
}
/**
* 取得病人列表
*/
function getList() {
console.log('queryParams', queryParams.value);
getDepositInfo().then((res) => {
patientData.value = res.data.records;
total.value = res.data.total;
});
}
function reset() {
queryParams.value = {
pageNo: 1,
pageSize: 10,
searchKey: undefined,
wardLocationId: undefined,
};
}
defineExpose({
show,
});
</script>
<style lang="scss" scoped>
.drawer-content {
// padding: 0px 20px 20px 20px; // 顶部不需要padding让筛选栏贴近
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
}
.filter-form {
padding: 15px 0;
:deep(.el-form-item) {
margin-bottom: 0; // 减少筛选表单项的下边距
}
}
.patient-table {
flex-grow: 1; // 让表格占据剩余空间
margin-bottom: 20px;
:deep(.el-table__header th) {
background-color: #f0f2f5; // 表头背景色,更接近图片
color: #333;
font-weight: normal;
}
:deep(.el-table__row) {
cursor: pointer;
}
:deep(.selected-row) {
background-color: #ecf5ff !important; // Element Plus 选中行高亮颜色
}
}
.pagination-container {
padding: 0; // 移除分页组件的默认padding
margin-top: auto; // 将分页组件推到底部
}
</style>

View File

@@ -0,0 +1,259 @@
<template>
<el-dialog
title="确认退费"
v-model="props.open"
width="700px"
append-to-body
destroy-on-close
@close="close"
@open="open"
>
<div>
<el-form
:model="form"
:rules="rules"
ref="chargeDialogRef"
label-width="110px"
label-position="left"
>
<el-text size="large">
<!-- <el-form-item label="费用性质:" prop="currentDate"> {{ '自费' }} </el-form-item> -->
</el-text>
<!-- 自费支付 -->
<div class="payment-container">
<!-- <el-form-item label="支付方式:" prop="payEnum" style="display: flex">
<el-select
v-model="form.payEnum"
placeholder="选择支付方式"
style="width: 160px"
@change="clearAmount(index)"
>
<el-option
v-for="payEnum in props.payLists"
:key="payEnum.value"
:label="payEnum.label"
:value="payEnum.value"
:disabled="isMethodDisabled(payEnum.value)"
/>
</el-select>
</el-form-item> -->
<el-form-item label="退费金额:" prop="amount">
<div class="suffix-wrapper">
<el-input-number
v-model="form.amount"
:precision="2"
:min="0"
:max="props.patientInfo.balanceAmount"
:controls="false"
placeholder="金额"
class="amount-input"
@change="handleAmountChange"
/>
<span class="suffix-text"></span>
</div>
</el-form-item>
</div>
<!-- 金额汇总 -->
<div class="summary">
<el-space :size="30">
<div class="summary-item">
<el-form-item label="实退合计:" prop="displayAmount">
<el-text type="success">
{{ form.displayAmount ? form.displayAmount : 0 + ' 元' }}
</el-text>
</el-form-item>
</div>
</el-space>
</div>
</el-form>
</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 { refund } from './api';
import { reactive, ref, getCurrentInstance, nextTick } from 'vue';
const props = defineProps({
open: {
type: Boolean,
default: false,
},
totalAmount: {
type: Number,
default: 0.0,
},
patientInfo: {
type: Object,
default: undefined,
},
payLists: {
type: Array,
default: () => [],
},
});
const { proxy } = getCurrentInstance();
const data = reactive({
form: {},
rules: {},
});
const { queryParams, form, rules } = toRefs(data);
const emit = defineEmits(['close']);
const payMethods = ref(undefined);
async function submit() {
form.value.patientId = props.patientInfo.patientId;
form.value.encounterId = props.patientInfo.encounterId;
form.value.accountId = props.patientInfo.accountId;
console.log(props.patientInfo, 'patientInfo');
refund(form.value).then((res) => {
if (res.code == 200) {
reset();
emit('close', 'success');
}
});
}
function open() {
form.value.amount = props.patientInfo.balanceAmount;
}
/** 重置操作表单 */
function reset() {
form.value = {
patientId: undefined,
encounterId: undefined,
displayAmount: 0,
payEnum: undefined,
amount: undefined,
};
proxy.resetForm('chargeDialogRef');
}
/**
* 处理金额变化事件
*
* 当表单中的金额发生变化时,将显示金额设置为实际金额
*/
function handleAmountChange() {
form.value.displayAmount = form.value.amount;
}
function close() {
reset();
emit('close');
}
</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>

View File

@@ -0,0 +1,404 @@
<template>
<div class="container">
<!-- 顶部操作区域 -->
<el-card class="header-card" shadow="never">
<el-row :gutter="20" align="middle">
<el-col :span="6">
<span class="descriptions-item-label">住院号</span>
<el-input
v-model="queryParams.searchKey"
placeholder="请输入内容"
clearable
style="width: 300px"
@keyup.enter="getPatientInfo"
/>
<el-button type="primary" @click="getPatientInfo" style="margin-left: 10px">
查询
</el-button>
</el-col>
<el-col :span="18" style="text-align: right">
<el-space>
<el-button type="primary" @click="confirmCharge()">收预交金</el-button>
<el-button type="primary" @click="showPatient()">在院患者</el-button>
</el-space>
</el-col>
</el-row>
</el-card>
<!-- 患者信息区域 -->
<el-card class="patient-info-card" shadow="never">
<el-row align="middle" :gutter="20">
<el-avatar
:size="40"
src="https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png"
style="margin-left: 20px"
/>
<el-col :span="10">
<div>
<span
class="descriptions-item-label"
style="font-size: 16px; margin: 0 0"
v-if="patientInfo.patientName"
>
{{ patientInfo.patientName }} / {{ patientInfo.genderEnum_enumText }} /
{{ patientInfo.age }}
</span>
<span class="descriptions-item-label"> 住院号: </span>
<span class="descriptions-item-value"> {{ patientInfo.busNo }} </span>
</div>
</el-col>
<el-col :span="4" style="text-align: left; margin-top: 10px">
<span class="descriptions-item-label">预交金总额</span>
<el-text type="primary" size="large">
{{ patientInfo.totalAmount ? patientInfo.totalAmount.toFixed(2) + ' 元' : '0.00 元' }}
</el-text>
</el-col>
<el-col :span="4" style="text-align: left; margin-top: 10px">
<span class="descriptions-item-label">余额</span>
<el-text type="primary" size="large">
{{
patientInfo.balanceAmount ? patientInfo.balanceAmount.toFixed(2) + ' 元' : '0.00 元'
}}
</el-text>
</el-col>
</el-row>
<el-row :gutter="24" style="margin-top: 10px">
<el-col :span="23">
<span class="descriptions-item-label">在院科室/病区: </span>
<span class="descriptions-item-value" v-if="patientInfo.inHospitalOrgName">
{{ patientInfo.inHospitalOrgName }} /
{{
patientInfo.wardName +
formatValue(patientInfo.houseName) +
formatValue(patientInfo.bedName)
}}
</span>
</el-col>
<el-col :span="1">
<el-button type="primary" @click="refund()">退费</el-button>
</el-col>
</el-row>
</el-card>
<!-- 表格区域 -->
<el-card class="table-card" shadow="never">
<el-table
:data="tableData"
style="width: 100%"
:row-class-name="tableRowClassName"
v-loading="loading"
border
>
<!-- <el-table-column prop="payWay" label="支付方式" /> -->
<!-- <el-table-column prop="paymentEnum_enumText" label="状态" /> -->
<el-table-column type="index" label="序号" width="70" align="center" />
<el-table-column prop="paymentNo" label="收据号" width="280" align="center" />
<el-table-column prop="tenderedAmount" label="金额" align="center">
<template #default="scope">
<span :class="{ 'negative-amount': scope.row.tenderedAmount < 0 }">
{{
scope.row.tenderedAmount ? scope.row.tenderedAmount.toFixed(2) + ' 元' : '0.00 元'
}}
</span>
</template>
</el-table-column>
<el-table-column
prop="paymentEnum_enumText"
label="票据类型"
align="center"
min-width="120"
/>
<!-- <el-table-column prop="afterBalance" label="可退金额" min-width="120">
<template #default="scope">
<span>
{{
scope.row.afterBalance ? scope.row.afterBalance.toFixed(2) : scope.row.afterBalance
}}
</span>
</template>
</el-table-column> -->
<el-table-column prop="operateTime" label="收款时间" align="center" min-width="180" />
<el-table-column prop="enterer" label="收款员" align="center" min-width="100" />
<!-- <el-table-column label="操作" min-width="100" align="center" fixed="right">
<template #default="scope">
<el-button link type="primary" size="small">补打</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="getPatientInfo"
/>
</el-card>
<!-- 患者列表弹窗 -->
<PatientList
:drawerVisible="showPatientList"
ref="showPatientRef"
:wardListOptions="wardListOptions"
@patientSelected="handlePatientSelected"
/>
<ChargeDialog
ref="chargeListRef"
:open="openDialog"
@close="handleClose"
:patientInfo="patientInfo"
:payLists="payLists"
/>
<RefundDialog
:open="openRefundDialog"
@close="handleClose"
:patientInfo="patientInfo"
:payLists="payLists"
/>
</div>
</template>
<script setup>
import { ref, nextTick } from 'vue';
import { getDepositInfo, getDepositInfoPage } from './components/api';
import PatientList from './components/patientList.vue';
import ChargeDialog from './components/chargeDialog.vue';
import RefundDialog from './components/refundDialog.vue';
const showPatientList = ref(false);
const showPatientRef = ref();
const openDialog = ref(false);
const openRefundDialog = ref(false);
const chargeListRef = ref();
const loading = ref(false);
const tableData = ref([]);
const wardListOptions = ref(undefined);
const payLists = ref(undefined);
const total = ref(0);
const { proxy } = getCurrentInstance();
const patientInfo = ref({});
const queryParams = ref({
pageNo: 1,
pageSize: 10,
searchKey: undefined, // 供应商名称
searchKey: 'ZY202507310001',
});
const tableRowClassName = ({ row, rowIndex }) => {
if (row.amount < 0) {
// 根据图片,当金额为负数时,整行(或特定列)文字变红
// 这里我们给整行添加一个class然后在style中定义颜色
// 或者也可以只给特定列的文字变红,如金额列
return 'negative-row-text';
}
return '';
};
/**
* 获取患者信息
*/
function getPatientInfo() {
console.log(queryParams.searchKey, 'queryParams.searchKey');
if (!queryParams.value.searchKey) {
proxy.$modal.msgError('请先输入住院号!');
return;
}
console.log(queryParams.value, 'queryParams.value');
getDepositInfo({ busNo: queryParams.value.searchKey }).then((res) => {
if (res.code == 200 && res.data.records[0].encounterId) {
patientInfo.value = res.data.records[0];
getDepositInfoPage({ encounterId: res.data.records[0].encounterId }).then((res) => {
tableData.value = res.data;
});
}
});
}
/**
* 显示患者列表
*/
function showPatient() {
showPatientList.value = true;
nextTick(() => {
proxy.$refs['showPatientRef'].show();
});
}
// 确认收费
function confirmCharge() {
console.log(patientInfo.value, 'patientInfo.valueconfirmCharge');
if (patientInfo.value.patientId) {
openDialog.value = true;
} else {
proxy.$modal.msgError('请先选择病人!');
}
}
function refund() {
if (patientInfo.value.patientId) {
openRefundDialog.value = true;
} else {
proxy.$modal.msgError('请先选择病人!');
}
}
/** 选择病人 */
function handlePatientSelected(row) {
console.log(row, 'rowwwwwwwwhandlePatientSelected');
queryParams.value.searchKey = row.admissionNo;
patientInfo.value = row;
nextTick(() => {
getPatientInfo();
});
}
/** 重置操作表单 */
function reset() {
form.value = {
id: undefined,
patientName: undefined,
genderEnum_enumText: undefined,
ageString: undefined,
payWay: undefined,
patientId: undefined,
organizationId_dictText: undefined,
totalPrice: undefined,
deposit: undefined,
balanceAmount: undefined,
bedLocationId_dictText,
};
proxy.resetForm('formRef');
}
// 复制文本到剪贴板
async function copyText() {
console.log('复制文本:', form.value);
try {
// 使用 navigator.clipboard.writeText 复制文本
await navigator.clipboard.writeText(form.value.admissionNo);
proxy.$modal.msgSuccess('复制成功!');
} catch (err) {
proxy.$modal.msgError('复制失败!' + err);
}
}
function formatValue(value) {
return value ? '-' + value : '';
}
/**
* 处理关闭事件
*
* @returns {void} 无返回值
*/
function handleClose(str) {
openDialog.value = false;
openRefundDialog.value = false;
if (str === 'success') {
getPatientInfo();
proxy.$modal.msgSuccess('操作成功!');
}
}
</script>
<style lang="scss" scoped>
.container {
padding: 15px;
background-color: #f0f2f5; // 类似图片背景色
min-height: 90vh;
}
.header-card,
.patient-info-card,
.table-card {
margin-bottom: 15px;
border: none; // 移除卡片边框,更接近图片效果
:deep(.el-card__body) {
// 调整卡片内边距
padding: 15px;
}
}
.patient-info-card {
:deep(.el-card__body) {
padding-bottom: 0; // 患者信息卡片底部不需要太多padding
}
}
.patient-details {
margin-top: 15px;
:deep(.el-descriptions__label.el-descriptions__cell.is-bordered-label) {
background-color: #fafafa; // 表头背景色
}
:deep(td),
:deep(th) {
// 移除边框,更像图片
border: none;
}
}
:deep(.custom-label .el-input__inner) {
color: #ff7100 !important; // 橙色高亮
font-weight: bold;
}
.amount-highlight-balance {
color: #ff7100; // 橙色高亮
font-weight: bold;
}
// 表格样式调整
.el-table {
:deep(th) {
background-color: #f0f8ff !important; // 表头淡蓝色背景
color: #333;
font-weight: normal;
}
:deep(td),
:deep(th.is-leaf) {
border-bottom: 1px solid #ebeef5; // 只保留底部边框
border-left: none;
border-right: none;
border-top: none;
}
:deep(.el-table__row):hover > td {
// 鼠标悬浮时背景色
background-color: #f5f7fa;
}
}
.negative-amount {
color: red;
}
// 如果需要整行文字变红
.el-table .negative-row-text {
color: red;
td {
color: red !important; // 确保覆盖默认样式
}
.el-button--primary.is-link {
// 如果按钮也需要变红
color: red !important;
}
}
.action-red {
// 单独给退还按钮变红
color: red !important;
}
// 移除el-input-group__append的边框使其与输入框融为一体
:deep(.el-input-group__append) {
border-left: 0;
background-color: #409eff;
color: white;
.el-button {
color: white;
&:hover {
background-color: #66b1ff;
}
}
}
:deep(.custom-label .el-form-item__label) {
background-color: #fafafa; /* 设置背景色 */
padding: 4px 8px; /* 可选:添加一些内边距 */
border: #e9e8e8 solid 1px; /* 可选:添加边框 */
display: flex; /* 使用 flex 布局 */
align-items: center; /* 垂直居中 */
// justify-content: center; /* 水平居中 */
}
</style>

View File

@@ -0,0 +1,100 @@
import request from '@/utils/request'
/**
* 收费患者列表
*/
export function getList(queryParams) {
return request({
url: '/charge-manage/inpa-charge/encounter-patient-page',
method: 'get',
params: queryParams
})
}
/**
* 患者处方列表
*/
export function getChargeList(row) {
return request({
url: `/charge-manage/inpa-charge/patient-prescription?encounterId=${row.encounterId}&startTime=${row.startTime}&endTime=${row.endTime}`,
method: 'get',
})
}
/**
* 医保转自费
*/
export function changeToSelfPay(encounterId) {
return request({
url: '/charge-manage/inpa-charge/self-pay?encounterId=' + encounterId,
method: 'put',
})
}
/**
* 自费转医保
*/
export function changeToMedicalInsurance(encounterId) {
return request({
url: '/charge-manage/inpa-charge/medical-insurance?encounterId=' + encounterId,
method: 'put',
})
}
/**
* 收费
*/
export function savePayment(data) {
return request({
url: '/payment/payment/inpa-pay',
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/inpa-pre-pay',
method: 'post',
data: data
})
}
/**
* 取消预结算
*/
export function unprecharge(data) {
return request({
url: '/payment/payment/unprecharge',
method: 'post',
params: data
})
}
/**
* 发耗材
*/
export function dispenseMedicalConsumables(data) {
return request({
url: '/pharmacy-manage/medical-consumables-dispense/consumables-dispense',
method: 'put',
data: data
})
}

View File

@@ -0,0 +1,536 @@
<template>
<el-dialog
:title="props.paymentEnum == 1 ? '确认退费' : '确认收费'"
v-model="props.open"
width="700px"
append-to-body
destroy-on-close
@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="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="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="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">{{ props.paymentEnum == 1 ? '退费合计:' : '收费合计:' }}</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, unprecharge, dispenseMedicalConsumables } from './api';
import { computed, watch, reactive, ref, getCurrentInstance, nextTick } from 'vue';
import { Delete } from '@element-plus/icons-vue';
import { debounce } from 'lodash-es';
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,
},
userCardInfo: {
type: Object,
},
patientInfo: {
type: Object,
default: undefined,
},
chargeItemIds: {
type: [],
default: [],
},
consumablesIdList: {
type: [],
default: [],
},
chrgBchnoList: {
type: [],
default: [],
},
details: {
type: Object,
default: undefined,
},
paymentEnum: {
type: String,
},
newId: {
type: String,
},
oldId: {
type: String,
}
});
const { proxy } = getCurrentInstance();
const userStore = useUserStore();
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) => {
nextTick(() => {});
formData.totalAmount = newValue;
formData.selfPay[0].amount = newValue;
}
);
const emit = defineEmits(['close']);
async function printReceipt(param) {
console.log(param, 'param');
console.log(props.patientInfo, 'props.patientInfo');
// 构造一个新的对象,添加头 "data"
const result = {
data: [
{
...param,
// 基础支付类型
YB_FUND_PAY: param.detail.find((t) => t.payEnum === 100000)?.amount ?? 0, // 基金支付总额
SELF_PAY: param.detail.find((t) => t.payEnum === 200000)?.amount ?? 0, // 个人负担总金额
OTHER_PAY: param.detail.find((t) => t.payEnum === 300000)?.amount ?? 0, // 其他(如医院负担金额)
// 基本医保统筹基金支出
YB_TC_FUND_AMOUNT: param.detail.find((t) => t.payEnum === 110000)?.amount ?? 0, // 基本医保统筹基金支出
YB_BC_FUND_AMOUNT: param.detail.find((t) => t.payEnum === 120000)?.amount ?? 0, // 补充医疗保险基金支出
YB_JZ_FUND_AMOUNT: param.detail.find((t) => t.payEnum === 130000)?.amount ?? 0, // 医疗救助基金支出
YB_OTHER_AMOUNT: param.detail.find((t) => t.payEnum === 140000)?.amount ?? 0, // 其他支出
// 职工基本医疗保险
YB_TC_ZG_FUND_VALUE: param.detail.find((t) => t.payEnum === 110100)?.amount ?? 0, // 职工基本医疗保险
YB_TC_JM_FUND_VALUE: param.detail.find((t) => t.payEnum === 110200)?.amount ?? 0, // 居民基本医疗保险(修正原错误注释)
// 补充医疗保险基金支出细分
YB_BC_JM_DB_VALUE: param.detail.find((t) => t.payEnum === 120100)?.amount ?? 0, // 全体参保人的居民大病保险
YB_BC_DE_BZ_VALUE: param.detail.find((t) => t.payEnum === 120200)?.amount ?? 0, // 大额医疗费用补助
YB_BC_ZG_DE_BZ_VALUE: param.detail.find((t) => t.payEnum === 120300)?.amount ?? 0, // 企业职工大额医疗费用补助
YB_BC_GWY_BZ_VALUE: param.detail.find((t) => t.payEnum === 120400)?.amount ?? 0, // 公务员医疗补助
// 其他支出细分
OTHER_PAY_DD_FUND_VALUE: param.detail.find((t) => t.payEnum === 300001)?.amount ?? 0, // 兜底基金支出
OTHER_PAY_YW_SH_FUND_VALUE: param.detail.find((t) => t.payEnum === 300002)?.amount ?? 0, // 意外伤害基金支出
OTHER_PAY_LX_YL_FUND_VALUE: param.detail.find((t) => t.payEnum === 300003)?.amount ?? 0, // 离休人员医疗保障金支出
OTHER_PAY_LX_YH_FUND_VALUE: param.detail.find((t) => t.payEnum === 300004)?.amount ?? 0, // 离休人员优惠金支出
OTHER_PAY_CZ_FUND_VALUE: param.detail.find((t) => t.payEnum === 300005)?.amount ?? 0, // 财政基金支出
OTHER_PAY_CZ_YZ_FUND_VALUE: param.detail.find((t) => t.payEnum === 300006)?.amount ?? 0, // 财政预支支出
OTHER_PAY_ZG_DB_FUND_VALUE: param.detail.find((t) => t.payEnum === 300007)?.amount ?? 0, // 职工大病基金支出
OTHER_PAY_EY_FUND_VALUE: param.detail.find((t) => t.payEnum === 300008)?.amount ?? 0, // 二乙基金支出
OTHER_PAY_QX_JZ_FUND_VALUE: param.detail.find((t) => t.payEnum === 300009)?.amount ?? 0, // 倾斜救助支出
OTHER_PAY_YL_JZ_FUND_VALUE: param.detail.find((t) => t.payEnum === 300010)?.amount ?? 0, // 医疗救助再救助基金
HOSP_PART_AMT: param.detail.find((t) => t.payEnum === 300011)?.amount ?? 0, // 医院负担金额
// 医保结算返回值
FULAMT_OWNPAY_AMT: param.detail.find((t) => t.payEnum === 1)?.amount ?? 0, // 全自费金额
OVERLMT_SELFPAY: param.detail.find((t) => t.payEnum === 3)?.amount ?? 0, // 超限价自费费用
PRESELFPAY_AMT: param.detail.find((t) => t.payEnum === 4)?.amount ?? 0, // 先行自付金额
INSCP_SCP_AMT: param.detail.find((t) => t.payEnum === 5)?.amount ?? 0, // 符合政策范围金额
ACT_PAY_DEDC: param.detail.find((t) => t.payEnum === 6)?.amount ?? 0, // 实际支付起付线
POOL_PROP_SELFPAY: param.detail.find((t) => t.payEnum === 7)?.amount ?? 0, // 基本医疗保险统筹基金支付比例
BALC: param.detail.find((t) => t.payEnum === 8)?.amount ?? 0, // 余额
// 特殊支付方式
SELF_YB_ZH_PAY: param.detail.find((t) => t.payEnum === 210000)?.amount ?? 0, // 个人医保账户支付
SELF_YB_ZH_GJ_VALUE: param.detail.find((t) => t.payEnum === 210100)?.amount ?? 0, // 账户共济支付金额
SELF_CASH_PAY: param.detail.find((t) => t.payEnum === 220000)?.amount ?? 0, // 个人现金支付金额
SELF_VX_PAY: param.detail.find((t) => t.payEnum === 230000)?.amount ?? 0, // 微信支付金额
SELF_ALI_PAY: param.detail.find((t) => t.payEnum === 240000)?.amount ?? 0, // 阿里支付金额
// 现金支付细分
SELF_CASH_VALUE: param.detail.find((t) => t.payEnum === 220400)?.amount ?? 0, // 个人现金支付金额(现金)
SELF_CASH_VX_VALUE: param.detail.find((t) => t.payEnum === 220100)?.amount ?? 0, // 个人现金支付金额(微信)
SELF_CASH_ALI_VALUE: param.detail.find((t) => t.payEnum === 220200)?.amount ?? 0, // 个人现金支付金额(支付宝)
SELF_CASH_UNION_VALUE: param.detail.find((t) => t.payEnum === 220300)?.amount ?? 0, // 个人现金支付金额(银联)
// 基金类型(扩展)
BIRTH_FUND: param.detail.find((t) => t.payEnum === 510100)?.amount ?? 0, // 生育基金
RETIREE_MEDICAL: param.detail.find((t) => t.payEnum === 340100)?.amount ?? 0, // 离休人员医疗保障基金
URBAN_BASIC_MEDICAL: param.detail.find((t) => t.payEnum === 390100)?.amount ?? 0, // 城乡居民基本医疗保险基金
URBAN_SERIOUS_ILLNESS: param.detail.find((t) => t.payEnum === 390200)?.amount ?? 0, // 城乡居民大病医疗保险基金
MEDICAL_ASSISTANCE: param.detail.find((t) => t.payEnum === 610100)?.amount ?? 0, // 医疗救助基金
GOVERNMENT_SUBSIDY: param.detail.find((t) => t.payEnum === 640100)?.amount ?? 0, // 政府兜底基金
ACCIDENT_INSURANCE: param.detail.find((t) => t.payEnum === 390400)?.amount ?? 0, // 意外伤害基金
CARE_INSURANCE: param.detail.find((t) => t.payEnum === 620100)?.amount ?? 0, // 照护保险基金
FINANCIAL_FUND: param.detail.find((t) => t.payEnum === 360100)?.amount ?? 0, // 财政基金
HOSPITAL_ADVANCE: param.detail.find((t) => t.payEnum === 999900)?.amount ?? 0, // 医院垫付
SUPPLEMENTARY_INSURANCE: param.detail.find((t) => t.payEnum === 390300)?.amount ?? 0, // 城乡居民大病补充保险基金
HEALTHCARE_PREPAYMENT: param.detail.find((t) => t.payEnum === 360300)?.amount ?? 0, // 保健预支基金
Mr_QR_Code: param.regNo,
sex: props.patientInfo.genderEnum_enumText,
age: props.patientInfo.age,
personType: '职工医保',
fixmedinsName: param.fixmedinsName + '门诊收费明细',
},
],
// feeDetial: param.detail, //收费项目,后端还未返回
};
// 将对象转换为 JSON 字符串
let jsonString = JSON.stringify(result, null, 2);
console.log(jsonString, 'jsonString');
await CefSharp.BindObjectAsync('boundAsync');
await boundAsync.printReport(
'门诊收费明细单.grf',
jsonString
)
.then((response) => {
//返回结果是jsonString可判断其调用是否成功
console.log(response, 'response');
var res = JSON.parse(response);
if (!res.IsSuccess) {
proxy.$modal.msgError('调用打印插件失败:' + res.ErrorMessage);
}
})
.catch((error) => {
proxy.$modal.msgError('调用打印插件失败:' + error);
});
}
const throttledGetList = debounce(submit, 300);
async function submit() {
console.log(parseFloat(displayAmount.value), 'parseFloat(displayAmount.value)');
console.log(formData.totalAmount, 'formData.totalAmount');
if (parseFloat(displayAmount.value) < formData.totalAmount.toFixed(2)) {
proxy.$modal.msgError('请输入正确的结算金额');
return;
}
// if(chrome.webview === undefined) {
// alert('当前版本不支持银联支付');
// }
// else {
// try {
// let jsonResult = await window.chrome.webview.hostObjects.CSharpAccessor.ReadCardAsync();
// let cardInfo = JSON.parse(jsonResult);
// console.log(cardInfo.CardType);
// } catch (error) {
// console.error('调用失败:', error);
// }
// }
dialogLoading.value = true;
savePayment({
encounterId: props.patientInfo.encounterId,
id: props.paymentId,
oldId: props.oldId,
newId: props.newId,
chargeItemIds: props.chargeItemIds,
paymentDetails: formData.selfPay,
ybMdtrtCertType: props.userCardInfo.psnCertType,
busiCardInfo: props.userCardInfo.busiCardInfo,
})
.then((res) => {
if (res.code == 200) {
printReceipt(res.data);
(formData.selfPay = [{ payEnum: 220100, amount: 0.0, payLevelEnum: 2 }]),
emit('close', 'success', res.msg);
// 长春大学自动发耗材
if (userStore.fixmedinsCode == 'H22010200672' && props.consumablesIdList.length > 0) {
dispenseMedicalConsumables(props.consumablesIdList);
}
}
})
.finally(() => {
dialogLoading.value = false;
});
}
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() {
// unprecharge({ encounterId: props.patientInfo.encounterId }).then((res) => {
// if (res.code == 200) {
// emit('close');
// } else {
// proxy.$modal.msgError(res.message);
// }
// });
emit('close');
}
</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>

View File

@@ -0,0 +1,546 @@
<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"
/>
<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="4">
<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.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>
<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"
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
:type="scope.row.statusEnum === 1 ? 'default' : 'success'"
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>
</el-card>
</div>
<ChargeDialog
:open="openDialog"
@close="handleClose"
:category="patientInfo.categoryEnum"
:totalAmount="totalAmount"
:patientInfo="patientInfo"
:chargeItemIds="chargeItemIdList"
:consumablesIdList="consumablesIdList"
:chrgBchnoList="chrgBchnoList"
:userCardInfo="userCardInfo"
:paymentId="paymentId"
:newId="newId"
:oldId="oldId"
:details="details"
:paymentEnum="paymentEnum"
/>
</div>
</template>
<script setup name="ClinicCharge">
import {
getList,
getChargeList,
changeToSelfPay,
changeToMedicalInsurance,
init,
precharge,
} from './components/api';
import ChargeDialog from './components/chargeDialog.vue';
import { formatDateStr } from '@/utils';
import useUserStore from '@/store/modules/user';
const { proxy } = getCurrentInstance();
const userStore = useUserStore();
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 consumablesIdList = ref([]);
const receptionTime = ref([
formatDateStr(new Date(), 'YYYY-MM-DD'),
formatDateStr(new Date(), 'YYYY-MM-DD'),
]);
const newId = ref('');
const oldId = ref('');
const paymentEnum = ref(1);
const buttonDisabled = computed(() => {
return Object.keys(patientInfo.value).length === 0;
});
watch(
() => selectedRows.value,
(newVlaue) => {
if (newVlaue && newVlaue.length > 0) {
handleTotalAmount();
}
},
{ immediate: true }
);
function handleSelectionChange(selection) {
selectedRows.value = selection;
}
function handleTotalAmount() {
totalAmounts.value = selectedRows.value.reduce((accumulator, currentRow) => {
return accumulator + (Number(currentRow.totalPrice) || 0);
}, 0);
}
getPatientList();
initOption();
/**
* 患者列表
*/
function getPatientList() {
if (receptionTime.value.length > 0) {
queryParams.value.startTimeSTime = receptionTime.value[0] + ' 00:00:00';
queryParams.value.startTimeETime = receptionTime.value[1] + ' 23:59:59';
} else {
queryParams.value.startTimeSTime = undefined;
queryParams.value.startTimeETime = 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;
const date = row.startTime.split('T')[0].split('-').join('');
getChargeList({encounterId: row.encounterId, startTime:date, endTime: formatDateStr(new Date(), 'YYYYMMDD'),}).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({encounterId: patientInfo.value.encounterId, startTime:date, endTime: formatDateStr(new Date(), 'YYYYMMDD'),}).then((res) => {
chargeList.value = res.data;
setTimeout(() => {
chargeLoading.value = false;
}, 100);
});
}
}
// 确认收费
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;
});
// 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) {
// totalAmount.value = res.data.psnCashPay;
if(res.data.newPayment) {
paymentEnum.value = res.data.newPayment.paymentEnum;
paymentId.value = res.data.id.toString();
newId.value = res.data.newId.toString();
oldId.value = res.data.oldId.toString();
encounterId.value = patientInfo.value.encounterId,
chrgBchnoList.value = res.data.paymentRecDetailDtoList;
totalAmount.value = res.data.newPayment.tenderedAmount;
details.value = res.data.paymentRecDetailDtoList;
openDialog.value = true;
}else {
}
} 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 (chrome.webview === undefined) {
alert('请在医保版本中调用读卡功能!');
} else {
try {
let webView = window.chrome.webview.hostObjects.CSharpAccessor;
// 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 webView
.GetInfoByQrCodeAsync(
'http://10.47.0.67:8089/localcfc/api/hsecfc/localQrCodeQuery',
'H22010200672',
'01101',
userStore.id,
userStore.name,
'D83',
'财务科'
)
.then((res) => {
readCardLoading.value = true;
loadingText.value = '正在读取...';
jsonResult = res;
})
.catch(() => {
readCardLoading.value = false;
})
.finally(() => {
readCardLoading.value = false;
});
cardInfo = JSON.parse(jsonResult);
let message = JSON.parse(cardInfo.message);
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 webView
.ReadHeaSecCardAsync(
JSON.stringify({
IP: 'ddjk.jlhs.gov.cn',
PORT: 20215,
TIMEOUT: 60,
SFZ_DRIVER_TYPE: 1,
})
)
.then((res) => {
jsonResult = res;
})
.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) {
// totalAmount.value = res.data.psnCashPay;
paymentId.value = res.data.paymentId;
totalAmount.value = res.data.details.find((item) => item.payEnum == 220000).amount;
details.value = res.data.details;
// chrgBchnoList.value = res.data.chrgBchnoList;
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('操作成功');
}
});
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,158 @@
<template>
<div class="basic-form">
<div class="header">
<div class="title">基础信息</div>
</div>
<div class="content">
<div class="info-grid">
<div class="info-item">
<span class="label">患者姓名</span>
<span class="value">{{ formData.patientId }}</span>
</div>
<div class="info-item">
<span class="label">患者编号</span>
<span class="value">{{ formData.name }}</span>
</div>
<div class="info-item">
<span class="label">证件类型</span>
<span class="value">{{ formData.idType }}</span>
</div>
<div class="info-item">
<span class="label">性别</span>
<span class="value">{{ formData.gender }}</span>
</div>
<div class="info-item">
<span class="label">出生日期</span>
<span class="value">{{ formData.birthDate }}</span>
</div>
<div class="info-item">
<span class="label">年龄</span>
<span class="value">{{ formData.age }}</span>
</div>
<div class="info-item">
<span class="label">账户余额</span>
<span class="value">{{ formData.balance }}</span>
</div>
<div class="info-item">
<span class="label">险种类型</span>
<span class="value">{{ formData.insuranceType }}</span>
</div>
<div class="info-item">
<span class="label">人员类别</span>
<span class="value">{{ formData.personType }}</span>
</div>
<div class="info-item">
<span class="label">参保区域</span>
<span class="value">{{ formData.insuredArea }}</span>
</div>
<div class="info-item">
<span class="label">单位名称</span>
<span class="value">{{ formData.companyName }}</span>
</div>
<div class="info-item">
<span class="label">原费别</span>
<span class="value">{{ formData.originalFeeType }}</span>
</div>
</div>
<div class="footer">
<el-button type="primary" style="width:100px" fixed>转自费</el-button>
</div>
</div>
</div>
</template>
<script setup >
import { ref } from 'vue';
// interface FormData {
// patientId: string;
// name: string;
// idType: string;
// idNumber: string;
// gender: string;
// birthDate: string;
// age: string;
// balance: string;
// insuranceType: string;
// personType: string;
// insuredArea: string;
// companyName: string;
// originalFeeType: string;
// }
// const formData = ref<FormData>({
// patientId: '12112',
// name: '张三',
// idType: '身份证',
// idNumber: '210381198702200034',
// gender: '男',
// birthDate: '1996/05/28',
// age: '10岁',
// balance: '2645.08',
// insuranceType: '商业保险',
// personType: '',
// insuredArea: '沈阳市',
// companyName: '哈药大厂',
// originalFeeType: '市医保',
// });
</script>
<style lang="scss" scoped>
.basic-form {
background: #fff;
border-radius: 4px;
padding: 0 16px 16px;
.header {
height: 32px;
border-radius: 4px 4px 0px 0px;
background: rgba(37, 109, 149, 0.05);
display: flex;
align-items: center;
padding: 0 12px;
margin: 0 -16px;
.title {
font-size: 16px;
font-weight: 500;
color: #256d95;
}
}
.content {
padding-top: 8px;
.info-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 8px;
.info-item {
display: flex;
align-items: center;
min-height: 32px;
.label {
width: 100px;
text-align: right;
color: #606266;
padding-right: 12px;
flex-shrink: 0;
}
.value {
color: #333;
flex: 1;
}
}
}
}
.footer {
margin-top: 24px;
text-align: center;
.el-button {
width: 100px;
}
}
}
</style>

View File

@@ -0,0 +1,186 @@
<template>
<div class="insurance-form">
<div class="header">
<div class="title">医保登记</div>
</div>
<div class="content">
<el-form :model="formData" label-width="100px" :rules="rules">
<el-row :gutter="24">
<el-col :span="8">
<el-form-item label="医疗类别" prop="medicalType">
<el-select v-model="formData.medicalType" placeholder="请选择">
<el-option label="特殊门诊" value="special" />
<!-- 其他选项 -->
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="病种名称" prop="diseaseName">
<el-select v-model="formData.diseaseName" placeholder="请选择">
<!-- 病种选项 -->
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="入院日期" prop="admissionDate">
<el-date-picker v-model="formData.admissionDate" type="date" format="yyyy-MM-dd" value-format="yyyy-MM-dd"
style="width: 100%" placeholder="请选择日期" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="8">
<el-form-item label="参保地" prop="insuredPlace">
<el-select v-model="formData.insuredPlace" placeholder="请选择">
<el-option label="特困户" value="special" />
<!-- 其他选项 -->
</el-select>
</el-form-item>
</el-col>
<el-col :span="16">
<el-form-item label="入院诊断" prop="admissionDiagnosis">
<el-input v-model="formData.admissionDiagnosis" placeholder="请输入" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="8">
<el-form-item label="重复住院">
<el-switch inline-prompt v-model="formData.isRepeatHospitalization" active-text="是" inactive-text="否" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="外伤标志">
<el-radio-group v-model="formData.hasOutsideStandard" class="ml-20">
<el-radio :value="true"></el-radio>
<el-radio :value="false"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="临床试验">
<el-radio-group v-model="formData.hasClinicalTrial" class="ml-20">
<el-radio :value="true"></el-radio>
<el-radio :value="false"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="第三方责任">
<el-radio-group v-model="formData.hasThirdParty" class="ml-20">
<el-radio :value="true"></el-radio>
<el-radio :value="false"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="急诊标志">
<el-switch inline-prompt v-model="formData.isEmergency" active-text="是" inactive-text="否" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="涉外标志">
<el-radio-group v-model="formData.hasOverseasStandard" class="ml-20">
<el-radio :value="true"></el-radio>
<el-radio :value="false"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24" class="text-center">
<el-button type="primary" fixed style="width: 100px">登记变更</el-button>
</el-col>
</el-row>
</el-form>
</div>
</div>
</template>
<script setup >
import { ref } from 'vue';
// interface FormData {
// medicalType: string;
// diseaseName: string;
// admissionDate: string;
// insuredPlace: string;
// admissionDiagnosis: string;
// isRepeatHospitalization: boolean;
// hasOutsideStandard: boolean;
// isEmergency: boolean;
// hasOverseasStandard: boolean;
// }
// const formData = ref<FormData>({
// medicalType: '',
// diseaseName: '',
// admissionDate: '',
// insuredPlace: '',
// admissionDiagnosis: '',
// isRepeatHospitalization: false,
// hasOutsideStandard: false,
// isEmergency: false,
// hasOverseasStandard: false,
// });
// const rules = {
// medicalType: [
// { required: true, message: '请选择医疗类别', trigger: 'change' },
// ],
// diseaseName: [
// { required: true, message: '请选择病种名称', trigger: 'change' },
// ],
// admissionDate: [
// { required: true, message: '请选择入院日期', trigger: 'change' },
// ],
// admissionDiagnosis: [
// { required: true, message: '请输入入院诊断', trigger: 'blur' },
// ],
// };
const handleSubmit = () => {
// 处理表单提交
};
</script>
<style lang="scss" scoped>
.insurance-form {
background: #fff;
border-radius: 4px;
padding: 0 16px 16px;
.header {
height: 32px;
border-radius: 4px 4px 0px 0px;
background: rgba(37, 109, 149, 0.05);
display: flex;
align-items: center;
padding: 0 12px;
margin: 0 -16px;
.title {
font-size: 16px;
font-weight: 500;
color: #256d95;
}
}
.content {
padding-top: 8px;
}
.ml-20 {
margin-left: 20px;
}
.text-center {
text-align: center;
}
.label {
color: #606266;
}
}
</style>

View File

@@ -0,0 +1,83 @@
<template>
<div class="pat-info">
<!-- 患者信息 -->
<el-space direction="vertical" alignment="flex-start">
<el-space>
<div>
100
</div>
<div>
头像
</div>
<div>
任素汐
</div>
<div>
/24
</div>
<div>
自费
</div>
<div>
住院:29
</div>
<div>
入科:2025-04-04
</div>
<div>
住院号:0023445454
</div>
<div>
诊断:人工流产
</div>
</el-space>
<el-space>
<div>
过明历史鸡蛋过敏
</div>
<div>
低保人员
</div>
<div>
主治医生张三
</div>
<div>
总额56545.89
</div>
<div>
预交金12312312.9
</div>
<div>
余额12312312.9
</div>
</el-space>
</el-space>
</div>
</template>
<script setup >
import { onMounted, ref } from 'vue';
const visitCode = ref('');
onMounted(() => {
visitCode.value = 'IPD0000188';
})
// function updatePatientInfo(params: string) {
// console.log('updatePatientInfo', updatePatientInfo);
// }
// defineProps<{
// patientInfo: any;
// }>();
</script>
<style lang="scss" scoped>
.pat-info {
width: 100%;
align-items: center;
padding: 8px;
// background: #c12626;
}
</style>

View File

@@ -0,0 +1,63 @@
<template>
<div class="patient-list">
<el-table
:data="data"
highlight-current-row
show-overflow-tooltip
@current-change="handleCurrentChange"
height="100%"
>
<el-table-column label="住院号" prop="inpatientCode" />
<el-table-column label="姓名" prop="name" min-width="90px" />
<el-table-column label="年龄" prop="age" width="60px" />
<el-table-column label="费别" prop="feeType" width="60px" />
<el-table-column label="病区" prop="nurseDeptName" width="60px" />
</el-table>
</div>
</template>
<script setup >
// defineProps<{
// data: any[];
// }>();
// const emit = defineEmits(['current-change']);
// const handleCurrentChange = (row: any) => {
// emit('current-change', row);
// };
</script>
<style lang="scss" scoped>
.patient-list {
height: 100%;
box-sizing: border-box;
.el-table {
height: 100%;
}
.el-table__row {
cursor: pointer;
&:hover > td {
background-color: #f5f7fa !important;
}
&.current-row > td {
background-color: #dcf8f6 !important;
color: #256d95;
&:first-child {
&::before {
content: '';
display: block;
position: absolute;
width: 2px;
height: 12px;
top: 50%;
transform: translateY(-50%);
background-color: #00bbaa;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,64 @@
<template>
<div class="search-form">
<el-form :model="form" inline :label-width="80">
<el-form-item label="病区">
<el-select style="width: 206px" v-model="form.nurseDeptCode" placeholder="请选择" clearable>
<el-option v-for="item in nursingGroupList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="患者姓名">
<el-input v-model="form.name" style="width: 206px" placeholder="请输入" clearable @keyup.enter="handleSearch" />
</el-form-item>
<el-form-item label="住院号">
<el-input v-model="form.inpatientCode" style="width: 206px" placeholder="请输入" @keyup.enter="handleSearch"
clearable />
</el-form-item>
<div class="button-group">
<el-button @click="handleReset">重置</el-button>
<el-button type="primary" @click="handleSearch">查询</el-button>
</div>
</el-form>
</div>
</template>
<script setup >
import { ref, onMounted } from 'vue';
// import { store } from '@hip/portal';
// const { userInfo } = store.useGlobalStore();
// const emit = defineEmits(['search', 'reset']);
// const form = ref({
// nurseDeptCode: '',
// name: '',
// inpatientCode: '',
// });
// const nursingGroupList = ref<any[]>([]);
// onMounted(() => {
// // 获取科室
// });
// const handleSearch = () => {
// emit('search', form.value);
// };
// const handleReset = () => {
// form.value = {
// nurseDeptCode: '',
// name: '',
// inpatientCode: '',
// };
// emit('reset');
// };
</script>
<style scoped>
.button-group {
display: flex;
gap: 10px;
justify-content: right;
margin-bottom: 12px;
}
</style>

View File

@@ -0,0 +1,99 @@
<template>
<div class="top-form">
<el-form :model="form" inline>
<el-form-item label="费别" class="fee-type">
<el-select v-model="form.medicalType" placeholder="请选择">
<el-option label="市职工医保" value="1" />
</el-select>
</el-form-item>
<el-form-item class="card-type" label-width="0px">
<el-radio-group v-model="form.payType">
<el-radio :value="1">医保卡</el-radio>
<el-radio :value="2">医保电子凭证</el-radio>
<el-radio :value="3">居民身份证</el-radio>
<el-radio :value="4">社会保障卡</el-radio>
<el-radio :value="5">医保刷脸</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item class="operate-btns">
<el-button type="primary" class="main-btn" @click="handleReadCard">读卡</el-button>
<el-button type="primary" class="main-btn" @click="handleUpload">费用上传</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script setup >
import { ref, inject } from 'vue';
import { FormInstance } from 'element-plus';
// const form = inject('formState') as any;
// const formRef = ref<FormInstance>();
const handleReset = () => {
formRef.value?.resetFields();
};
const handleReadCard = () => {
console.log('读卡');
};
const handleUpload = () => {
console.log('费用上传');
};
</script>
<style lang="scss" scoped>
.top-form {
padding: 8px;
background: #fff;
border-radius: 4px;
padding-left: 16px;
:deep(.el-form) {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 8px;
}
:deep(.el-radio) {
margin-right: 8px;
}
.fee-type {
margin-right: 8px;
:deep(.el-select) {
width: 160px;
}
}
.card-type {
// flex: 1;
// margin-left: auto;
// margin-right: 24px;
margin-right: 8px;
:deep(.el-radio-group) {
display: flex;
// gap: 24px;
}
}
.operate-btns {
.main-btn {
// margin-left: 16px;
// width: 100px;
&:first-child {
margin-left: 0;
}
}
}
:deep(.el-form-item) {
margin-bottom: 0;
}
}
</style>

View File

@@ -0,0 +1,122 @@
<template>
<div class="insurance-wrap">
<div class="left-wrap" v-loading="loading">
<div class="left-wrap-content">
<SearchForm @search="handleSearch" @reset="handleReset" />
<PatientList :data="patientList" @current-change="handleCurrentChange" />
</div>
</div>
<div class="right-wrap">
<PatientDetail :patient-info="currentPatient || {}" />
<div class="right-wrap-content">
<el-scrollbar height="100%">
<TopForm></TopForm>
<BasicForm></BasicForm>
<InsuranceForm :visit-code="currentPatient?.visitCode" />
</el-scrollbar>
</div>
</div>
</div>
</template>
<script setup >
import { provide, reactive, ref } from 'vue';
import SearchForm from './components/SearchForm.vue';
import PatientList from './components/PatientList.vue';
import PatientDetail from './components/PatientDetail.vue';
import InsuranceForm from './components/InsuranceForm.vue';
// import { getPatientListApi } from '@/api/feeTypeConversion';
import TopForm from './components/TopForm.vue';
import BasicForm from './components/BasicForm.vue';
// const patientList = ref<any[]>([
// {}
// ]);
const currentPatient = ref();
const formState = reactive({});
const loading = ref(false);
provide('formState', formState);
// const handleSearch = (params: any) => {
// loading.value = true;
// // getPatientListApi(params)
// // .then((res) => {
// // patientList.value = res;
// // })
// // .finally(() => {
// // loading.value = false;
// // });
// };
const handleReset = () => {
currentPatient.value = null;
patientList.value = [];
};
// const handleCurrentChange = (patient: any) => {
// currentPatient.value = patient;
// };
</script>
<style lang="scss" scoped>
.insurance-wrap {
width: 100%;
height: 100%;
height: calc(100vh - 84px);
// background: #c0ddf0;
display: flex;
// flex-direction: row;
}
.left-wrap {
display: flex;
flex-direction: column;
height: 100%;
box-sizing: border-box;
width: 302px;
overflow: hidden;
flex: none;
border-right: 1px solid #c0ddf0;
padding: 8px;
.left-wrap-content {
height: 100%;
display: flex;
flex-direction: column;
.search-form {
flex: none;
height: 182px;
}
.patient-list {
flex: auto;
height: 200px;
}
}
}
.right-wrap {
width: 302px;
flex: auto;
height: 100%;
display: flex;
flex-direction: column;
.pat-info {
width: 100%;
height: 72px;
flex: none;
}
.right-wrap-content {
flex: auto;
height: 200px;
}
}
// .content {
// padding: 16px;
// }</style>

View File

@@ -0,0 +1,158 @@
<template>
<div class="awaitList-container">
<div class="operate">
<el-space>
<el-input
v-model="queryParams.searchKey"
style="max-width: 600px"
placeholder="请输入内容"
class="input-with-select"
>
</el-input>
<el-button @click="resetQuery">重置</el-button>
<el-button type="primary" @click="handleQuery">查询</el-button>
</el-space>
<el-space>
<!-- <el-button>读卡</el-button> -->
<!-- <el-button type="primary">无档登记</el-button> -->
</el-space>
</div>
<div class="table-container">
<el-table
:data="treatHospitalizedData"
style="width: 100%"
height="100%"
show-overflow-tooltip
>
<el-table-column type="index" width="54" align="center" label="序号" />
<el-table-column prop="patientName" align="center" label="申请患者" />
<el-table-column prop="genderEnum_enumText" label="性别" align="center" />
<el-table-column prop="age" label="年龄" align="center" />
<el-table-column prop="sourceName" align="center" label="申请来源">
<template #default="scope">
{{ scope.row.sourceName || '-' }}
</template>
</el-table-column>
<el-table-column prop="requestTime" align="center" label="申请时间" />
<el-table-column prop="wardName" align="center" label="入院病区" />
<el-table-column prop="registrar" align="center" label="登记员" />
<el-table-column fixed="right" align="center" label="操作" width="88">
<template #default="scope">
<el-button type="primary" text @click="doEdit(scope.row)"> 查看 </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="getList"
/>
</div>
</div>
<PatientRegister
v-model="patientRegisterVisible"
:patientInfo="patient"
:inHospitalInfo="inHospitalInfo"
title="登记"
:registrationType="registrationType"
:alreadyEdit="alreadyEdit"
:noFile="noFile"
@okAct="patientRegisterOK"
@cancelAct="cancelAct"
/>
</template>
<script setup >
import PatientRegister from './patientRegister.vue';
import { getAdmissionPage, getPatientBasicInfo, getInHospitalInfo } from './api';
//const { proxy } = getCurrentInstance();
const emits = defineEmits([]);
// const props = defineProps({});
const searchForm = reactive({
searchType: 'name',
searchKey: '',
});
const total = ref();
const inHospitalInfo = ref({});
const alreadyEdit = ref(true);
const queryParams = ref({
pageNo: 1,
pageSize: 10,
searchKey: undefined,
registeredFlag: '1',
searchKey: '',
});
const treatHospitalizedData = ref([]);
const patientRegisterVisible = ref(false);
const noFile = ref(false);
const registrationType = ref(true);
const patient = ref({});
const doEdit = (row) => {
getPatientBasicInfo(row.patientId).then((res) => {
patient.value = res.data;
});
getInHospitalInfo(row.encounterId).then((res) => {
inHospitalInfo.value = res.data;
patientRegisterVisible.value = true;
noFile.value = false;
});
};
onBeforeMount(() => {});
onMounted(() => {
getList();
});
const activeName = ref('first');
const patientRegisterOK = () => {
patientRegisterVisible.value = false;
queryParams.value.searchKey = '';
emits('okList');
resetQuery();
};
const cancelAct = () => {
patientRegisterVisible.value = false;
};
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNo = 1;
getList();
}
function resetQuery() {
queryParams.value = {
pageNo: 1,
pageSize: 10,
searchKey: undefined,
registeredFlag: '1',
searchKey: '',
};
getList();
}
const getList = () => {
getAdmissionPage(queryParams.value).then((res) => {
treatHospitalizedData.value = res.data.records;
total.value = res.data.total;
});
};
</script>
<style lang="scss" scoped>
.awaitList-container {
width: 100%;
height: 100%;
.operate {
display: flex;
justify-content: space-between;
height: 40px;
padding: 0 16px;
align-items: center;
}
.table-container {
padding: 8px 16px;
}
}
</style>

View File

@@ -0,0 +1,169 @@
import request from '@/utils/request'
// 获取住院信息初期数据列表
export function getInit(query) {
return request({
url: '/inpatient-manage/init',
method: 'get',
params: query
})
}
// 获取住院信息 分页显示
// export function getAdmissionPage(query) {
// return request({
// url: '/inpatient-manage/admission-page',
// method: 'get',
// params: query
// })
// }
// 获取住院信息 分页显示 新
export function getAdmissionPage(query) {
return request({
url: '/inhospital-charge/register/register-info',
method: 'get',
params: query
})
}
// 住院无档登记
export function addAdmissionInfo(data) {
return request({
url: '/inpatient-manage/admission-information',
method: 'post',
data: data
})
}
// 住院登记
export function admissionInfo(data) {
return request({
url: '/inpatient-manage/admission-information',
method: 'put',
data: data
})
}
/**
* 获取科室下拉列表
*/
export function getOrgList() {
return request({
url: '/base-data-manage/organization/organization',
method: 'get',
})
}
/**
* 查询病区下拉列表
*/
export function wardList() {
return request({
url: '/app-common/ward-list',
method: 'get'
})
}
/**
* 获取诊断基础下拉数据
*/
export function diagnosisInit() {
return request({
url: '/doctor-station/diagnosis/init',
method: 'get',
})
}
// 查询患者相关
export function patientlLists() {
return request({
url: '/patient-manage/information/init',
method: 'get'
})
}
// 查询患者相关
export function doctorList(id) {
return request({
url: '/inpatient-manage/doctor-list?orgId=' + id,
method: 'get'
})
}
// 查询患者相关
export function getPatientInfo(id, statusEnum) {
return request({
url: `/inpatient-manage/admission-one?id=${id}&statusEnum=${statusEnum}`,
method: 'get'
})
}
// 获取患者基础信息
export function getPatientBasicInfo(patientId) {
return request({
url: `/inhospital-charge/register/patient-info?patientId=${patientId}`,
method: 'get'
})
}
// 获取患者入院信息
export function getInHospitalInfo(encounterId) {
return request({
url: `/inhospital-charge/register/in-hospital-info?encounterId=${encounterId}`,
method: 'get'
})
}
// 获取病区床位信息
export function getBedInfo(wardBusNo) {
return request({
url: `/inhospital-charge/register/beds-num?wardBusNo=${wardBusNo}`,
method: 'get'
})
}
// 住院登记
export function registerInHospital(data) {
return request({
url: '/inhospital-charge/register/by-cashier',
method: 'post',
data: data
})
}
// 无档登记
export function noFilesRegister(data) {
return request({
url: '/inhospital-charge/register/no-files',
method: 'post',
data: data
})
}
// 表单初始化
export function patientFormInit() {
return request({
url: '/patient-manage/information/init',
method: 'get'
})
}
// 合同
export function getContractList() {
return request({
url: '/app-common/contract-list',
method: 'get',
})
}
/**
* 获取诊断定义列表
*/
export function getDiagnosisDefinitionList(queryParams) {
return request({
url: '/doctor-station/diagnosis/condition-definition-metadata',
method: 'get',
params: queryParams
})
}

View File

@@ -0,0 +1,150 @@
<template>
<div class="awaitList-container">
<div class="operate">
<el-space>
<el-input
v-model="queryParams.searchKey"
style="max-width: 600px"
placeholder="请输入内容"
class="input-with-select"
@keydown.enter="handleQuery"
>
</el-input>
<el-button @click="resetQuery">重置</el-button>
<el-button type="primary" @click="handleQuery">查询</el-button>
</el-space>
<el-space>
<!-- <el-button>读卡</el-button> -->
<el-button type="primary" @click="doRegistering('no-file')">无档登记</el-button>
</el-space>
</div>
<div class="table-container">
<el-table
:data="treatHospitalizedData"
style="width: 100%"
height="100%"
show-overflow-tooltip
>
<el-table-column type="index" width="54" align="center" label="序号" />
<el-table-column prop="patientName" align="center" label="患者姓名" />
<el-table-column prop="genderEnum_enumText" label="性别" align="center" />
<el-table-column prop="age" label="年龄" align="center" />
<el-table-column prop="requestTime" align="center" label="申请时间" />
<el-table-column prop="sourceName" align="center" label="申请来源" />
<el-table-column prop="wardName" align="center" label="入院病区" />
<el-table-column fixed="right" align="center" label="操作" width="88">
<template #default="scope">
<el-button type="primary" link @click="doRegistering(scope.row)"> 登记 </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="getList"
/>
</div>
<PatientRegister
v-model="patientRegisterVisible"
:patientInfo="patient"
:inHospitalInfo="inHospitalInfo"
title="登记"
:registrationType="registrationType"
@okAct="patientRegisterOK"
@cancelAct="cancelAct"
:noFile="noFile"
/>
</div>
</template>
<script setup>
import PatientRegister from './patientRegister.vue';
import { getAdmissionPage, getPatientBasicInfo, getInHospitalInfo } from './api';
const emits = defineEmits(['okList']);
const total = ref();
const patient = ref({});
const inHospitalInfo = ref({});
const noFile = ref(false);
const registrationType = ref(true);
const queryParams = ref({
pageNo: 1,
pageSize: 10,
searchKey: undefined,
registeredFlag: '0',
searchKey: '',
});
const treatHospitalizedData = ref([]);
const doRegistering = (row) => {
if (row == 'no-file') {
patientRegisterVisible.value = true;
noFile.value = true;
inHospitalInfo.value = {};
} else {
getPatientBasicInfo(row.patientId).then((res) => {
patient.value = res.data;
});
getInHospitalInfo(row.encounterId).then((res) => {
inHospitalInfo.value = res.data;
patientRegisterVisible.value = true;
noFile.value = false;
});
}
};
const getList = () => {
getAdmissionPage(queryParams.value).then((res) => {
treatHospitalizedData.value = res.data.records;
total.value = res.data.total;
});
};
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNo = 1;
getList();
}
function resetQuery() {
queryParams.value = {
pageNo: 1,
pageSize: 10,
searchKey: undefined,
registeredFlag: '0',
searchKey: '',
};
getList();
}
const patientRegisterVisible = ref(false);
const patientYbRegisterVisible = ref(false);
const patientRegisterOK = () => {
patientRegisterVisible.value = false;
queryParams.value.searchKey = '';
emits('okList');
};
const cancelAct = () => {
patientRegisterVisible.value = false;
};
getList();
</script>
<style lang="scss" scoped>
.awaitList-container {
width: 100%;
height: 100%;
.operate {
display: flex;
justify-content: space-between;
height: 40px;
padding: 0 16px;
align-items: center;
}
.table-container {
padding: 8px 16px;
}
}
</style>

View File

@@ -0,0 +1,99 @@
<template>
<div class="awaitList-container">
<div class="operate">
<el-space>
<el-input
v-model="searchForm.searchVal"
style="max-width: 600px"
placeholder="请输入内容"
class="input-with-select"
>
<template #prepend>
<el-select v-model="searchForm.searchType" placeholder="" style="width: 115px">
<el-option label="患者姓名" value="name" />
<el-option label="诊疗卡号" value="MED_ID" />
<el-option label="身份证号" value="1" />
</el-select>
</template>
</el-input>
<el-button>重置</el-button>
<el-button type="primary">查询</el-button>
</el-space>
<el-space>
<!-- <el-button>读卡</el-button>
<el-button type="primary">无档登记</el-button> -->
</el-space>
</div>
<div class="table-container">
<el-table
:data="treatHospitalizedData"
style="width: 100%"
height="100%"
show-overflow-tooltip
>
<el-table-column type="index" width="54" label="序号" />
<el-table-column prop="storageName" label="申请来源"> </el-table-column>
<el-table-column prop="createdDate" label="申请时间" min-width="160" />
<el-table-column prop="name" label="申请患者" />
<el-table-column prop="deptNurseName" label="入院病区" />
<el-table-column prop="sexName" label="性别" />
<el-table-column prop="purchaseTotalAmount" label="年龄"> </el-table-column>
</el-table>
</div>
</div>
</template>
<script setup >
import { getAdmissionPage } from './api';
//const { proxy } = getCurrentInstance();
const emits = defineEmits([]);
// const props = defineProps({});
const searchForm = reactive({
searchType: 'name',
searchVal: '',
});
const queryParams = ref({
pageNo: 1,
pageSize: 10,
searchKey: undefined,
registeredFlag: '1',
searchKey: '',
});
const total = ref(0);
const treatHospitalizedData = ref([]);
const doRegistering = (row) => {};
onBeforeMount(() => {});
onMounted(() => {
getList();
});
// defineExpose({ state });
const getList = () => {
getAdmissionPage(queryParams.value).then((res) => {
treatHospitalizedData.value = res.data.records;
total.value = res.data.total;
});
};
const activeName = ref('first');
// const handleClick = (tab: TabsPaneContext, event: Event) => {
// console.log(tab, event);
// };
</script>
<style lang="scss" scoped>
.awaitList-container {
width: 100%;
height: 100%;
.operate {
display: flex;
justify-content: space-between;
height: 40px;
padding: 0 16px;
align-items: center;
}
.table-container {
padding: 8px 16px;
}
}
</style>

View File

@@ -0,0 +1,4 @@
import AwaitList from "./awaitList.vue";
import AccomplishList from "./accomplishList.vue";
import ExistList from "./existList.vue";
export {AwaitList,AccomplishList,ExistList}

View File

@@ -0,0 +1,407 @@
<template>
<div class="patientInfo-container">
<div class="operate">
<div>基础信息</div>
<!-- <div
v-if="props.registrationType"
type="primary"
@click="toggleEdit"
style="margin-right: 0; cursor: pointer; margin-right: 12px"
>
{{ isEditing ? '取消' : '编辑' }}
</div> -->
<div>
<el-radio-group v-model="typeCode">
<el-radio label="电子凭证" value="01"></el-radio>
<el-radio label="医保卡" value="03"></el-radio>
<el-radio label="身份证" value="02"></el-radio>
</el-radio-group>
<span
@click="handleReadCard(typeCode)"
style="cursor: pointer; margin: 0 12px 0 30px; color: #409eff"
>
{{ '读卡' }}
</span>
</div>
</div>
<!-- 展示模式 -->
<div v-if="!noFile" style="margin-left: 30px">
<el-row class="patientInfos">
<el-col :span="2" class="patInfo-label">
<el-text truncated>患者编码</el-text>
</el-col>
<el-col :span="4" class="patInfo-value">
<el-text truncated>{{ patientInfo?.busNo || '-' }}</el-text>
</el-col>
<el-col :span="2" class="patInfo-label">
<el-text truncated>患者姓名</el-text>
</el-col>
<el-col :span="4" class="patInfo-value">
<el-text truncated>{{ patientInfo?.name || '-' }}</el-text>
</el-col>
<el-col :span="2" class="patInfo-label">
<el-text truncated>费别类型</el-text>
</el-col>
<el-col :span="4" class="patInfo-value">
<el-text truncated>{{ patientInfo?.ybClassEnum_enumText || '-' }}</el-text>
<!-- TODO -->
<svg-icon size="20" icon-class="hipEdit" style="cursor: pointer" @click="changFeeType" />
</el-col>
</el-row>
<el-row class="patientInfos">
<el-col :span="2" class="patInfo-label">
<el-text truncated>证件类型</el-text>
</el-col>
<!-- TODO -->
<el-col :span="4" class="patInfo-value">
<el-text truncated>{{ patientInfo?.patientTypeCode_dictText || '-' }}</el-text>
</el-col>
<el-col :span="2" class="patInfo-label">
<el-text truncated>证件号</el-text>
</el-col>
<el-col :span="4" class="patInfo-value">
<el-text truncated>{{ patientInfo?.idCard || '-' }}</el-text>
</el-col>
<el-col :span="2" class="patInfo-label">
<el-text truncated>出生日期</el-text>
</el-col>
<el-col :span="4" class="patInfo-value">
<el-text truncated>{{ patientInfo?.birthDate || '-' }}</el-text>
</el-col>
<el-col :span="2" class="patInfo-label">
<el-text truncated>年龄</el-text>
</el-col>
<el-col :span="4" class="patInfo-value">
<el-text truncated>{{ patientInfo?.ageString || '-' }}</el-text>
</el-col>
</el-row>
<el-row class="patientInfos">
<el-col :span="2" class="patInfo-label">
<el-text truncated>性别</el-text>
</el-col>
<el-col :span="4" class="patInfo-value">
<div>{{ patientInfo?.genderEnum_enumText || '-' }}</div>
</el-col>
<el-col :span="2" class="patInfo-label">
<el-text truncated>民族</el-text>
</el-col>
<el-col :span="4" class="patInfo-value">
<div>{{ patientInfo?.nationalityCode || '-' }}</div>
</el-col>
<el-col :span="2" class="patInfo-label">
<el-text truncated>国籍</el-text>
</el-col>
<el-col :span="4" class="patInfo-value">
<div>{{ patientInfo?.countryCode || '-' }}</div>
</el-col>
<el-col :span="2" class="patInfo-label">
<el-text truncated>婚姻</el-text>
</el-col>
<el-col :span="4" class="patInfo-value">
<div>{{ patientInfo?.maritalStatusEnum_enumText || '-' }}</div>
</el-col>
</el-row>
<el-row class="patientInfos">
<el-col :span="2" class="patInfo-label">
<el-text truncated>职业</el-text>
</el-col>
<el-col :span="4" class="patInfo-value">
<div>{{ patientInfo?.prfsEnum_enumText || '-' }}</div>
</el-col>
<el-col :span="2" class="patInfo-label">
<el-text truncated>手机</el-text>
</el-col>
<el-col :span="4" class="patInfo-value">
<div>{{ patientInfo.phone || '-' }}</div>
</el-col>
<el-col :span="2" class="patInfo-label">
<el-text truncated>现住址</el-text>
</el-col>
<el-col :span="4" class="patInfo-value">
<div>{{ patientInfo?.address || '-' }}</div>
</el-col>
</el-row>
<el-row class="patientInfos">
<!-- <el-col :span="2" class="patInfo-label">
<el-text truncated>户口地址</el-text>
</el-col>
<el-col :span="4" class="patInfo-value">
<div>{{ patientInfo?.nativeExactAddr }}</div>
</el-col> -->
<el-col :span="2" class="patInfo-label">
<el-text truncated>籍贯</el-text>
</el-col>
<el-col :span="4" class="patInfo-value">
<div>{{ patientInfo?.nativePlace || '-' }}</div>
</el-col>
<el-col :span="2" class="patInfo-label">
<el-text truncated>病人来源</el-text>
</el-col>
<el-col :span="4" class="patInfo-value">
<div>{{ patientInfo?.organizationId_dictText || '-' }}</div>
</el-col>
<el-col :span="2" class="patInfo-label">
<el-text truncated>单位名称</el-text>
</el-col>
<el-col :span="4" class="patInfo-value">
<div>{{ patientInfo?.workCompany || '-' }}</div>
</el-col>
</el-row>
</div>
<div v-else>
<PatientInfoForm ref="patientInfoFormRef" />
</div>
</div>
</template>
<script setup>
import { ref, reactive, watch } from 'vue';
import PatientInfoForm from './patientInfoForm.vue';
import { patientlLists, getOrgList } from './api';
const typeList = ref({});
const patientInfoFormRef = ref();
const props = defineProps({
patientInfo: {
type: Object,
require: true,
default: () => ({}),
},
registrationType: {
type: [String, Boolean, Number], // 根据实际类型调整
default: null, // 或者 false、'' 等
},
initOptions: {
type: Object,
require: true,
default: () => ({}),
},
noFile: {
type: Boolean,
default: false,
},
});
const emits = defineEmits(['onChangFeeType']);
const registerRef = ref();
const typeCode = ref('01');
const organization = ref([]);
onMounted(() => {
getInitOptions();
});
// 编辑状态
const isEditing = ref(false);
watch(
() => props.registrationType,
(newValue) => {
isEditing.value = !newValue;
},
{ immediate: true }
);
watch(
() => props.patientInfo,
(newValue) => {},
{ immediate: true }
);
function getInitOptions() {
patientlLists().then((res) => {
typeList.value = res.data;
});
getOrgList().then((res) => {
organization.value = res.data.records;
});
}
// 表单数据
const form = reactive({});
// 切换编辑状态
const toggleEdit = () => {
if (!isEditing.value) {
// 取消时恢复原值
Object.assign(form, props.patientInfo);
}
isEditing.value = !isEditing.value;
};
// 提交表单
const submitForm = async (callback) => {
console.log('提交更新:', form);
if (!registerRef.value) return false;
registerRef.value.validate((valid) => {
if (valid) {
callback();
return true;
} else {
return false;
}
});
};
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 boundAsync
.getInfoByQrCodeAsync(
'http://10.47.0.67:8089/localcfc/api/hsecfc/localQrCodeQuery',
'H22010200672',
'01101',
userStore.id,
userStore.name,
'D83',
'财务科'
)
.then((res) => {
readCardLoading.value = true;
loadingText.value = '正在读取...';
jsonResult = res;
})
.catch(() => {
readCardLoading.value = false;
});
cardInfo = JSON.parse(jsonResult);
let message = JSON.parse(cardInfo.message);
userMessage = {
certType: '02', // 证件类型
certNo: message.data.idNo, // 身份证号
psnCertType: '02', // 居民身份证
};
break;
case '02':
break;
case '03': // 社保卡
readCardLoading.value = true;
loadingText.value = '正在读取...';
await boundAsync
.readHeaSecCardAsync(
JSON.stringify({
IP: 'ddjk.jlhs.gov.cn',
PORT: 20215,
TIMEOUT: 60,
SFZ_DRIVER_TYPE: 1,
})
)
.then((res) => {
jsonResult = res;
})
.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', // 居民身份证
};
break;
case '99':
break;
}
readCardLoading.value = true;
if (userMessage.certNo) {
gerPreInfo(userMessage)
.then((res) => {
if (res.code == 200) {
form.value.patientId = res.data.id;
form.value.name = res.data.name;
form.value.age = res.data.age;
form.value.idCard = res.data.idCard;
form.value.card = res.data.id;
form.value.contractNo = res.data.contractBusNo;
form.value.genderEnum = res.data.genderEnum;
form.value.ybAreaNo = res.data.contractName;
}
})
.finally(() => {
readCardLoading.value = false;
});
}
} catch (error) {
console.error('调用失败:', error);
readCardLoading.value = false;
}
}
}
function getPatientForm() {
console.log(patientInfoFormRef.value.form);
return patientInfoFormRef.value.form;
}
// 患者费别变更
const changFeeType = () => {
emits('onChangFeeType');
};
defineExpose({ submitForm, form, isEditing, getPatientForm });
</script>
<style lang="scss" scoped>
.patientInfo-container {
.operate {
display: flex;
justify-content: space-between;
align-items: center;
height: 32px;
border-radius: 4px 4px 0px 0px;
background: rgba(37, 109, 149, 0.05);
padding-left: 16px;
color: var(--hip-color-primary-light);
font-weight: bold;
margin-bottom: 8px;
}
> .patientInfos {
margin-bottom: 16px;
&:not(.patientInfo-container :has(+ .patientInfos)) {
margin-bottom: 0px;
}
}
}
.patInfo-label {
color: #606266 !important;
font-size: 14px;
font-weight: 700 !important;
margin-bottom: 10px;
}
</style>

View File

@@ -0,0 +1,392 @@
<template>
<el-form ref="patientRef" :model="form" :rules="rules" label-width="100px">
<el-row>
<el-col :span="6">
<el-form-item label="姓名" prop="name">
<el-input v-model="form.name" clearable :disabled="isViewMode" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="性别" prop="genderEnum">
<el-radio-group v-model="form.genderEnum" :disabled="isViewMode">
<el-radio
v-for="item in administrativegenderList"
:key="item.value"
:label="item.value"
>
{{ item.info }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<!-- <el-col :span="6">
<el-form-item label="活动标识" prop="tempFlag">
<el-radio-group v-model="form.tempFlag" :disabled="isViewMode">
<el-radio v-for="dict in patient_temp_flag" :key="dict.value" :label="dict.value">
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col> -->
<el-col :span="6">
<el-form-item label="联系方式" prop="phone">
<el-input v-model="form.phone" clearable :disabled="isViewMode" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="年龄" prop="age">
<el-input
v-model="form.age"
:disabled="isViewMode"
@input="(value) => (form.age = value.replace(/[^0-9]/g, ''))"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="卡类别" prop="typeCode">
<el-select v-model="form.typeCode" placeholder="卡类别" clearable :disabled="isViewMode">
<el-option
v-for="dict in sys_idtype"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="证件号码" prop="idCard">
<el-input v-model="form.idCard" clearable :disabled="isViewMode" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="就诊卡号" prop="identifierNo">
<el-input v-model="form.identifierNo" clearable :disabled="isViewMode" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="民族" prop="nationalityCode">
<el-select v-model="form.nationalityCode" clearable filterable :disabled="isViewMode">
<el-option
v-for="item in nationality_code"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<!-- <el-col :span="6">
<el-form-item label="年龄" prop="age">
<el-input v-model="form.age" clearable :disabled="isViewMode"/>
</el-form-item>
</el-col> -->
<el-row>
<el-col :span="6">
<el-form-item label="国家编码" prop="countryCode">
<el-input v-model="form.countryCode" clearable :disabled="isViewMode" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="职业" prop="prfsEnum">
<el-select v-model="form.prfsEnum" placeholder="职业" clearable :disabled="isViewMode">
<el-option
v-for="item in occupationtypeList"
:key="item.value"
:label="item.info"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="工作单位" prop="workCompany">
<el-input v-model="form.workCompany" clearable :disabled="isViewMode" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="6">
<el-form-item label="联系人" prop="linkName">
<el-input v-model="form.linkName" clearable :disabled="isViewMode" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="联系人关系" prop="linkRelationCode">
<el-select
v-model="form.linkRelationCode"
placeholder="联系人关系"
clearable
:disabled="isViewMode"
>
<el-option
v-for="item in familyrelationshiptypeList"
:key="item.value"
:label="item.info"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="联系人电话" prop="linkRelationCode">
<el-input v-model="form.linkTelcom" clearable :disabled="isViewMode" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="6">
<el-form-item label="地址选择" prop="addressSelect">
<el-cascader
:options="options"
:props="{ checkStrictly: true, value: 'code', label: 'name' }"
v-model="selectedOptions"
@change="handleChange"
:disabled="isViewMode"
>
<template #default="{ node, data }">
<span>{{ data.name }}</span>
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
</template>
</el-cascader>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="详细地址" prop="address">
<el-input v-model="form.address" clearable :disabled="isViewMode" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="6">
<el-form-item label="血型ABO" prop="bloodAbo">
<el-select v-model="form.bloodAbo" placeholder="血型ABO" clearable :disabled="isViewMode">
<el-option
v-for="item in bloodtypeaboList"
:key="item.value"
:label="item.info"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="血型RH" prop="bloodRh">
<el-select v-model="form.bloodRh" placeholder="血型RH" clearable :disabled="isViewMode">
<el-option
v-for="item in bloodtypearhList"
:key="item.value"
:label="item.info"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="婚姻状态" prop="maritalStatusEnum">
<el-select
v-model="form.maritalStatusEnum"
placeholder="婚姻状态"
clearable
:disabled="isViewMode"
>
<el-option
v-for="item in maritalstatusList"
:key="item.value"
:label="item.info"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="死亡时间" prop="deceasedDate">
<el-date-picker
v-model="form.deceasedDate"
type="datetime"
placeholder="请选择时间"
format="YYYY/MM/DD HH:mm:ss"
:disabled="isViewMode"
value-format="YYYY/MM/DD HH:mm:ss"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script setup>
import { watch } from 'vue';
import pcas from 'china-division/dist/pcas-code.json';
import { patientFormInit } from './api';
const { proxy } = getCurrentInstance();
const {
patient_gender_enum,
sys_idtype,
prfs_enum,
blood_rh,
blood_abo,
marital_status_enum,
patient_temp_flag,
link_relation_code,
nationality_code,
} = proxy.useDict(
'patient_gender_enum',
'sys_idtype',
'prfs_enum',
'blood_rh',
'blood_abo',
'marital_status_enum',
'patient_temp_flag',
'link_relation_code',
'nationality_code'
);
const selectedOptions = ref([]); // v-model 绑定的选中值
const maritalstatusList = ref([]); //婚姻
const occupationtypeList = ref([]); //职业
const administrativegenderList = ref([]); //性别
const bloodtypeaboList = ref([]); //血型abo
const bloodtypearhList = ref([]); //血型RH
const familyrelationshiptypeList = ref([]); //家庭关系
// 使用 ref 定义查询所得用户信息数据
const patientInfo = ref(undefined);
const addressCom = ref(''); //地址
const options = ref(pcas); // 地区数据
const emits = defineEmits(['submit']); // 声明自定义事件
const data = reactive({
isViewMode: false,
form: {
typeCode: '01',
},
rules: {
name: [{ required: true, message: '姓名不能为空', trigger: 'change' }],
genderEnum: [{ required: true, message: '请选择性别', trigger: 'change' }],
age: [{ required: true, message: '年龄不能为空', trigger: 'change' }],
phone: [{ required: true, message: '联系方式不能为空', trigger: 'change' }],
},
});
const { queryParams, form, rules, isViewMode } = toRefs(data);
const props = defineProps({
item: {
type: Object,
required: false,
},
});
watch(
() => form.value.idCard,
(newIdCard) => {
if (newIdCard && newIdCard.length === 18) {
const birthYear = parseInt(newIdCard.substring(6, 10));
const birthMonth = parseInt(newIdCard.substring(10, 12));
const birthDay = parseInt(newIdCard.substring(12, 14));
const today = new Date();
const currentYear = today.getFullYear();
const currentMonth = today.getMonth() + 1;
const currentDay = today.getDate();
let age = currentYear - birthYear;
// 如果当前月份小于出生月份或者月份相同但当前日期小于出生日期则年龄减1
if (currentMonth < birthMonth || (currentMonth === birthMonth && currentDay < birthDay)) {
age--;
}
form.value.age = age;
}
}
);
getList();
/** 查询菜单列表 */
function getList() {
patientFormInit().then((response) => {
console.log(response);
occupationtypeList.value = response.data.occupationType;
administrativegenderList.value = response.data.sex;
bloodtypeaboList.value = response.data.bloodTypeABO;
bloodtypearhList.value = response.data.bloodTypeRH;
familyrelationshiptypeList.value = response.data.familyRelationshipType;
maritalstatusList.value = response.data.maritalStatus;
});
}
//地址选择
const handleChange = () => {
const checkedNodes = selectedOptions.value.map((code) => {
const node = findNodeByCode(options.value, code);
return node ? node.name : null;
});
form.value.addressProvince = checkedNodes[0] || '';
form.value.addressCity = checkedNodes[1] || '';
form.value.addressDistrict = checkedNodes[2] || '';
form.value.addressStreet = checkedNodes[3] || '';
form.value.address = '';
};
// 递归查找节点
const findNodeByCode = (data, code) => {
for (const item of data) {
if (item.code === code) return item;
if (item.children) {
const result = findNodeByCode(item.children, code);
if (result) return result;
}
}
return null;
};
/** 表单重置 */
function reset() {
form.value = {
name: undefined,
nameJson: undefined,
menuName: undefined,
age: undefined,
genderEnum: undefined,
typeCode: '01',
idCard: undefined,
phone: undefined,
prfsEnum: undefined,
address: undefined,
tempFlag: undefined,
countryCode: undefined,
bloodRh: undefined,
bloodAbo: undefined,
nationalityCode: undefined,
deceasedDate: undefined,
linkName: undefined,
linkRelationCode: undefined,
linkTelcom: undefined,
workCompany: undefined,
addressCity: undefined,
addressDistrict: undefined,
addressStreet: undefined,
addressProvince: undefined,
maritalStatusEnum: undefined,
busNo: undefined,
organizationId: undefined,
};
proxy.resetForm('patientRef');
}
defineExpose({ form });
</script>
<style scoped>
.el-form--inline .el-form-item {
display: inline-flex;
vertical-align: middle;
margin-right: 10px !important;
}
/* 使用深度选择器 */
.custom-label-spacing :deep(.el-form-item__label) {
line-height: 1.2; /* 调整行间距 */
margin-bottom: 4px; /* 调整 label 和输入框之间的间距 */
}
</style>

View File

@@ -0,0 +1,317 @@
<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"
:registrationType="props.registrationType"
:initOptions="initOptions"
:noFile="noFile"
ref="patientInfoRef"
@onChangFeeType="onChangFeeType"
/>
<!-- <PatientRelationList
class="relationList"
:patCode="patientInfo.code"
ref="PatientRelationListRef"
/> -->
<!--联系人组件 -->
<RegisterForm
:code="code"
ref="RegisterFormRef"
:patientInfo="patientApiInfo"
:initOptions="initOptions"
:alreadyEdit="alreadyEdit"
:inHospitalInfo="inHospitalInfo"
:noFile="noFile"
/>
</el-scrollbar>
<template v-slot:footer>
<div class="advance-container">
<el-space>
<div>缴费预交金</div>
<el-input
style="width: 142px"
placeholder="请输入"
v-model="advance"
@input="handleAdvanceInput"
:formatter="handleAdvanceFormatter"
:parser="handleAdvanceParser"
></el-input>
<div
class="feeType"
:class="currentFeeType == typeitem.type ? 'activeFeeType' : ''"
v-for="typeitem in feeTypeOptions"
:key="typeitem.type"
@click="currentFeeType = typeitem.type"
>
<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 size="fixed" type="primary" @click="handleSubmit">登记</el-button>
<!-- <hip-button size="fixed" type="primary" @click="supplementMi">医保登记</hip-button> -->
<!-- <AdvancePayment
v-model="advancePaymentVisible"
@submitOk="advancePaymentSubmitOk"
:money="advance"3
/> -->
</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, getInit } from './api';
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,
},
});
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 cancelAct = () => {
emits('cancelAct');
};
const patientInfoRef = ref();
/* 预交金 */
const advancePaymentVisible = ref(false);
/* 保存 */
const handleSubmit = () => {
let params = {};
if (props.noFile) {
RegisterFormRef.value.validateData(async () => {
params.inHospitalInfo = RegisterFormRef.value.submitForm;
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) {
emits('okAct');
ElMessage.success(res.msg);
advancePaymentVisible.value = true;
} 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 };
console.log('params', params);
const performRegistration = () => {
registerInHospital(params).then((res) => {
if (res.code == 200) {
emits('okAct');
ElMessage.success(res.msg);
advancePaymentVisible.value = true;
} 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) => {
initOptions.value = res.data;
});
});
/* 登记 */
const RegisterFormRef = ref();
const feeTypeOptions = reactive([
{
type: 'hipCash',
label: '现金',
},
{
type: 'hipAlipay',
label: '支付宝',
},
{
type: 'wechat',
label: '微信',
},
{
type: 'hipPayCard',
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;
};
/* */
</script>
<style lang="scss" scoped>
.patientRegister-container {
height: 700px;
overflow-y: auto;
}
.advance-container {
width: 660px;
display: flex;
.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>

View File

@@ -0,0 +1,440 @@
<template>
<div class="registerForm-container">
<div class="operate">
<div>住院信息</div>
</div>
<el-form
class="register-from"
:model="submitForm"
style="padding-left: 8px"
ref="registerRef"
label-width="80px"
:rules="rules"
>
<el-row :gutter="8">
<el-col :span="6">
<el-form-item label="住院号:" prop="encounterBusNo">
{{ submitForm.busNo ? submitForm.busNo : '-' }}
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="住院次数:" prop="hospitalizationCount" autocomplete="off">
{{ submitForm.inHospitalCount }}
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="入院科室" prop="inHospitalOrgId">
<el-tree-select
clearable
style="width: 100%"
v-model="submitForm.inHospitalOrgId"
filterable
:data="organization"
:props="{
value: 'id',
label: 'name',
children: 'children',
}"
value-key="id"
check-strictly
:check-strictly-except-leaf="false"
:default-expand-all="true"
placeholder="请选择入院科室"
@change="handleChange"
@node-click="handleNodeClick"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="入院病区" prop="wardLocationId">
<el-select :disabled="props.alreadyEdit" v-model="submitForm.wardLocationId">
<el-option
v-for="item in wardListOptions"
:key="item.id"
:label="item.name"
:value="item.id"
@click="handleWardClick(item)"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="床位数:" prop="bedCount">
{{
submitForm.totalBedsNum ? submitForm.idleBedsNum + '/' + submitForm.totalBedsNum : '-'
}}
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="门诊医生" prop="ambDoctorPractitionerName">
<el-input disabled v-model="submitForm.ambDoctorPractitionerName" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="诊断类别" prop="medTypeCode">
<el-select
v-model="submitForm.medTypeCode"
placeholder="诊断类别"
clearable
filterable
@change="
(value) => {
submitForm.ybClassEnum = value;
}
"
>
<el-option
v-for="item in med_type"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6" v-if="!props.noFile">
<el-form-item label="入院诊断" prop="ambDiagnosisName">
<el-input v-model="submitForm.ambDiagnosisName" disabled />
</el-form-item>
</el-col>
<el-col :span="6" v-else>
<el-form-item label="入院诊断" prop="diagnosisDefinitionId">
<el-select
v-model="submitForm.diagnosisDefinitionId"
placeholder="入院诊断"
clearable
filterable
remote
:remote-method="getDiagnosisInfo"
>
<el-option
v-for="item in diagnosisDefinitionList"
:key="item.id"
:label="item.name"
:value="item.id"
@click="handleDiagnosisChange(item)"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6" v-if="props.noFile">
<el-form-item label="诊断描述" prop="diagnosisDesc">
<el-input v-model="submitForm.diagnosisDesc" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="患者病情">
<el-select v-model="submitForm.priorityEnum">
<el-option
v-for="item in props.initOptions.priorityEnumList"
:key="item.value"
:label="item.info"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="入院类型" prop="admitSourceCode">
<el-select v-model="submitForm.admitSourceCode">
<el-option
v-for="item in admit_source_code"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="入院方式" prop="inWayCode">
<el-select v-model="submitForm.inWayCode">
<el-option
v-for="item in in_way_code"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="费用性质">
<el-select
v-model="submitForm.contractNo"
placeholder="费用性质"
clearable
@change="getValue"
>
<el-option
v-for="item in contractList"
:key="item.busNo"
:label="item.contractName"
:value="item.busNo"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="入院日期" prop="startTime">
<el-date-picker
v-model="submitForm.startTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="date"
placeholder="请选择日期"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</template>
<script setup>
import {
getInit,
getOrgList,
wardList,
diagnosisInit,
getBedInfo,
getContractList,
getDiagnosisDefinitionList,
} from './api';
const { proxy } = getCurrentInstance();
const { in_way_code, admit_source_code, med_type } = proxy.useDict(
'in_way_code',
'admit_source_code',
'med_type'
);
import { formatDateStr } from '@/utils';
const emits = defineEmits([]);
const props = defineProps({
patientInfo: {
type: Object,
require: true,
default: () => ({}),
},
inHospitalInfo: {
type: Object,
require: true,
default: () => ({}),
},
initOptions: {
type: Object,
require: true,
default: () => ({}),
},
alreadyEdit: {
type: Boolean,
default: false,
},
noFile: {
type: Boolean,
default: false,
},
});
const organization = ref([]);
const wardListOptions = ref([]);
const contractList = ref([]);
const verificationStatusOptions = ref([]);
const diagnosisDefinitionList = ref([]);
const rules = reactive({
inHospitalOrgId: [
{
required: true,
message: '入院科室未填写',
trigger: ['blur', 'change'],
},
],
wardLocationId: [
{
required: true,
message: '入院病区未填写',
trigger: ['blur', 'change'],
},
],
startTime: [
{
required: true,
message: '入院日期未填写',
trigger: ['blur', 'change'],
},
],
diagnosisDefinitionId: [
{
required: true,
message: '入院诊断未填写',
trigger: ['blur', 'change'],
},
],
diagnosisDesc: [
{
required: true,
message: '诊断描述未填写',
trigger: ['blur', 'change'],
},
],
});
/* 提交表单 */
const submitForm = reactive({
inHospitalOrgId: props.inHospitalInfo.inHospitalOrgId,
ambDoctorPractitionerName: props.inHospitalInfo.ambDoctorPractitionerName,
wardLocationId: props.inHospitalInfo.wardLocationId, // 入院护理组编码
admitSourceCode: '', // 患者入院类型字典PatientSource
inWayCode: '', // 入院方式字典InpWay
startTime: formatDateStr(new Date(), 'YYYY-MM-DD HH:mm:ss'), // 入院日期
priorityEnum: props.inHospitalInfo.priorityEnum, // 患者病情字典PatAdmCondition
ambDiagnosisName: props.inHospitalInfo.ambDiagnosisName,
medTypeCode: '21',
});
/* 科室 病区 */
watch(
() => submitForm.inDocterWorkGroupCode,
(newValue) => {
if (newValue) {
if (newValue == '') {
submitForm.wardLocationId = '';
}
} else {
submitForm.wardLocationId = '';
}
}
);
watch(
() => submitForm.inNurseDeptCode,
(newValue) => {
if (newValue) {
getBedInfo(newValue);
}
}
);
onMounted(() => {
getInitOptions();
setValue();
});
function handleWardClick(item) {
submitForm.wardBusNo = item.busNo;
getBedInfo(submitForm.wardBusNo).then((res) => {
submitForm.totalBedsNum = res.data.totalBedsNum;
submitForm.idleBedsNum = res.data.idleBedsNum;
});
}
function getInitOptions() {
getOrgList().then((res) => {
organization.value = res.data.records;
});
if (!props.noFile) {
wardList().then((res) => {
wardListOptions.value = res.data;
});
}
diagnosisInit().then((res) => {
verificationStatusOptions.value = res.data.verificationStatusOptions;
});
getContractList().then((response) => {
contractList.value = response.data;
setValue();
});
getDiagnosisInfo(undefined);
}
function getDiagnosisInfo(value) {
getDiagnosisDefinitionList({ pageSize: 500, pageNo: 1, searchKey: value }).then((res) => {
diagnosisDefinitionList.value = res.data.records;
});
}
function handleNodeClick(orgInfo) {
wardList({ orgId: orgInfo.id }).then((res) => {
wardListOptions.value = res.data;
});
}
function handleChange(value) {
if (!value) {
wardListOptions.value = [];
submitForm.wardLocationId = undefined;
}
}
function handleDiagnosisChange(item) {
submitForm.diagnosisYbNo = item.ybNo;
submitForm.diagnosisDefinitionId = item.id;
}
function setValue() {
submitForm.encounterId = props.inHospitalInfo?.encounterId;
submitForm.busNo = props.inHospitalInfo?.busNo;
submitForm.contractNo = props.inHospitalInfo?.contractNo;
submitForm.inHospitalCount = props.inHospitalInfo?.inHospitalCount;
submitForm.inHospitalOrgId = props.inHospitalInfo?.inHospitalOrgId;
submitForm.inHospitalOrgName = props.inHospitalInfo?.inHospitalOrgName;
submitForm.wardLocationId = props.inHospitalInfo?.wardLocationId;
submitForm.wardName = props.inHospitalInfo?.wardName;
submitForm.wardBusNo = props.inHospitalInfo?.wardBusNo;
submitForm.totalBedsNum = props.inHospitalInfo?.totalBedsNum;
submitForm.idleBedsNum = props.inHospitalInfo?.idleBedsNum;
submitForm.ambEncounterId = props.inHospitalInfo?.ambEncounterId;
submitForm.ambDoctorPractitionerId = props.inHospitalInfo?.ambDoctorPractitionerId;
submitForm.ambDoctorPractitionerName = props.inHospitalInfo?.ambDoctorPractitionerName;
submitForm.ambDiagnosisName = props.inHospitalInfo?.ambDiagnosisName;
submitForm.priorityEnum = props.inHospitalInfo?.priorityEnum;
submitForm.priorityEnum_enumText = props.inHospitalInfo?.priorityEnum_enumText;
submitForm.admitSourceCode = props.inHospitalInfo?.admitSourceCode;
submitForm.admitSourceCode_dictText = props.inHospitalInfo?.admitSourceCode_dictText;
submitForm.inWayCode = props.inHospitalInfo?.inWayCode;
submitForm.inWayCode_dictText = props.inHospitalInfo?.inWayCode_dictText;
}
const registerRef = ref();
/* 登记 */
const validateData = async (callback) => {
if (!registerRef.value) return false;
registerRef.value.validate((valid) => {
if (valid) {
callback();
return true;
} else {
return false;
}
});
};
const init = () => {
submitForm.inDocterWorkGroupCode = '';
submitForm.wardLocationId = '';
};
defineExpose({ validateData, submitForm, init });
</script>
<style lang="scss" scoped>
.registerForm-container {
margin-top: 16px;
.operate {
background: rgba(37, 109, 149, 0.05);
display: flex;
justify-content: space-between;
align-items: center;
height: 32px;
border-radius: 4px 4px 0px 0px;
padding-left: 16px;
color: var(--hip-color-primary-light);
font-weight: bold;
margin-bottom: 8px;
}
.register-from {
padding: 0 8px;
}
:deep(.el-form-item) {
width: 100%;
margin-right: 0px;
}
}
</style>

View File

@@ -0,0 +1,31 @@
<template>
<div class="app-container">
<el-tabs v-model="activeName" type="card" class="demo-tabs">
<el-tab-pane label="待登记入院" name="first">
<AwaitList v-if="activeName === 'first'" @okList="activeName = 'second'" />
</el-tab-pane>
<el-tab-pane label="已登记入院" name="second">
<AccomplishList v-if="activeName === 'second'" />
</el-tab-pane>
<!-- <el-tab-pane label="在院患者" name="third">
<ExistListt />
</el-tab-pane> -->
</el-tabs>
</div>
</template>
<script setup>
import { getCurrentInstance, onBeforeMount, onMounted, reactive, ref } from 'vue';
import { AwaitList, AccomplishList, ExistList } from './components/index.js';
const { proxy } = getCurrentInstance();
const emits = defineEmits([]);
const props = defineProps({});
const state = reactive({});
defineExpose({ state });
const activeName = ref('first');
</script>
<style lang="scss" scoped>
.sds {
background-color: red;
}
</style>

View File

@@ -0,0 +1,55 @@
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
})
}
// 退费
export function inpaUnPay(data) {
return request({
url: '/payment/payment/inpa-un-pay',
method: 'post',
data: data
})
}

View File

@@ -0,0 +1,363 @@
<!--
* @Author: X_bo v-hss@tbpartners.local
* @Date: 2025-08-15 10:00:37
* @LastEditTime: 2025-08-15 14:18:01
* @LastEditors: X_bo v-hss@tbpartners.local
* @Description:
* @FilePath: \openhis-ui-vue3\src\views\inHospitalManagement\charge\settleAccounts\index.vue
-->
<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="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>
<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="400">
<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="handleRefund(scope.row)" :disabled="scope.row.paymentEnum != 0 || scope.row.outcomeEnum == 3">退费</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>
<!-- 退费原因弹窗 -->
<el-dialog title="退费原因" v-model="refundDialogVisible" width="30%">
<el-form :model="refundForm" label-width="80px">
<el-form-item
label="退费原因"
prop="reason"
:rules="[
{ required: true, message: '请输入退费原因', trigger: 'blur' },
{ min: 1, max: 200, message: '长度在1到200个字符之间', trigger: 'blur' }
]"
>
<el-input v-model="refundForm.reason" placeholder="请输入退费原因" type="textarea" :rows="3" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="refundDialogVisible = false"> </el-button>
<el-button type="primary" @click="submitRefund"> </el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup name="ClinicRecord">
const { proxy } = getCurrentInstance();
import { getList ,invoiceMzInvoice,invoiceReissue,invoiceWriteoff,invoiceOpen,paymentDetail,inpaUnPay} from './components/api.js';
import { formatDate } from '@/utils/index';
const occurrenceTime = ref([
formatDate(new Date(new Date().getFullYear(), new Date().getMonth() - 1, new Date().getDate())),
formatDate(new Date())
]);
const total = ref(0);
const queryParams = ref({
pageNo: 1,
pageSize: 10,
billDateSTime:"",
billDateETime:"",
searchKey:"",
kinsEnum: 2
});
// 初始化时设置时间参数
queryParams.value.billDateSTime = occurrenceTime.value[0] + " 00:00:00";
queryParams.value.billDateETime = occurrenceTime.value[1] + " 23:59:59";
const paymentDetailShow = ref(false)
const clinicRecord = ref([]);
const reasonDialogVisible = ref(false);
const reasonForm = ref({
reason: ''
});
const currentRow = ref(null);
const paymentDetailList = ref([])
const refundDialogVisible = ref(false);
const refundForm = ref({
reason: '',
paymentId: '',
encounterId: ''
});
const currentRefundRow = ref(null);
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){
// }
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)=>{
})
}
}
function handleRefund(row) {
currentRefundRow.value = row;
refundForm.value.reason = '';
refundForm.value.paymentId = row.paymentId || row.id;
refundForm.value.encounterId = row.encounterId || '';
refundDialogVisible.value = true;
}
function submitRefund() {
// 使用表单验证
if (!refundForm.value.reason || refundForm.value.reason.trim() === '') {
proxy.$message.warning('请输入退费原因');
return;
}
if (refundForm.value.reason.length > 200) {
proxy.$message.warning('退费原因长度不能超过200个字符');
return;
}
const refundData = {
id: refundForm.value.paymentId,
reason: refundForm.value.reason,
encounterId: refundForm.value.encounterId ? refundForm.value.encounterId : ""
};
inpaUnPay(refundData).then((res) => {
if (res.code == 200) {
proxy.$message.success('退费成功');
refundDialogVisible.value = false;
getLists();
}else {
proxy.$message.error(res.data);
}
}).catch((err) => {
console.error(err);
});
}
</script>
<style scoped>
.el-dialog{
height: 90vh!important;
}
.dialog-footer {
text-align: right;
}
.el-textarea__inner {
resize: none;
}
</style>

View File

@@ -0,0 +1,337 @@
<!--
* @Author: hezhibo@bjgoodwill.com
* @Date: 2025-03-10 17:21:55
* @Description:
-->
<template>
<div class="hospitalizationSettlementCancel-container">
<div class="operate-container">
<el-space>
<el-input v-model="queryForm.searchValue" style="width: 304px" placeholder="请输入" class="searchValue"
@keyup.enter="queryPatient" clearable>
<template #prepend>
<el-select v-model="queryForm.searchType" placeholder="" style="width: 115px">
<el-option label="发票号" value="receipt" />
<el-option label="住院号" value="inpatientCode" />
</el-select>
</template>
</el-input>
<el-button style="margin-right: 0px" @click="queryPatient">查询</el-button>
</el-space>
<el-space>
<el-button style="margin-right: 0px" @click="goSettleCancel"
:disabled="!currentPatient?.visitCode">取消结算</el-button>
</el-space>
</div>
<!-- // TODO 患者信息 -->
<div>患者信息</div>
<div class="billData-container">
<el-table :data="queryPpatientList" height="186px" show-overflow-tooltip :style="{ height: '100%' }">
<el-table-column prop="name" label="姓名" min-width="131" />
<el-table-column prop="inpatientCode" label="住院号" width="167" />
<el-table-column prop="settleNo" label="发票号" min-width="210" />
<el-table-column prop="feeTypeName" label="类别" min-width="155" />
<el-table-column prop="settleTypeName" label="结算类型" min-width="174" />
<el-table-column prop="createdStaffName" label="结算人" min-width="145" />
<template v-slot:empty>
<div>
<div class="empty-text-sty">暂无数据</div>
</div>
</template>
</el-table>
</div>
<div class="pay-container">
<div class="payList-container">
<div class="totals">
<el-space class="costcollect" :size="32">
<span>费用总额: <span class="costValue">{{ econDetailsInfo.totalAmount }}</span></span>
<span>预缴金: <span class="costValue">{{ econDetailsInfo.prepayAmount }}</span></span>
<span>已补收: <span class="costValue">{{ econDetailsInfo.payAmount }}</span></span>
</el-space>
</div>
<div class="payListData-container">
<div>
<el-table :data="econDetailsInfo.bpubTypeList" height="186px" show-overflow-tooltip
:style="{ height: '100%' }">
<el-table-column prop="nameLeft" label="缴费方式" width="165" />
<el-table-column prop="costRight" label="金额" width="159" align="right" header-align="left" />
<template v-slot:empty>
<div>
<div class="empty-text-sty">暂无数据</div>
</div>
</template>
</el-table>
</div>
<div>
<el-table :data="econDetailsInfo.econIpdSettlePayAsToList" height="186px" show-overflow-tooltip
:style="{ height: '100%' }">
<el-table-column prop="paywayName" label="缴费方式" width="165" />
<el-table-column prop="amount" label="金额" min-width="159" align="right" header-align="left" />
<el-table-column prop="returnWay" label="返还方式" min-width="145">
<template #default="{ row }">
<el-select v-model="row.returnWay" placeholder="返还方式" style="width: 100%">
<el-option label="转押金" value="1" />
</el-select>
</template>
</el-table-column>
<template v-slot:empty>
<div>
<div class="empty-text-sty">暂无数据</div>
</div>
</template>
</el-table>
</div>
</div>
</div>
<div class="currentbill-container">
<div class="totals">
<span class="countTitle">退还金额: <span class="countValue">1500.00</span></span>
</div>
<div class="eceivableDetails">
<div>
<span>转押金</span>
<span>2490.00</span>
</div>
<div>
<span>微信</span>
<span>200.00</span>
</div>
<div>
<span>支付宝</span>
<span>1500.00</span>
</div>
<div>
<span>银行卡</span>
<span>2000.00</span>
</div>
<div>
<span>现金</span>
<span>-</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup >
import { getCurrentInstance, onBeforeMount, onMounted, reactive, ref } from 'vue'
import { ElMessage } from 'element-plus'
import dayjs from 'dayjs'
import { round } from 'lodash-es'
const emits = defineEmits([])
const props = defineProps({})
const state = reactive({})
/* 查询患者 */
const queryForm = reactive({
searchValue: '',
ward: '',
inPatientId: '',
searchType: 'receipt',
})
const patientsBarRef = ref()
// const queryPpatientList = ref<Array<any>>([])
// const currentPatient = ref<Partial<any>>() // 当前
/* 查询患者 */
const queryPatient = () => {
// TODO 查询患者接口
//1. 根据输入精确匹配,根据主索引查找患者时,如果有多条住院记录,弹出患者选择控件
}
/* 患者费用信息 */
// const econDetailsInfo = ref<{
// bpubTypeList: []
// econIpdSettlePayAsToList: Array<any>
// payAmount: 0
// prepayAmount: 0
// totalAmount: 0
// }>({
// bpubTypeList: [],
// econIpdSettlePayAsToList: [],
// payAmount: 0,
// prepayAmount: 0,
// totalAmount: 0,
// })
const getEconDetails = () => {
if (currentPatient.value && currentPatient.value.settleId) {
}
}
/* 弹窗 */
/* 患者列表,弹窗 */
const patientListDialogVisible = ref(false)
/* 结算取消 */
const goSettleCancel = () => {
if (currentPatient.value?.visitCode) {
ElMessage({
message: '结算取消成功!',
type: 'success',
grouping: true,
showClose: true,
})
}
}
// onBeforeMount(() => {
// })
// onMounted(() => {
// })
defineExpose({ state })
</script>
<style lang="scss" scoped>
.hospitalizationSettlementCancel-container {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
font-family: '思源黑体 CN';
font-weight: 400;
.operate-container {
height: 56px;
padding: 0 16px;
display: flex;
align-items: center;
background-color: #ffffff;
justify-content: space-between;
border-bottom: 2px solid #e9f3f9;
flex: none;
:deep(.el-input) {
.el-input-group__prepend {
div.el-select {
.el-select__wrapper {
background-color: #ffffff !important;
}
}
}
}
}
.patientBar {
box-shadow: 0px 2px 2px 0px rgba(199, 224, 240, 0.4);
background: #ffffff;
flex: none;
}
.billData-container {
height: 154px;
padding: 16px;
border-bottom: 8px solid #f1faff;
flex: none;
}
.pay-container {
width: 100%;
display: flex;
flex: auto;
height: 100px;
.totals {
height: 56px;
border-bottom: 2px solid #f1faff;
box-shadow: 0px 1px 1px 0px rgba(181.05, 210.63, 255, 0.25);
line-height: 56px;
padding: 0 16px;
.costcollect {
span {
color: #666666;
}
.costValue {
color: #ff8616 !important;
font-size: 20px;
}
}
.countTitle {
font-size: 20px;
}
.countValue {
font-size: 32px;
color: #e95657;
font-weight: 500;
}
}
.payList-container {
flex: auto;
width: 100px;
.payListData-container {
width: calc(100% - 32px);
padding: 8px 16px;
display: flex;
height: calc(100% - 74px);
>div:first-child {
width: 324px;
flex: none;
}
>div:nth-child(2) {
width: calc(100% - 340px);
margin-left: 16px;
flex: auto;
.el-table {
width: 100%;
}
}
}
}
.currentbill-container {
border-left: 8px solid #f1faff;
width: 380px;
flex: none;
// border: 1px solid #DDDDDD;
.eceivableDetails {
padding-top: 29px;
>div {
border-bottom: 2px solid #eeeeee;
height: 40px;
line-height: 40px;
margin: 0 24px;
font-size: 22px;
span:first-child {
width: 138px;
display: inline-block;
text-align: right;
font-weight: 400;
color: #666666;
}
span:nth-child(2) {
width: 80px;
display: inline-block;
text-align: right;
font-weight: 400;
color: #333333;
}
// span:nth-child(2) {
// color: #333333;
// }
span {
&:nth-child(2) {
color: #333333;
min-width: 120px;
text-align: right;
// border: 1px solid red
}
}
}
}
}
}
}
</style>

View File

@@ -0,0 +1,80 @@
<!--
* @Author: hezhibo@bjgoodwill.com
* @Date: 2025-02-25 14:46:43
* @Description:
-->
<template>
<el-dialog v-model="visible" ref="returnStoreDialogAddRef" @open="okActTh" @close="closedAct" width="388px"
title="添加费用减免">
<el-form :model="form" ref="derateRef" label-width="auto" style="max-width: 600px" :rules="rules">
<el-form-item label="减免项目">
<el-select v-model="form.region" placeholder="减免项目">
<el-option label="全部" value="0" />
<el-option :label="bpubType.elementName" value="bpubType.elementCode" v-for="bpubType in bpubTypeOption"
:key="bpubType" />
</el-select>
</el-form-item>
</el-form>
<template v-slot:tool>
<el-button @click="close" class="margin-left-auto" type="plain">取消</el-button>
<el-button @click="submitForm" class="confirm-button" type="primary">确定</el-button>
</template>
</el-dialog>
</template>
<script setup lang='ts'>
import { FormRules } from 'element-plus';
import { getCurrentInstance, onBeforeMount, onMounted, reactive, ref } from 'vue'
// const { proxy } = getCurrentInstance();
const emits = defineEmits(["derateOk"])
const props = defineProps({
})
const state = reactive({
})
const visible = defineModel('visible', { type: Boolean, default: false });
function okActTh(row: any) {
// if (thFlag.value === true || currentDataNumberPZH.value === '无启用收据') {
// ElMessage.warning('无在用收据或使用共享号段时不能操作跳号!');
// }
derateRef.value.resetFields()
}
const closedAct = () => {
visible.value = false;
};
const derateRef = ref()
const form = reactive({
amount: 0,
region: '0',
})
const bpubTypeOption = ref<Array<any>>([])
const rules = reactive<FormRules<any>>({
amount: [
{ required: true, message: '请输入减免金额', trigger: 'blur' },
],
})
const close = () => {
visible.value = false;
};
const submitForm = () => {
if (!derateRef.value) return false
derateRef.value.validate((valid: boolean) => {
if (valid) {
emits('derateOk', form.amount)
return true
} else {
return false
}
})
};
onMounted(() => {
derateRef.value && derateRef.value.resetFields()
})
defineExpose({ state })
</script>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,13 @@
/*
* @Author: hezhibo@bjgoodwill.com
* @Date: 2025-03-07 16:57:42
* @Description:
*/
import receipt from './receipt.vue'
import refund from './refund.vue'
import patientList from './patientList.vue'
import invoiceSkip from './invoiceSkip.vue'
import derate from './derate.vue'
import patientListDialog from './patientListDialog.vue'
import preSettlement from './preSettlement.vue'
export { receipt, refund, patientList, invoiceSkip, derate, patientListDialog, preSettlement }

View File

@@ -0,0 +1,399 @@
<!--
* @Author: hezhibo@bjgoodwill.com
* @Date: 2025-03-10 17:21:55
* @Description:
-->
<template>
<div class="hospitalizationSettlementCancel-container">
<div class="operate-container">
<el-space>
<el-input v-model="queryForm.searchValue" style="width: 304px" placeholder="请输入" class="searchValue"
@keyup.enter="queryPatient" clearable>
<template #prepend>
<el-select v-model="queryForm.searchType" placeholder="" style="width: 115px">
<el-option label="发票号" value="receipt" />
<el-option label="住院号" value="inpatientCode" />
</el-select>
</template>
</el-input>
<el-button style="margin-right: 0px" @click="queryPatient">查询</el-button>
</el-space>
<el-space>
<el-button style="margin-right: 0px" @click="goSettleCancel"
:disabled="!currentPatient?.visitCode">取消结算</el-button>
</el-space>
</div>
<div> //患者信息</div>
<!-- // TODO el-dialog -->
<div class="billData-container">
<el-table :data="queryPpatientList" height="186px" show-overflow-tooltip :style="{ height: '100%' }">
<el-table-column prop="name" label="姓名" min-width="131" />
<el-table-column prop="inpatientCode" label="住院号" width="167" />
<el-table-column prop="settleNo" label="发票号" min-width="210" />
<el-table-column prop="costs" label="金额" width="160" align="right" header-align="left" :formatter="(row) => {
return row.costs && round(row.costs, 2).toFixed(2)
}
" />
<el-table-column prop="feeTypeName" label="类别" min-width="155" />
<el-table-column prop="settleTypeName" label="结算类型" min-width="174" />
<el-table-column prop="createdDate" label="结算时间" min-width="194" :formatter="(row) => {
return row.createdDate && dayjs(row.createdDate).format('YYYY/MM/DD HH:mm')
}
" />
<el-table-column prop="createdStaffName" label="结算人" min-width="145" />
<template v-slot:empty>
<div>
<div class="empty-text-sty">暂无数据</div>
</div>
</template>
</el-table>
</div>
<div class="pay-container">
<div class="payList-container">
<div class="totals">
<el-space class="costcollect" :size="32">
<span>费用总额: <span class="costValue">{{ econDetailsInfo.totalAmount }}</span></span>
<span>预缴金: <span class="costValue">{{ econDetailsInfo.prepayAmount }}</span></span>
<span>已补收: <span class="costValue">{{ econDetailsInfo.payAmount }}</span></span>
</el-space>
</div>
<div class="payListData-container">
<div>
<el-table :data="econDetailsInfo.bpubTypeList" height="186px" show-overflow-tooltip
:style="{ height: '100%' }">
<el-table-column prop="nameLeft" label="缴费方式" width="165" />
<el-table-column prop="costRight" label="金额" width="159" align="right" header-align="left" />
<template v-slot:empty>
<div>
<div class="empty-text-sty">暂无数据</div>
</div>
</template>
</el-table>
</div>
<div>
<el-table :data="econDetailsInfo.econIpdSettlePayAsToList" height="186px" show-overflow-tooltip
:style="{ height: '100%' }">
<el-table-column prop="paywayName" label="缴费方式" width="165" />
<el-table-column prop="amount" label="金额" min-width="159" align="right" header-align="left" />
<el-table-column prop="returnWay" label="返还方式" min-width="145">
<template #default="{ row }">
<el-select v-model="row.returnWay" placeholder="返还方式" style="width: 100%">
<el-option label="转押金" value="1" />
</el-select>
</template>
</el-table-column>
<template v-slot:empty>
<div>
<div class="empty-text-sty">暂无数据</div>
</div>
</template>
</el-table>
</div>
</div>
</div>
<div class="currentbill-container">
<div class="totals">
<span class="countTitle">退还金额: <span class="countValue">1500.00</span></span>
</div>
<div class="eceivableDetails">
<div>
<span>转押金</span>
<span>2490.00</span>
</div>
<div>
<span>微信</span>
<span>200.00</span>
</div>
<div>
<span>支付宝</span>
<span>1500.00</span>
</div>
<div>
<span>银行卡</span>
<span>2000.00</span>
</div>
<div>
<span>现金</span>
<span>-</span>
</div>
</div>
</div>
</div>
<patientListDialog v-model:visible="patientListDialogVisible" :patientList="queryPpatientList" />
</div>
</template>
<script setup >
import { getCurrentInstance, onBeforeMount, onMounted, reactive, ref } from 'vue'
import { ElMessage } from 'element-plus'
import dayjs from 'dayjs'
import { round } from 'lodash-es'
// const { proxy } = getCurrentInstance();
const emits = defineEmits([])
const props = defineProps({})
const state = reactive({})
/* 查询患者 */
const queryForm = reactive({
searchValue: '',
ward: '',
inPatientId: '',
searchType: 'receipt',
})
const patientsBarRef = ref()
// const queryPpatientList = ref<Array<any>>([])
// const currentPatient = ref<Partial<any>>() // 当前
/* 查询患者 */
const queryPatient = () => {
// TODO 查询患者接口
//1. 根据输入精确匹配,根据主索引查找患者时,如果有多条住院记录,弹出患者选择控件
getPatInfo({
inpatientCode: queryForm.searchType == 'inpatientCode' ? queryForm.searchValue : undefined,
invoiceNo: queryForm.searchType == 'receipt' ? queryForm.searchValue : undefined,
})
.then((res) => {
if (res && res.length == 1) {
queryPpatientList.value = res
currentPatient.value = res[0]
try {
if (currentPatient.value) {
getEconDetails()
patientsBarRef.value.fetchPatientInfoById(currentPatient.value.visitCode)
}
} catch (error) {
console.log(error)
}
} else if (res && res.length > 1) {
queryPpatientList.value = res
patientListDialogVisible.value = true
} else {
ElMessage({
message: '未查询到患者!',
type: 'info',
grouping: true,
showClose: true,
})
queryPpatientList.value = []
currentPatient.value = {}
}
})
.catch((error) => {
console.log(error)
queryPpatientList.value
})
}
/* 患者费用信息 */
// const econDetailsInfo = ref<{
// bpubTypeList: []
// econIpdSettlePayAsToList: Array<any>
// payAmount: 0
// prepayAmount: 0
// totalAmount: 0
// }>({
// bpubTypeList: [],
// econIpdSettlePayAsToList: [],
// payAmount: 0,
// prepayAmount: 0,
// totalAmount: 0,
// })
const getEconDetails = () => {
if (currentPatient.value && currentPatient.value.settleId) {
getPatInpatientEconInfo(currentPatient.value.settleId).then((res) => {
econDetailsInfo.value = res
econDetailsInfo.value.econIpdSettlePayAsToList =
econDetailsInfo.value.econIpdSettlePayAsToList.map((i) => {
return { ...i, returnWay: '1' }
})
})
}
}
/* 弹窗 */
/* 患者列表,弹窗 */
const patientListDialogVisible = ref(false)
/* 结算取消 */
const goSettleCancel = () => {
if (currentPatient.value?.visitCode) {
cancelSettle({
patIndexCode: currentPatient.value?.patCode,
amount: econDetailsInfo.value.payAmount,
visitCode: currentPatient.value?.visitCode, // 经济结算-住院流水号s
feeType: currentPatient.value?.feeType, // 经济结算-费别
settleId: currentPatient.value?.settleId,
econCancelSettlePrepayAsTo: econDetailsInfo.value.econIpdSettlePayAsToList.map((i) => {
return { id: i.id }
}),
}).then((res) => {
ElMessage({
message: '结算取消成功!',
type: 'success',
grouping: true,
showClose: true,
})
getEconDetails()
//TODO 结算取消成功,处理后续
})
}
}
// onBeforeMount(() => {
// })
// onMounted(() => {
// })
defineExpose({ state })
</script>
<style lang="scss" scoped>
.hospitalizationSettlementCancel-container {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
font-family: '思源黑体 CN';
font-weight: 400;
.operate-container {
height: 56px;
padding: 0 16px;
display: flex;
align-items: center;
background-color: #ffffff;
justify-content: space-between;
border-bottom: 2px solid #e9f3f9;
flex: none;
:deep(.el-input) {
.el-input-group__prepend {
div.el-select {
.el-select__wrapper {
background-color: #ffffff !important;
}
}
}
}
}
.patientBar {
box-shadow: 0px 2px 2px 0px rgba(199, 224, 240, 0.4);
background: #ffffff;
flex: none;
}
.billData-container {
height: 154px;
padding: 16px;
border-bottom: 8px solid #f1faff;
flex: none;
}
.pay-container {
width: 100%;
display: flex;
flex: auto;
height: 100px;
.totals {
height: 56px;
border-bottom: 2px solid #f1faff;
box-shadow: 0px 1px 1px 0px rgba(181.05, 210.63, 255, 0.25);
line-height: 56px;
padding: 0 16px;
.costcollect {
span {
color: #666666;
}
.costValue {
color: #ff8616 !important;
font-size: 20px;
}
}
.countTitle {
font-size: 20px;
}
.countValue {
font-size: 32px;
color: #e95657;
font-weight: 500;
}
}
.payList-container {
flex: auto;
width: 100px;
.payListData-container {
width: calc(100% - 32px);
padding: 8px 16px;
display: flex;
height: calc(100% - 74px);
>div:first-child {
width: 324px;
flex: none;
}
>div:nth-child(2) {
width: calc(100% - 340px);
margin-left: 16px;
flex: auto;
.el-table {
width: 100%;
}
}
}
}
.currentbill-container {
border-left: 8px solid #f1faff;
width: 380px;
flex: none;
// border: 1px solid #DDDDDD;
.eceivableDetails {
padding-top: 29px;
>div {
border-bottom: 2px solid #eeeeee;
height: 40px;
line-height: 40px;
margin: 0 24px;
font-size: 22px;
span:first-child {
width: 138px;
display: inline-block;
text-align: right;
font-weight: 400;
color: #666666;
}
span:nth-child(2) {
width: 80px;
display: inline-block;
text-align: right;
font-weight: 400;
color: #333333;
}
// span:nth-child(2) {
// color: #333333;
// }
span {
&:nth-child(2) {
color: #333333;
min-width: 120px;
text-align: right;
// border: 1px solid red
}
}
}
}
}
}
}
</style>

View File

@@ -0,0 +1,99 @@
<template>
<el-dialog
v-model="visible"
ref="returnStoreDialogAddRef"
@ok="okActTh"
@close="closedAct"
width="388px"
title="结算发票跳号"
>
<el-space direction="vertical" :size="24" class="rinvoiceSkipContainer" alignment="flex-start">
<el-space>
<span class="title">当前收据号:</span>
<span>{{ 12312312312 }} </span>
<el-tooltip placement="bottom" content="复制">
<el-icon
icon-class="hipCopy"
height="23px"
width="23px"
class="svg-blue"
@click="copyToClipboard"
/>
</el-tooltip>
</el-space>
<el-space>
<span class="title">调整至:</span>
<el-input
class="hzlb-width"
v-model="newInvoiceNumber"
clearable
placeholder="格式如xx00168x"
></el-input>
<el-button @click="skip" class="confirm-button" style="margin-left: 10px">跳号</el-button>
</el-space>
</el-space>
<template v-slot:tool>
<el-button @click="close" class="margin-left-auto" type="plain">取消</el-button>
<el-button @click="submitForm" class="confirm-button" type="primary">确定</el-button>
</template>
</el-dialog>
</template>
<script setup >
import { ElMessage } from 'element-plus'
import { onMounted, ref } from 'vue'
// const { proxy } = getCurrentInstance();
const emits = defineEmits([])
const props = defineProps({})
const visible = defineModel('visible', { type: Boolean, default: false })
// function okActTh(row: any) {
// // if (thFlag.value === true || currentDataNumberPZH.value === '无启用收据') {
// // ElMessage.warning('无在用收据或使用共享号段时不能操作跳号!');
// // }
// }
const closedAct = () => {
visible.value = false
}
/* */
// const currentInvoiceNumber = ref('1000000000030001')//当前发票号
// 复制当前发票号
const copyToClipboard = async () => {
try {
// 使用 Clipboard API 复制文本
await toClipboard(12312312312)
ElMessage.success('复制成功') // Element Plus 的消息组件
} catch (err) {
ElMessage.error('复制失败')
console.error('复制失败:', err)
}
}
const close = () => {
visible.value = false
}
const submitForm = () => {
visible.value = false
}
const newInvoiceNumber = ref('')
const skip = () => {
newInvoiceNumber.value = '1000000000030002'
}
// onBeforeMount(() => {
// })
onMounted(() => {})
defineExpose({})
</script>
<style lang="scss" scoped>
.rinvoiceSkipContainer {
height: 142px;
justify-content: center;
.title {
text-align: right;
width: 100px;
}
}
</style>

View File

@@ -0,0 +1,128 @@
<!--
* @Author: hezhibo@bjgoodwill.com
* @Date: 2025-02-19 11:23:31
* @Description:
-->
<template>
<el-drawer
ref="elDrawerComRef"
title="患者列表"
:style="{
maxWidth: '477px',
minWidth: '477px',
}"
v-model="showDrawer"
:showFoot="false"
:showFootLine="false"
body-class="patientList-container"
@after-enter="initData"
>
<div class="operate">
<el-space class="operate-line" direction="vertical" alignment="flex-start">
<el-space class="">
<span>病区</span>
<div>
</div>
<el-checkbox v-model="searchForm.rcptPayFlag" label="未缴费" />
</el-space>
<el-space class="operate-line">
<span>患者</span>
<el-input v-model="searchForm.inpatientCode" style="width: 168px" placeholder="住院号" />
<el-input v-model="searchForm.patName" style="width: 139px" placeholder="姓名" />
<el-button style="margin-right: 0px; margin-left: 8px" @click="search">查找</el-button>
</el-space>
</el-space>
</div>
<div class="table-container">
<el-table
:data="patientListData"
height="100%"
show-overflow-tooltip
:style="{ height: '100%' }"
>
<el-table-column prop="deptNurseName" label="病区" width="127" show-overflow-tooltip />
<el-table-column prop="bedName" label="床号" width="77" />
<el-table-column prop="name" label="姓名" width="78" show-overflow-tooltip />
<el-table-column
prop="status"
label="状态"
min-width="108"
show-overflow-tooltip
:formatter="statusFormatter"
>
</el-table-column>
<el-table-column prop="type" label="操作" width="55">
<template #default="{ row }">
<el-button link type="warning" style="margin-right: 0px" @click="settle(row)"
>结算</el-button
>
<el-button link type="warning" style="margin-right: 0px" @click="pay(row)"
>缴费</el-button
>
</template>
</el-table-column>
</el-table>
</div>
</el-drawer>
</template>
<script setup lang="ts">
import { getCurrentInstance, onBeforeMount, onMounted, reactive, ref, h } from 'vue'
// const { proxy } = getCurrentInstance();
const emits = defineEmits(['settling', 'paying'])
const props = defineProps({})
const state = reactive({})
const showDrawer = defineModel('showDrawer', { type: Boolean, default: false })
// onBeforeMount(() => {
// })
const searchForm = reactive({
deptNurseCode: '',
rcptPayFlag: false,
inpatientCode: '',
patName: '',
})
const patientListData = ref<Array<any>>([])
const search = () => {
getPatInfoSenior(searchForm).then((res: Array<any>) => {
patientListData.value = res
})
}
const hipWorkGroupSelTabelRef = ref()
onMounted(() => {
initData()
})
const initData = () => {
// TODO 获取科室
}
const settle = (row: any) => {
emits('settling', row)
}
const pay = (row: any) => {
emits('paying', row)
}
defineExpose({ state })
</script>
<style lang="scss">
.patientList-container {
height: 100%;
display: flex;
flex-direction: column;
.operate {
flex: none;
padding-left: 12px;
}
.table-container {
padding: 8px 0;
height: 100px;
flex: auto;
}
}
</style>

View File

@@ -0,0 +1,72 @@
<!--
* @Author: hezhibo@bjgoodwill.com
* @Date: 2025-03-07 16:10:45
* @Description:
-->
<template>
<el-dialog v-model="visible" top="6vh" width="930px" title="患者列表" :z-index="20">
<el-table :data="patientList" style="width: 100%;" height="300px" show-overflow-tooltip>
<el-table-column prop="deptNurseName" label="病区" width="100">
</el-table-column>
<el-table-column prop="name" label="姓名" width="80" />
<el-table-column prop="sexName" label="性别" width="60" />
<el-table-column prop="age" label="年龄" width="80">
</el-table-column>
<el-table-column prop="inpatientCode" label="住院号" min-width="120" />
<el-table-column prop="code" label="结算状态" min-width="120" />
<el-table-column prop="code" label="支付状态" min-width="120" />
<el-table-column prop="tel" label="医疗总费用" min-width="120" />
<el-table-column fixed="right" label="操作" width="88">
<template #default="scope">
<el-button type="primary" text @click="doRegistering(scope.row)">
缴费
</el-button>
<el-button type="primary" text @click="doRegistering(scope.row)">
结算
</el-button>
<span>费用未审核</span>
<span>已完成</span>
</template>
</el-table-column>
</el-table>
<template v-slot:tool>
<el-button class="margin-left-auto" @click="cancelAct">取消
</el-button>
<el-button type="primary" @click="handleSubmit">保存</el-button>
</template>
</el-dialog>
</template>
<script setup lang='ts'>
import { getCurrentInstance, onBeforeMount, onMounted, reactive, ref, watch, watchEffect } from 'vue'
// const { proxy } = getCurrentInstance();
const emits = defineEmits(["selectOK"])
const props = defineProps<{
patientList?: Array<any>
}>();
const visible = defineModel('visible', { type: Boolean, default: false });
const newProps = reactive({ ...props });
const doRegistering = (row: any) => {
emits("selectOK", row.patMiCode);
//patMiCode 主索引
}
// onBeforeMount(() => {
// })
// onMounted(() => {
// })
/* 取消 */
const cancelAct = () => {
console.log('121231');
}
/* 保存,登记 */
const handleSubmit = () => {
console.log('121231');
}
defineExpose({})
</script>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,33 @@
<!--
* @Author: hezhibo@bjgoodwill.com
* @Date: 2025-02-19 11:23:31
* @Description:
-->
<template>
<el-drawer ref="elDrawerComRef" title="基线版医保-预结算" width="640px" v-model="showDrawer" :showFoot="false" :style="{
maxWidth: '640px', minWidth: '640px',
}" :showFootLine="false">
基线版医保-预结算
</el-drawer>
</template>
<script setup lang='ts'>
import { getCurrentInstance, onBeforeMount, onMounted, reactive } from 'vue'
// const { proxy } = getCurrentInstance();
const emits = defineEmits([])
const props = defineProps({
})
const state = reactive({
})
const showDrawer = defineModel('showDrawer', { type: Boolean, default: false });
// onBeforeMount(() => {
// })
// onMounted(() => {
// })
defineExpose({ state })
</script>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,279 @@
<!--
* @Author: hezhibo@bjgoodwill.com
* @Date: 2025-02-17 17:32:06
* @Description: 收款
-->
<template>
<el-dialog v-model="visible" width="689px" title="收款" @open="openAct" @closed="closedAct" destroy-on-close
class="receiptContainer">
<div class="operate">
<el-space :size="16">
<el-button link v-for="type in chargeTypeData" :key="type.elementCode" @click="changeType(type.elementCode)"
class="chargeType" :class="{
currentChargeType: payForm.payway == type.elementCode,
}">
<el-icon size="16" color="#666666" :icon-class="type.iconClass" style="cursor: pointer; margin-right: 4px" />
{{ type.elementName }}
</el-button>
</el-space>
</div>
<div class="collectFee">
<el-space :size="0" class="amountReceivable">
<span class="title">应收</span>
<span class="costValue">¥{{ receivable }}</span>
</el-space>
<el-space :size="8">
<span>金额</span>
<el-input v-model="payForm.amount" placeholder="">
<template #suffix>
<span></span>
</template>
</el-input>
<el-button style="margin-right: 0px" @click="collectFee">收费</el-button>
</el-space>
</div>
<div class="payData-container">
<el-table :data="payData" height="100%" show-overflow-tooltip
:style="{ 'border-right': '1px solid #eeeeee', height: '100%' }">
<el-table-column prop="paywayName" label="缴费方式" width="99" />
<el-table-column prop="amount" label="金额" width="117" align="right" header-align="left" />
<el-table-column prop="costRight" label="退款方式" min-width="124" align="right" header-align="left">
<template #default="{ row }">
<el-select v-if="row.transactionType == 'IN'" v-model="row.returnWay" placeholder="返还方式"
style="width: 100%">
<el-option label="原路返还" value="1" />
<el-option label="现金" value="2" />
</el-select>
</template>
</el-table-column>
<el-table-column prop="type" label="操作" width="113">
<template #default="{ row }">
<el-button v-if="row.transactionType == 'IN'" link type="warning" width="115"
@click="collectFeeCancel(row)">退款</el-button>
<el-button link width="115" style="margin-right: 0">打印</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="line-container"></div>
<el-space :size="40" class="confirm-container">
<div>
<span class="title">实收</span>
<span class="costReal">{{ payForm.amount }}</span>
<span class="unit"></span>
</div>
<div>
<span class="title">找零</span>
<span class="charge">
88
</span>
<span class="unit"></span>
</div>
</el-space>
<div class="confirm-container">
<el-space :size="40">
<el-space :size="12">
<span>发票类型</span>
<el-select v-model="receiptType" placeholder="发票类型" style="width: 145px">
<el-option label="纸质发票" value="1" />
</el-select>
</el-space>
<div>
<span>当前发票号</span>
<span style="color: #256d95">{{ 123213 }}</span>
<el-button style="margin-right: 0px; margin-left: 8px">跳号</el-button>
</div>
</el-space>
</div>
<template v-slot:tool>
<el-button class="margin-left-auto" @click="close">取消 </el-button>
<el-button type="primary" @click="submitForm()">确定 </el-button>
</template>
<invoiceSkip v-model:visible="invoiceSkipVisible" />
</el-dialog>
</template>
<script setup lang="ts">
import { getCurrentInstance, onActivated, onBeforeMount, onMounted, reactive, ref } from 'vue'
import { invoiceSkip } from './index'
import { ElMessage } from 'element-plus'
// const { proxy } = getCurrentInstance();
const emits = defineEmits([])
const props = defineProps<{
settleId: string
receivable: number //应收
patCode: string //主索引,
visitCode: string
}>()
const state = reactive({})
const payForm = reactive({
visitCode: '',
// econIpdSettlePayAddAsTo: {
settleId: '', //结算 id
payway: '', //支付方式
amount: 0, //金额
bankCard: '', //银行卡号
posId: '',
econPosBusinessAddto: {
patCode: '',
posAmount: 0,
},
// }
})
const visible = defineModel('visible', { type: Boolean, default: false })
const openAct = () => {
//字典等基础数据
payForm.settleId = props.settleId
payForm.econPosBusinessAddto.patCode = props.patCode
// TODO
payForm.amount = props.receivable
payForm.econPosBusinessAddto.posAmount = props.receivable
getPayData()
}
// /* 收费方式 */
const chargeTypeData = ref<Array<any>>([
])
const changeType = (elementCode: string) => {
payForm.payway = elementCode
}
/* 支付信息 */
const payData = ref([])
const getPayData = () => {
if (props.settleId) {
}
}
/* 收费 */
const collectFee = () => {
payForm.econPosBusinessAddto.posAmount = payForm.amount
payForm.visitCode = props.visitCode
}
/* 退费 */
const closedAct = () => {
visible.value = false
}
//
// onBeforeMount(() => {
// })
// onMounted(() => {
// getPayData()
// })
onActivated(() => {
getPayData()
})
/* 发票类型 */
const receiptType = ref('1')
/* 发票跳号 */
const invoiceSkipVisible = ref(false)
// const jump = () => {
// invoiceSkipVisible.value = true
// }
const close = () => {
visible.value = false
}
const submitForm = () => {
ElMessage({
message: '打印发票!',
type: 'success',
grouping: true,
showClose: true,
})
visible.value = false
}
defineExpose({ state })
</script>
<style lang="scss" scoped>
.receiptContainer {
font-family: '思源黑体 CN';
font-weight: 400;
.operate {
padding: 8px;
margin-top: -16px;
margin: -16px 8px 0;
border-bottom: 2px solid #e9f3f9;
box-shadow: 0px 1px 1px 0px rgba(181.05, 210.63, 255, 0.25);
.currentChargeType {
background: rgba(19, 192, 179, 0.1);
height: 32px;
}
.chargeType {
padding: 0 8px;
}
}
.collectFee {
height: 60px;
display: flex;
padding: 0 8px 0 22px;
align-items: center;
justify-content: space-between;
.amountReceivable {
.title {
color: #666666;
font-family: '思源黑体 CN';
}
.costValue {
font-size: 24px;
font-family: '思源黑体 CN';
font-weight: 400;
color: #ff8616;
}
}
}
.payData-container {
height: 228px;
}
.line-container {
margin: 8px -16px 4px;
border: 1px solid #e9f3f9;
width: calc(100% + 30px);
box-shadow: 0px 1px 1px 0px rgba(181.05, 210.63, 255, 0.25);
}
.confirm-container {
padding-left: 22px;
height: 30px;
margin-top: 8px;
.title {
color: #666666;
}
.charge {
font-size: 20px;
margin-right: 8px;
color: #e95657;
}
.costReal {
font-size: 20px;
font-weight: 400;
color: #333333;
margin-right: 10px;
}
.unit {
color: #bbbbbb;
}
}
.costValue {
color: #ff8616 !important;
}
}
</style>

View File

@@ -0,0 +1,220 @@
<!--
* @Author: hezhibo@bjgoodwill.com
* @Date: 2025-02-17 17:32:06
* @Description: 收款
-->
<template>
<el-dialog v-model="visible" width="870px" title="返款" @open="openAct" @closed="closedAct" destroy-on-close
class="refundContainer">
<div class="operate">
<el-space :size="8">
<span class="title">应返</span>
<span class="charge">¥{{ Math.abs(refund) }}</span>
<!-- -->
</el-space>
<el-space :size="16">
<div>
<span class="title">预缴金合计</span>
<span class="castvalue">{{ refundCalculation.prepayAmountAll }}</span>
</div>
<div>
<span class="title">余额</span>
<span class="castvalue castvalueWeight">{{ refundCalculation.prepayAmount }}</span>
</div>
<div>
<span class="title">返还方式</span>
<el-select class="refundType" v-model="paywaytype" placeholder="返还方式" @change="paywaytypeChange">
<el-option label="原路返还" value="1" />
<el-option label="现金" value="2" />
</el-select>
</div>
</el-space>
</div>
<div class="table-container">
<el-table :data="refundData" height="100%" show-overflow-tooltip :style="{ height: '100%' }"
v-loading="prePayDataloading" @selection-change="selectionChange">
<el-table-column prop="checkStatus" type="selection" width="38" header-row-class-name="removeAllSelect"
:selectable="selectablejisuna">
</el-table-column>
/>
<el-table-column prop=" paywayName" label="支付方式" width="160" />
<el-table-column prop="amount" label="总金额" width="98" align="right" header-align="left" />
<el-table-column prop="remainingAmount" label="可返金额" width="98" align="right" header-align="left" :formatter="(row: any) => {
return row.remainingAmount && row.remainingAmount == 0
? h('div', { style: { color: '#E95657' } }, row.remainingAmount)
: row.remainingAmount
}
" />
<el-table-column prop="returnAmount" label="返还金额" width="98" align="right" header-align="left" :formatter="(row: any) => {
return row.remainingAmount && row.remainingAmount == 0
? h('div', { style: { color: '#E95657' } }, row.returnAmount)
: row.returnAmount
}
" />
<el-table-column prop="createdDate" label="缴费日期" width="104" />
<el-table-column prop="payway" label="状态" min-width="70" :formatter="(row: any) => {
return row.remainingAmount && row.remainingAmount == 0 ? '已返换' : ''
}
">
</el-table-column>
<el-table-column prop="" label="返还方式" width="168">
<template #default="{ row }">
<el-select v-if="row.checkStatus" v-model="row.returnWay" placeholder="返还方式" style="width: 100%">
<el-option label="原路返还" value="1" />
<el-option label="现金" value="2" />
</el-select>
</template>
</el-table-column>
</el-table>
</div>
<div class="line-container">
返还时请勾选需要退的预交金退款顺序为由上到下依次选中的退款
</div>
<template v-slot:tool>
<el-button class="margin-left-auto" @click="close">取消 </el-button>
<el-button type="primary" @click="submitForm()">确定 </el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { getCurrentInstance, onBeforeMount, onMounted, reactive, ref, h } from 'vue'
// const { proxy } = getCurrentInstance();
const emits = defineEmits([])
const props = defineProps<{
settleId: string
refund: number //应返
visitCode: string //预交金
patCode: string //主索引
}>()
const state = reactive({})
const visible = defineModel('visible', { type: Boolean, default: false })
const openAct = () => {
sumRefund.value = 0
sumRefundold.value = 0
//字典等基础数据
getPrePayData()
}
const currentChargeType = ref('现金')
const changeType = (name: string) => {
currentChargeType.value = name
}
const paywaytype = ref('1')
const paywaytypeChange = (value: any) => {
refundData.value.forEach((elementAll: any) => {
elementAll.returnWay = value
})
switch (value) {
case '1':
break
default:
break
}
}
const receive = ref('')
const refundData = ref([])
const selectablejisuna = (row: any) => {
return sumRefund.value < Math.abs(props.refund) || row.checkStatus
}
const refundCalculation = reactive({
prepayAmount: 0,
prepayAmountAll: 0,
})
const prePayDataloading = ref(false)
const getPrePayData = () => { }
const sumRefundold = ref(0)
const sumRefund = ref(0)
const selectionChange = (newSelection: any[]) => { }
const collectFee = () => {
console.log('收费')
}
const closedAct = () => {
visible.value = false
}
//
// onBeforeMount(() => {
// })
// onMounted(() => {
// })
/* 发票类型 */
const receiptType = ref('1')
const jump = () => {
console.log('跳号')
}
const close = () => {
visible.value = false
}
const submitFormloading = ref(false)
/* 返还 */
const submitForm = () => { }
defineExpose({ state })
</script>
<style lang="scss" scoped>
.refundContainer {
font-weight: 400;
font-family: '思源黑体 CN';
.operate {
display: flex;
justify-content: space-between;
height: 72px;
margin: -16px 8px 0;
.title {
color: #666;
font-size: 14px;
}
.castvalue {
font-size: 20px;
}
.castvalueWeight {
font-weight: 500;
}
.charge {
margin-right: 8px;
color: #e95657;
font-size: 24px;
}
.refundType {
width: 145px;
margin-left: 8px;
}
}
.table-container {
height: 310px;
:deep(.el-table__row) {
height: 40px !important;
}
:deep(.el-table__header-wrapper .el-checkbox) {
visibility: hidden;
}
}
.line-container {
width: 100%;
color: #999;
font-weight: 400;
font-size: 14px;
font-family: '思源黑体 CN';
text-align: center;
}
}
</style>

View File

@@ -0,0 +1,742 @@
<!--
* @Author: hezhibo@bjgoodwill.com
* @Date: 2025-02-10 14:21:15
* @Description: 住院结算
-->
<template>
<div class="hospitalizationSettlement-container">
<div class="operate-container">
<el-space>
<el-input v-model="queryForm.searchValue" style="width: 304px" placeholder="请输入" class="searchValue"
@keyup.enter="queryPatient" clearable>
<template #prepend>
<el-select v-model="queryForm.searchType" placeholder="" style="width: 115px">
<el-option label="住院号" value="inpatientCode" />
<el-option label="主索引" value="patCode" />
</el-select>
</template>
</el-input>
<el-button style="margin-right: 0" @click="queryPatient">查询</el-button>
</el-space>
<el-space>
<span>
<span>当前发票号: </span>
<span style="color: #256d95">{{ 12312312312 }} </span>
</span>
<el-button style="margin-right: 0">跳号</el-button>
<el-button style="margin-right: 0" @click="goSettle"> 结算</el-button>
<el-button style="margin-right: 0" type="warning" @click="goSettleCancel">取消结算</el-button>
<el-button style="margin-right: 0" @click="receiptVisible = true" v-if="receivable >= 0">补缴</el-button>
<el-button style="margin-right: 0" @click="goRefund" v-if="receivable < 0">返费</el-button>
<el-icon @click="hipPatientList">
<UserFilled />
</el-icon>
</el-space>
</div>
<!-- // TODO 患者信息 -->
<div>患者信息</div>
<div class="settle-container">
<div class="settle-operate-container">
<el-space class="costcollect" :size="16">
<span class="type"> {{ currentPatient?.feeType }}</span>
<span style="color: rgba(107.06, 150.91, 172.83, 30%)">|</span>
<span>费用总额:
<span class="costValue">{{ econDetailsInfo.settleAmount }}</span>
</span>
<!-- <span>账户支付: <span class="costValue">0.00</span>
</span> -->
<span>自付:
<span class="costValue">{{ econDetailsInfo.settleAmount }}</span>
</span>
<!-- <span>报销: <span class="costValue">0.00</span></span> -->
</el-space>
<el-space>
</el-space>
<div class="patientState">
<!-- // 患者 结算、支付状态 -->
</div>
</div>
<el-row :gutter="16" class="settle-table-container">
<el-col :span="12" style="height: 100%">
<el-table :data="itemSettlementData" height="100%" show-overflow-tooltip
:style="{ 'border-right': '1px solid #eeeeee', height: '100%' }">
<el-table-column prop="nameLeft" label="项目" min-width="100" />
<el-table-column prop="costLeft" label="金额" width="121" align="right" header-align="left" />
<el-table-column class-name="nameRight" prop="nameRight" label="项目" min-width="100" />
<el-table-column prop="costRight" label="金额" width="121" align="right" header-align="left" />
<template v-slot:empty>
<div>
<el-icon icon-class="hipNull" height="160px" width="160px" />
<div class="empty-text-sty">暂无数据</div>
</div>
</template>
</el-table>
</el-col>
<el-col :span="12" style="height: 100%">
<el-table :data="reimbursementMethodData" style="width: 100%" height="100%" show-overflow-tooltip>
<el-table-column prop="nameLeft" label="报销方式" min-width="100" />
<el-table-column prop="costLeft" label="金额" width="123" align="right" header-align="left" />
<el-table-column class-name="nameRight" prop="nameRight" label="报销方式" min-width="100" />
<el-table-column prop="costRight" label="金额" width="123" align="right" header-align="left" />
<template v-slot:empty>
<div>
<el-icon icon-class="hipNull" height="160px" width="160px" />
<div class="empty-text-sty">暂无数据</div>
</div>
</template>
</el-table>
</el-col>
</el-row>
</div>
<div class="accounts-container">
<div class="receivable">
<div class="receivable-operate">
<el-space class="">
<span>
<span class="receivableName">{{ `${receivable >= 0 ? '应收' : '应返'}` }}: </span>
<span class="receivableValue" :class="`${receivable >= 0 ? 'costValue' : 'receivableValueReturn'}`">
{{ Math.abs(receivable) }}
</span>
</span>
</el-space>
<el-space class="">
<el-button style="margin-right: 0" @click="derateVisible = true">添加减免</el-button>
</el-space>
</div>
<div class="eceivableDetails">
<div>
<span>总额</span>
<span> {{ econDetailsInfo.settleAmount }}</span>
</div>
<div>
<span>报销</span>
<span>0.00</span>
</div>
<div>
<span>医保账户</span>
<span>0.00</span>
</div>
<div>
<span>预缴金</span>
<span>{{ currentPatient?.prepayAmount }}</span>
</div>
<div>
<span>减免</span>
<span>{{ currentPatient?.deduAmount }}</span>
</div>
</div>
</div>
<div class="advanced">
<div class="advanced-operate">
<el-space class="advancedTotal" :size="16">
<span>预缴金合计金额:
<span class="costValue">{{ currentPatient?.prepayAmountAll }}</span></span>
<span>余额: <span class="costValue">{{ currentPatient?.prepayAmount }}</span></span>
</el-space>
<el-space class="" :size="20">
<el-icon size="20" color="#999999" icon-class="hipRefresh" style="cursor: pointer" @click="getPrePayData" />
<el-button style="margin-right: 0">预缴金管理</el-button>
</el-space>
</div>
<div class="advancedData-container">
<el-table :data="prePayData" v-loading="prePayDataloading" style="width: 100%" height="100%"
show-overflow-tooltip>
<el-table-column prop="paywayName" label="支付方式" width="147" />
<el-table-column prop="amount" label="金额" align="right" header-align="left" width="93" />
<el-table-column prop="remainingAmount" label="可用金额" width="94" align="right" header-align="left" />
<el-table-column prop="remark" label="备注" min-width="100" />
<el-table-column prop="createdDate" label="充值时间" width="143" />
<template v-slot:empty>
<div>
<el-icon icon-class="hipNull" height="160px" width="160px" />
<div class="empty-text-sty">暂无数据</div>
</div>
</template>
</el-table>
</div>
</div>
</div>
<receipt v-model:visible="receiptVisible" :settleId="econDetailsInfo.settleId" :receivable="receivable"
:visitCode="currentPatient?.visitCode || ''" :patCode="currentPatient?.patCode || ''" />
<refund v-model:visible="refundVisible" :refund="receivable" :settleId="econDetailsInfo.settleId"
:visitCode="currentPatient?.visitCode || ''" :patCode="currentPatient?.patCode || ''" />
<patientList v-model:showDrawer="patientListDrawer" @settling="settling" @paying="paying" />
<preSettlement v-model:showDrawer="preSettlementDrawer" chargeTypeCode="01" />
<!--preSettlement isEdit 提交状态 -->
<invoiceSkip v-model:visible="invoiceSkipVisible" />
<derate v-model:visible="derateVisible" @derateOk="derateOk" />
<patientListDialog v-model:visible="patientListDialogVisible" :patientList="queryPpatientList" />
</div>
</template>
<script setup>
import {
computed,
getCurrentInstance,
onBeforeMount,
onMounted,
reactive,
ref,
watchEffect,
} from 'vue'
import {
receipt,
refund,
patientList,
invoiceSkip,
derate,
patientListDialog,
preSettlement,
} from './components/index'
import { ElMessage } from 'element-plus'
const { proxy } = getCurrentInstance()
const emits = defineEmits([])
const props = defineProps({})
const state = reactive({})
/* 查询患者 */
const queryForm = reactive({
searchValue: '',
ward: '',
inPatientId: '',
searchType: 'inpatientCode',
})
const queryPpatientList = ref([]) //查询到的患者列表
const currentPatient = ref() // 当前
const queryPatient = () => {
// 查询患者接口
//1. 根据输入精确匹配,根据主索引查找患者时,如果有多条住院记录,弹出患者选择控件
getPatInfo({
inpatientCode: queryForm.searchType == 'inpatientCode' ? queryForm.searchValue : undefined,
patCode: queryForm.searchType == 'patCode' ? queryForm.searchValue : undefined,
})
.then((res) => {
if (res && res.length == 1) {
currentPatient.value = res[0]
try {
if (currentPatient.value) {
getEconDetails()
getPrePayData()
patientsBarRef.value.fetchPatientInfoById(currentPatient.value.visitCode)
}
} catch (error) {
console.log(error)
}
} else if (res && res.length > 1) {
console.log(res)
queryPpatientList.value = res
patientListDialogVisible.value = true
} else {
ElMessage({
message: '未查询到患者!',
type: 'info',
grouping: true,
showClose: true,
})
queryPpatientList.value = []
currentPatient.value = {}
}
})
.catch((error) => {
console.log(error)
})
}
/* 患者费用信息 */
const econDetailsInfo = ref({
groupSystemClassTo: {
billAllToListL: [],
sumCosts: 0,
systemClassCostMap: {},
},
settleId: '',
settleAmount: 0, //费用总额
})
const getEconDetails = () => {
if (currentPatient.value) {
getPatEconSettleInfo(currentPatient.value).then((res) => {
econDetailsInfo.value = res
})
}
}
watchEffect(() => {
try {
if (currentPatient.value && currentPatient.value?.feeType && currentPatient.value?.visitCode) {
// 计算返回支付金额
amountCalculation({
// settleAmount: econDetailsInfo.value.settleAmount,
// miReimburse: 0,
// acctPay: 0,
// psnCashPay: 0,// econDetailsInfo.value.settleAmount,
// prepayAmount: currentPatient.value?.prepayAmountAll || 0,
// deduAmount: currentPatient.value?.deduAmount || 0,
// 增加流水号 费别
feeType: currentPatient.value?.feeType,
visitCode: currentPatient.value?.visitCode,
rcptFlag: currentPatient.value?.rcptFlag,
}).then((res) => {
console.log(res)
receivable.value = res.amount
// res.flag
})
}
} catch (error) {
console.log(error)
}
})
// const calculation = () => {
// }
/*预交金信息 */
const prePayData = ref([])
const prePayDataloading = ref(false)
const getPrePayData = () => {
if (currentPatient.value && currentPatient.value?.visitCode) {
prePayDataloading.value = true
getPrePayInfo(currentPatient.value?.visitCode)
.then((res) => {
prePayData.value = res.prepayList
; (currentPatient.value).prepayAmount = res.remainingAmountSum // 余额汇总
; (currentPatient.value).prepayAmountAll = res.amountSum //金额汇总
prePayDataloading.value = false
})
.finally(() => {
prePayDataloading.value = false
})
}
}
const patientsBarRef = ref()
const hipPatientList = () => {
patientListDrawer.value = true
}
/* 去结算 */
const settling = (row) => {
queryForm.searchType = 'inpatientCode'
queryForm.searchValue = row.inpatientCode
queryPatient()
patientListDrawer.value = false
}
/* 去缴费 */
const paying = (row) => {
queryForm.searchType = 'inpatientCode'
queryForm.searchValue = row.inpatientCode
// TODO 去缴费的逻辑?
queryPatient()
patientListDrawer.value = false
}
const childDatas = ref([
{
name: '迪丽热巴之子1',
type: '自费',
cost: '1500',
},
{
name: '迪丽热巴之子2',
type: '自费',
cost: '1500',
},
{
name: '迪丽热巴之子2',
type: '自费',
cost: '1500',
},
{
name: '迪丽热巴之子2',
type: '自费',
cost: '1500',
},
{
name: '迪丽热巴之子2',
type: '自费',
cost: '1500',
},
])
/*费用 */
const treatHospitalizedData = ref([])
const systemClassCostMap = computed(() => {
const classCost = econDetailsInfo.value?.groupSystemClassTo?.systemClassCostMap
return classCost
? Object.keys(classCost).map((key) => {
return { name: key, cost: classCost[key] }
})
: []
})
/* 项目数据 */
const itemSettlementData = computed(() => {
const exchangeData = []
if (systemClassCostMap.value.length > 7) {
let limitcenter = Math.ceil(systemClassCostMap.value.length / 2)
limitcenter = limitcenter > 7 ? limitcenter : 7
for (let index = 0; index < limitcenter; index++) {
exchangeData.push({
nameLeft: systemClassCostMap.value[index].name,
costLeft: systemClassCostMap.value[index].cost,
nameRight: systemClassCostMap.value[index + limitcenter]?.name,
costRight: systemClassCostMap.value[index + limitcenter]?.cost,
})
}
} else {
systemClassCostMap.value.forEach((element) => {
exchangeData.push({
nameLeft: element.name,
costLeft: element.cost,
})
})
}
return exchangeData
})
const reimbursementMethod = ref([
// { name: '基金支付总额', cost: '600' },
// { name: '医保其他支付总额', cost: '150' },
// { name: '医保账户总额', cost: '600' },
// { name: '现金总额', cost: '600' },
])
const reimbursementMethodData = computed(() => {
const exchangeData = []
// let limitcenter = Math.ceil(reimbursementMethod.value.length / 2)
// for (let index = 0; index < limitcenter; index++) {
// exchangeData.push({
// nameLeft: reimbursementMethod.value[index].name,
// costLeft: reimbursementMethod.value[index].cost,
// nameRight: reimbursementMethod.value[index + limitcenter]?.name,
// costRight: reimbursementMethod.value[index + limitcenter]?.cost,
// }
// )
// }
return exchangeData
})
// onBeforeMount(() => {
// })
// onMounted(() => {
// })
/* 先结算后 收款 */
const receiptVisible = ref(false)
const goSettle = () => {
// receiptVisible.value = true
ElMessage({
message: '结算成功!',
type: 'success',
grouping: true,
showClose: true,
})
}
/* 结算取消 */
const goSettleCancel = () => {
ElMessage({
message: '结算取消成功!',
type: 'success',
grouping: true,
showClose: true,
})
}
const receivable = ref(0)
//应收
const amount = computed(() => {
return econDetailsInfo.value.settleAmount - (currentPatient.value?.deduAmount || 0)
})
const refundVisible = ref(false) // 返款
const goRefund = () => {
// receiptVisible.value = true
refundVisible.value = true
}
/* 患者列表 ,抽屉*/
const patientListDrawer = ref(false)
/* 患者列表,弹窗 */
const patientListDialogVisible = ref(false)
/* 医保 */
const preSettlementDrawer = ref(false)
/* 医保详情 */
/* 减免 */
const derateVisible = ref(false)
const derateOk = (amount) => {
console.log(amount)
derateVisible.value = false
if (currentPatient.value) {
currentPatient.value.deduAmount = amount
}
}
/* 取消医保出院 */
const cancelDischarge = async () => {
await proxy.$hipMessageBox({
title: '提示',
type: 'warn',
content: '是否取消患者的医保出院登记?',
onConfirm: () => {
console.log('点击知道了')
},
onCancel: () => {
console.log('点击关闭')
},
})
}
/* 发票跳号 */
const invoiceSkipVisible = ref(false)
defineExpose({ state })
</script>
<style lang="scss" scoped>
.hospitalizationSettlement-container {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
font-weight: 400;
font-family: '思源黑体 CN';
// border: 1px solid blue;
background-color: #f1faff;
>div {
flex: none;
}
.operate-container {
display: flex;
align-items: center;
justify-content: space-between;
height: 56px;
padding: 0 16px;
background-color: #fff;
border-bottom: 2px solid #e9f3f9;
:deep(.el-input) {
.el-input-group__prepend {
div.el-select {
.el-select__wrapper {
background-color: #fff !important;
}
}
}
}
}
.settle-container {
// border: 1px solid #DDDDDD;
// border-radius: 8px;
width: 100%;
height: 323px;
margin-bottom: 8px;
background-color: #fff;
// padding: 0 16px;
// border: 1px solid greenyellow;
.settle-operate-container {
position: relative;
display: flex;
flex: none;
align-items: center;
justify-content: space-between;
width: 100%;
width: calc(100% - 32px);
height: 56px;
// border: 1px solid black;
padding: 0 16px;
/* 患者状态 */
.patientState {
position: absolute;
top: -56px;
right: 16px;
}
}
:deep(.settle-table-container) {
flex: auto;
width: calc(100% - 32px);
width: 100%;
height: calc(100% - 56px);
// border: 1px solid red;
margin-left: 0 !important;
padding: 0 8px 14px;
.table-child {
height: 100%;
// border: 1px solid red;
}
.nameRight {
border-left: 1px solid !important;
}
th.nameRight {
.cell {
&::before {
border: 0 !important;
}
}
}
}
.costcollect {
.type {
color: #333;
}
:nth-child(2) {
margin-left: 26px;
}
span {
color: #666;
}
}
}
.accounts-container {
display: flex;
flex: auto;
// margin: 0 8px;
width: 100%;
height: 321px;
// border: 1px solid black;
// background: #FFFFFF;
background-color: #f1faff;
.receivable {
flex: none;
width: 426px;
padding: 0 16px;
background-color: #fff;
// border: 1px solid #DDDDDD;
.receivable-operate {
display: flex;
justify-content: space-between;
height: 56px;
border-bottom: 2px solid #e9f3f9;
.receivableName {
color: #666;
font-size: 20px;
}
.receivableValue {
font-size: 32px;
}
.receivableValueReturn {
color: #e95657;
font-size: 32px;
}
}
.eceivableDetails {
padding-top: 29px;
>div {
height: 40px;
margin: 0 20px;
font-size: 22px;
line-height: 40px;
border-bottom: 2px solid #eee;
span:first-child {
display: inline-block;
width: 126px;
color: #666;
font-weight: 400;
text-align: right;
}
span:nth-child(2) {
display: inline-block;
width: 80px;
color: #333;
font-weight: 400;
text-align: right;
}
// span:nth-child(2) {
// color: #333333;
// }
span {
&:nth-child(2) {
min-width: 120px;
color: #333;
text-align: right;
// border: 1px solid red
}
}
}
}
}
.advanced {
flex: auto;
width: 100px;
margin-left: 8px;
background-color: #fff;
.advanced-operate {
display: flex;
justify-content: space-between;
height: 56px;
padding: 0 16px;
.advancedTotal {
color: #666;
}
}
.advancedData-container {
height: calc(100% - 64px);
padding: 0 16px 8px;
}
}
.childs {
flex: none;
width: 188px;
// border: 1px solid rgba(237, 241, 5, 0.894);
margin-left: 8px;
padding: 8px;
background: #fff;
.child {
width: 170px;
padding: 8px;
color: #666;
background: #fff;
border: 1px solid #ddd;
border-radius: 4px;
box-shadow: 0 2px 2px 0 rgba(57.55, 69.04, 86.28, 15%);
.name {
color: #333;
font-weight: 500;
font-size: 16px;
}
.typeValue {
color: #333;
}
}
}
}
.costValue {
color: #ff8616 !important;
}
}
</style>

View File

@@ -0,0 +1,21 @@
/*
* @Author: hezhibo@bjgoodwill.com
* @Date: 2025-03-07 16:57:42
* @Description:
*/
// import receipt from './receipt.vue';
// import refund from './refund.vue';
import patientList from './patientList.vue'
// import invoiceSkip from './invoiceSkip.vue';
// import derate from './derate.vue';
import selectSettlement from './selectSettlement.vue'
// import patientListDialog from './patientListDialog.vue';
export {
// receipt, refund,
patientList,
selectSettlement,
// invoiceSkip,
// derate,
// patientListDialog,
}

View File

@@ -0,0 +1,134 @@
<!--
* @Author: hezhibo@bjgoodwill.com
* @Date: 2025-02-19 11:23:31
* @Description:
-->
<template>
<el-drawer ref="elDrawerComRef" title="患者列表" :style="{
maxWidth: '477px',
minWidth: '477px',
}" v-model="showDrawer" :showFoot="false" :showFootLine="false" body-class="patientList-container"
@after-enter="initData">
<div class="operate">
<el-space class="operate-line" direction="vertical" alignment="flex-start">
<el-space class="">
<span>病区</span>
<div>
<el-select v-model="searchForm.deptNurseCode" style="width: 168px" placeholder="请选择信息">
</el-select>
</div>
<el-checkbox v-model="searchForm.rcptPayFlag" label="未缴费" />
</el-space>
<el-space class="operate-line">
<span>患者</span>
<el-input v-model="searchForm.inpatientCode" style="width: 168px" placeholder="住院号" />
<el-input v-model="searchForm.patName" style="width: 139px" placeholder="姓名" />
<el-button style="margin-right: 0px; margin-left: 8px" @click="search">查找</el-button>
</el-space>
</el-space>
</div>
<div class="table-container">
<el-table :data="patientListData" height="100%" show-overflow-tooltip :style="{ height: '100%' }">
<el-table-column prop="deptNurseName" label="病区" width="127" show-overflow-tooltip />
<el-table-column prop="bedName" label="床号" width="77" />
<el-table-column prop="name" label="姓名" width="78" show-overflow-tooltip />
<el-table-column prop="status" label="状态" min-width="108" show-overflow-tooltip :formatter="statusFormatter">
</el-table-column>
<el-table-column prop="type" label="操作" width="55">
<template #default="{ row }">
<el-button link type="warning" style="margin-right: 0px" @click="settle(row)">结算</el-button>
<el-button link type="warning" style="margin-right: 0px" @click="pay(row)">缴费</el-button>
</template>
</el-table-column>
</el-table>
</div>
</el-drawer>
</template>
<script setup >
import {
getCurrentInstance,
onBeforeMount,
onMounted,
reactive,
ref,
h,
} from 'vue';
// const { proxy } = getCurrentInstance();
const emits = defineEmits(['settling', 'paying']);
const props = defineProps({});
const state = reactive({});
// const showDrawer = defineModel('showDrawer', { type: Boolean, default: false });
// onBeforeMount(() => {
// })
const searchForm = reactive({
deptNurseCode: '',
rcptPayFlag: false,
inpatientCode: '',
patName: '',
});
// const patientListData = ref<Array<any>>([]);
const search = () => {
};
const hipWorkGroupSelTabelRef = ref();
onMounted(() => {
initData();
});
const initData = () => {
};
// const statusFormatter = (row: any) => {
// switch (row.status) {
// case '2':
// return h(
// 'div',
// {
// style: { color: '#5585E3' },
// },
// '待结算'
// );
// case '3':
// return h(
// 'div',
// {
// style: { color: '#945D3D' },
// },
// '待缴费'
// );
// case '4':
// return h('div', {}, '已支付');
// default:
// break;
// }
// };
// const settle = (row: any) => {
// emits('settling', row);
// };
// const pay = (row: any) => {
// emits('paying', row);
// };
defineExpose({ state });
</script>
<style lang="scss">
.patientList-container {
height: 100%;
display: flex;
flex-direction: column;
.operate {
flex: none;
padding-left: 12px;
}
.table-container {
padding: 8px 0;
height: 100px;
flex: auto;
}
}
</style>

View File

@@ -0,0 +1,88 @@
<template>
<el-drawer ref="elDrawerComRef" title="选择中途结算费用" :style="{
maxWidth: '580px',
minWidth: '580px',
}" v-model="showDrawer" :showFoot="false" :showFootLine="false" body-class="selectSettlement-container"
@open="initData">
<el-space class="operate-line" alignment="center" :size="16">
<div>收费时间</div>
<el-date-picker v-model="searchDateRange" type="daterange" range-separator="至" start-placeholder="开始时间"
end-placeholder="结束时间" value-format="YYYY-MM-DD" />
<el-button style="margin-right: 0px" @click="search">查找</el-button>
</el-space>
<div class="table-container">
<el-table :data="selectSettlementData" style="width: 100%" height="100%" align="center" show-overflow-tooltip
ref="selectSettlementDataRef">
<el-table-column type="selection" width="38" fixed />
<el-table-column prop="costsSum" label="实收总金额" width="100" align="center" />
<el-table-column class-name="nameRight" prop="amountSum" label="应付总金额" width="100" align="center" />
<el-table-column class-name="nameRight" prop="settleAmountSum" label="已结算金额" width="100" align="center" />
<el-table-column prop="unSettleAmountSum" label="未结算金额" width="100" align="center" />
</el-table>
</div>
>
<template #tool>
<el-button type="primary" style="margin: 8px" @click="selectOk">确定</el-button>
</template>
</el-drawer>
</template>
<script setup >
import {
getCurrentInstance,
onBeforeMount,
onMounted,
reactive,
ref,
} from 'vue';
// const { proxy } = getCurrentInstance();
import dayjs from 'dayjs';
const emits = defineEmits(['selectOk']);
const showDrawer = defineModel('showDrawer', { type: Boolean, default: false });
// const props = defineProps<{
// visitCode: string;
// }>();
const state = reactive({});
// onBeforeMount(() => {
// })
// onMounted(() => {
// })
const searchDateRange = ref([
dayjs(new Date()).format('YYYY-MM-DD'),
dayjs(new Date()).format('YYYY-MM-DD'),
]);
const search = () => {
if (searchDateRange.value) {
}
};
// const selectSettlementData = ref<Array<any>>([]);
const selectSettlementDataRef = ref();
const initData = () => {
search();
};
const selectOk = () => {
emits('selectOk', selectSettlementDataRef.value.getSelectionRows());
};
defineExpose({ state });
</script>
<style lang="scss" scoped>
.selectSettlement-container {
height: 100%;
display: flex;
flex-direction: column;
.operate-line {
padding-bottom: 16px;
flex: none;
}
.table-container {
width: 100%;
height: calc(100% - 50px);
padding-bottom: 16px;
flex: auto;
}
}
</style>

View File

@@ -0,0 +1,722 @@
<!--
* @Author: hezhibo@bjgoodwill.com
* @Date: 2025-03-10 17:21:55
* @Description:
-->
<template>
<div class="hospitalizationSettlement-container">
<div class="operate-container">
<el-space>
<el-input v-model="queryForm.searchValue" style="width: 304px" placeholder="请输入" class="searchValue"
@keyup.enter="queryPatient" clearable>
<template #prepend>
<el-select v-model="queryForm.searchType" placeholder="" style="width: 115px">
<el-option label="住院号" value="inpatientCode" />
<el-option label="主索引" value="patCode" />
</el-select>
</template>
</el-input>
<el-button style="margin-right: 0" @click="queryPatient">查询</el-button>
<!-- 读卡 -->
</el-space>
<el-space>
<span>
<span>当前发票号: </span>
<span style="color: #256d95">{{ 1231231231 }} </span>
</span>
<el-button style="margin-right: 0">跳号</el-button>
<el-button style="margin-right: 0" @click="goSettle">结算</el-button>
<el-button style="margin-right: 0" type="warning" @click="goSettleCancel">取消结算</el-button>
<el-button style="margin-right: 0" @click="receiptVisible = true">补缴</el-button>
<el-icon size="20" color="#999999" icon-class="hipPatientList" style="cursor: pointer"
@click="hipPatientList" />
</el-space>
</div>
<!-- // TODO 患者信息 -->
<div>患者信息</div>
<div class="settle-container">
<div class="settle-operate-container">
<el-space class="costcollect" :size="16">
<span class="type">基线版医保</span>
<span style="color: rgba(107.06, 150.91, 172.83, 30%)">|</span>
<span>总费用:
<span class="costValue">{{ econDetailsInfo.settleAmount }}</span>
</span>
<!-- 费用总额 -->
<span>勾选未结费用:
<span class="costValue">{{ econDetailsInfo.unRcptAmount }}</span>
</span>
<span>勾选已结费用:
<span class="costValue">{{ econDetailsInfo.rcptAmount || 0 }}</span>
</span>
<span>预交余额:
<span class="costValue">{{ prePayData.remainingAmountSum }}</span>
</span>
<!-- <span
>账户支付:
<span class="costValue">{{ econDetailsInfo.settleAmount }}</span>
</span> -->
<span>自付:
<span class="costValue">{{ econDetailsInfo.psnPartAmt }}</span>
</span>
<!-- <span
>报销:
<span class="costValue">{{ econDetailsInfo.settleAmount }}</span>
</span> -->
</el-space>
<el-space>
<el-button style="margin-right: 0" :disabled="!currentPatient?.visitCode"
@click="selectSettlementDrawer = true">选择结算费用</el-button>
<!-- 1. 根据患者费别显示按钮若患者费别为自费则不显示预结算按钮若患者费别为医保则显示预结算按钮 -->
<el-button style="margin-right: 0" @click="preSettlementDrawer = true">预结算</el-button>
<!-- 1. 已预结算的患者重新进行预结算则点击重新预结算 -->
<!-- <el-button style="margin-right: 0px;" @click="preSettlementDrawer = true">重新预结算</el-button>
<el-button style="margin-right: 0px;" @click="settlementDetailsVisible = true">报销详情</el-button>
<el-button style="margin-right: 0px;" @click="cancelDischarge">取消医保出院</el-button> -->
</el-space>
<div class="patientState">
<el-icon size="52" color="#FF8616" icon-class="hipUnpaid" style="cursor: pointer" />
<el-icon size="52" color="#E95657" icon-class="hipUnsettled" style="cursor: pointer" />
</div>
</div>
<el-row :gutter="16" class="settle-table-container">
<el-col :span="12" style="height: 100%">
<el-table :data="itemSettlementData" height="100%" show-overflow-tooltip
:style="{ 'border-right': '1px solid #eeeeee', height: '100%' }">
<el-table-column prop="nameLeft" label="项目" min-width="100" />
<el-table-column prop="costLeft" label="金额" width="121" align="right" header-align="left" />
<el-table-column class-name="nameRight" prop="nameRight" label="项目" min-width="100" />
<el-table-column prop="costRight" label="金额" width="121" align="right" header-align="left" />
</el-table>
</el-col>
<el-col :span="12" style="height: 100%">
<el-table :data="reimbursementMethodData" style="width: 100%" height="100%" show-overflow-tooltip>
<el-table-column prop="nameLeft" label="报销方式" min-width="100" />
<el-table-column prop="costLeft" label="金额" width="123" align="right" header-align="left" />
<el-table-column class-name="nameRight" prop="nameRight" label="报销方式" min-width="100" />
<el-table-column prop="costRight" label="金额" width="123" align="right" header-align="left" />
</el-table>
</el-col>
</el-row>
</div>
<div class="accounts-container">
<div class="receivable">
<div class="receivable-operate">
<el-space class="">
<span>
<span class="receivableName">应收: </span>
<span class="receivableValue costValue">{{
Math.abs(econDetailsInfo.settleCosts)
}}</span>
</span>
</el-space>
<el-space class="">
<el-button style="margin-right: 0" @click="derateVisible = true">添加减免</el-button>
</el-space>
</div>
<div class="eceivableDetails">
<div>
<span>总额</span>
<span>{{ econDetailsInfo.settleAmount || '0.00' }}</span>
</div>
<div>
<span>报销</span>
<span>0.00</span>
</div>
<div>
<span>医保账户</span>
<span>0.00</span>
</div>
<div>
<span>预缴金</span>
<span>{{ prePayData.remainingAmountSum || '0.00' }}</span>
</div>
<div>
<span>减免</span>
<span>{{ currentPatient?.deduAmount || '0.00' }}</span>
</div>
</div>
</div>
<div class="advanced">
<div class="advanced-operate">
<el-space class="advancedTotal" :size="16">
<span>预缴金合计金额: <span class="costValue">{{ prePayData.amountSum }}</span></span>
<span>余额: <span class="costValue">{{ prePayData.remainingAmountSum }}</span></span>
<span>已使用: <span class="costValue">{{ prePayData.alreadyUsedAmount }}</span></span>
</el-space>
<el-space class="" :size="20">
<el-icon size="20" color="#999999" icon-class="hipRefresh" style="cursor: pointer" @click="getPrePayData" />
<el-button style="margin-right: 0">预缴金管理</el-button>
</el-space>
</div>
<div class="advancedData-container">
<el-table :data="prePayData.prepayList" style="width: 100%" height="100%" show-overflow-tooltip>
<el-table-column prop="paywayName" label="支付方式" width="147" />
<el-table-column prop="amount" label="金额" align="right" header-align="left" width="93" />
<el-table-column prop="remainingAmount" label="可用金额" width="94" align="right" header-align="left" />
<el-table-column prop="remark" label="备注" min-width="100" />
<el-table-column prop="createdDate" label="充值时间" width="160" :formatter="(row: any) => {
return row.createdDate && dayjs(row.createdDate).format('YYYY/MM/DD HH:mm')
}
" />
<template v-slot:empty>
<div>
<el-icon icon-class="hipNull" height="160px" width="160px" />
<div class="empty-text-sty">暂无数据</div>
</div>
</template>
</el-table>
</div>
</div>
<!-- <div class="childs" v-if="childDatas.length > 0">
<el-scrollbar>
<el-space wrap :size="8" directio="vertical">
<div class="child" v-for="child in childDatas" :key="child.name">
<el-space wrap :size="8" directio="vertical">
<div class="name">{{ child.name }}</div>
<div>医保类型<span class="typeValue">{{ child.type }}</span></div>
<div>费用合计<span class="costValue">{{ child.cost }}</span> </div>
</el-space>
</div>
</el-space>
</el-scrollbar>
</div> -->
</div>
<patientList v-model:showDrawer="patientListDrawer" @settling="settling" @paying="paying" />
<!--preSettlement isEdit 提交状态 -->
<selectSettlement v-model:showDrawer="selectSettlementDrawer" :visit-code="currentPatient?.visitCode || ''"
/>
</div>
</template>
<script setup lang="ts">
import { computed, getCurrentInstance, onBeforeMount, onMounted, reactive, ref } from 'vue'
import dayjs from 'dayjs'
import {
patientList,
selectSettlement,
} from './components/index'
import { ElMessage } from 'element-plus'
import { method } from 'lodash-es'
const { proxy } = getCurrentInstance() as any
const emits = defineEmits([])
const props = defineProps({})
const state = reactive({})
/* 查询患者 */
const queryForm = reactive({
searchValue: '',
ward: '',
inPatientId: '',
searchType: 'inpatientCode',
})
const queryPpatientList = ref<Array<any>>([]) //查询到的患者列表
const currentPatient = ref<Partial<any>>() // 当前
const queryPatient = () => {
// TODO 查询患者接口
//1. 根据输入精确匹配,根据主索引查找患者时,如果有多条住院记录,弹出患者选择控件
}
/* 当前选择的待结算信息 */
// const currentSelectSettlement = reactive<any>({
// selectSettlementData: [],
// deduAmount: 0,
// })
// const selectOk = (res: any) => {
// selectSettlementDrawer.value = false
// currentSelectSettlement.selectSettlementData = res
// getEconDetails(currentSelectSettlement.selectSettlementData)
// }
// const isHaveSettleId = () => {
// if (currentPatient.value) {
// if (currentPatient.value.settleId) {
// feeInformationSettle(currentPatient.value).then((res: any) => {
// econDetailsInfo.value = res
// })
// } else {
// selectSettlementDrawer.value = true
// }
// }
// }
/* 患者费用信息 */
const econDetailsInfo = ref({
// groupSystemClassTo: {
// billAllToListL: [],
// sumCosts: 0,
// systemClassCostMap: {},
// },
settleAmount: 0, //费用信息-已选择费用
unRcptAmount: 0, //费用信息-未结算费用
rcptAmount: 0, // 费用信息-已结算费用
acctPay: 0, // 费用信息-账户支付
psnPartAmt: 0, // 费用信息-医保自付
systemClassCostMap: {}, // 系统分类名称,实收总金额
settleCosts: 0, // 结算信息-应收金额
// settleCosts: 0, //减免金额 //TODO
//明细信息
econIpdMidwayDetailAsToList: [
// {
// feeClassName: '',
// priceItemCode: '',
// priceItemName: '',
// spec: '',
// price: '',
// num: 0,
// costs: 0,
// },
],
econIpdBillIdList: [], //住院账单标识列表,
})
// const getEconDetails = (res: any) => {
// feeInformationUnSettle(res).then((res: any) => {
// econDetailsInfo.value = res
// })
// }
/*预交金信息 */
const prePayData = reactive({
remainingAmountSum: 0,
amountSum: 0,
alreadyUsedAmount: 0,
prepayList: [],
})
const prePayDataloading = ref(false)
const getPrePayData = () => {
if (currentPatient.value && currentPatient.value?.visitCode) {
prePayDataloading.value = true
// TODO 预结算
}
}
/*费用 */
const treatHospitalizedData = ref([])
// const systemClassCostMap = computed(() => {
// const classCost: any = econDetailsInfo.value?.systemClassCostMap
// return classCost
// ? Object.keys(classCost).map((key) => {
// return { name: key, cost: classCost[key] }
// })
// : []
// })
/* 项目数据 */
const itemSettlementData = computed(() => {
const exchangeData: any[] = []
if (systemClassCostMap.value.length > 7) {
let limitcenter = Math.ceil(systemClassCostMap.value.length / 2)
limitcenter = limitcenter > 7 ? limitcenter : 7
for (let index = 0; index < limitcenter; index++) {
exchangeData.push({
nameLeft: systemClassCostMap.value[index].name,
costLeft: systemClassCostMap.value[index].cost,
nameRight: systemClassCostMap.value[index + limitcenter]?.name,
costRight: systemClassCostMap.value[index + limitcenter]?.cost,
})
}
} else {
systemClassCostMap.value.forEach((element: any) => {
exchangeData.push({
nameLeft: element.name,
costLeft: element.cost,
})
})
}
return exchangeData
})
const reimbursementMethod = ref([
// { name: '基金支付总额', cost: '600' },
// { name: '医保其他支付总额', cost: '150' },
// { name: '医保账户总额', cost: '600' },
// { name: '现金总额', cost: '600' },
])
const reimbursementMethodData = computed(() => {
const exchangeData: any[] = []
return exchangeData
})
// onBeforeMount(() => {
// })
// onMounted(() => {
// })
const patientsBarRef = ref()
const hipPatientList = () => {
patientListDrawer.value = true
}
/* 去结算 */
const settling = (row: any) => {
queryForm.searchType = 'inpatientCode'
queryForm.searchValue = row.inpatientCode
queryPatient()
patientListDrawer.value = false
}
/* 去缴费 */
const paying = (row: any) => {
queryForm.searchType = 'inpatientCode'
queryForm.searchValue = row.inpatientCode
// TODO 去缴费的逻辑?
queryPatient()
patientListDrawer.value = false
}
const goSettle = () => {
// receiptVisible.value = true
settlement({
visitCode: currentPatient.value?.visitCode, // 经济结算-住院流水号s
patIndexCode: currentPatient.value?.patCode, //经济结算-患者信息编码
feeType: currentPatient.value?.feeType, // 经济结算-费别
deduAmount: currentPatient.value?.deduAmount, //、经济结算-减免金额
deduType: currentPatient.value?.deduType, // 经济结算-减免类型
prepayAmount:
econDetailsInfo.value.settleCosts == 0
? econDetailsInfo.value.settleCosts
: prePayData.remainingAmountSum, // 经济结算-结算使用预交金金额
amount: econDetailsInfo.value.settleAmount, // 经济结算-应收费用总额
paySelfAmount: econDetailsInfo.value.psnPartAmt, //经济结算-自付金额
costs: econDetailsInfo.value.settleAmount, // 经济结算-结算费用总额
econIpdBillIdList: econDetailsInfo.value.econIpdBillIdList,
}).then((res: any) => {
console.log(res)
// econDetailsInfo.value.settleId = res.id;
ElMessage({
message: '结算成功!',
type: 'success',
grouping: true,
showClose: true,
})
queryPatient()
if (res.payFlag) {
// TODO 调用打印
}
//付完成标志res.payFlag true:调用打印
// if (currentPatient.value) {
// currentPatient.value.rcptFlag = res.rcptFlag
// currentPatient.value.rcptPayFlag = res.rcptPayFlag
// currentPatient.value.examineFlag = res.examineFlag
// }
if (econDetailsInfo.value.settleCosts < 0) {
/* 需要交费时 交钱 */
receiptVisible.value = true
}
})
}
/* 结算取消 */
const goSettleCancel = () => {
// settlementCancel({
// visitCode: currentPatient.value?.visitCode,// 经济结算-住院流水号s
// feeType: currentPatient.value?.feeType,// 经济结算-费别
// settleId: econDetailsInfo.value.settleId
// }).then((res: any) => {
// ElMessage({
// message: '结算取消成功!',
// type: 'success',
// grouping: true,
// showClose: true,
// });
// (currentPatient.value as any).rcptFlag = false;
// getEconDetails()
// //TODO 结算取消成功,处理后续
// })
}
/* 收款 */
const receiptVisible = ref(false)
const refundVisible = ref(false) // 返款
/* 患者列表 ,抽屉*/
const patientListDrawer = ref(false)
/* 患者列表,弹窗 */
const patientListDialogVisible = ref(false)
/* 医保 */
const preSettlementDrawer = ref(false)
/* 选择费用 */
const selectSettlementDrawer = ref(false)
/* 减免 */
const derateVisible = ref(false)
const derateOk = (amount: number) => {
derateVisible.value = false
if (currentPatient.value) {
currentPatient.value.deduAmount = amount
// TODO
// getEconDetails(currentSelectSettlement.selectSettlementData);
}
}
/* 取消医保出院 */
const cancelDischarge = async () => {
await proxy.$hipMessageBox({
title: '提示',
type: 'warn',
content: '是否取消患者的医保出院登记?',
onConfirm: () => {
console.log('点击知道了')
},
onCancel: () => {
console.log('点击关闭')
},
})
}
defineExpose({ state })
</script>
<style lang="scss" scoped>
.hospitalizationSettlement-container {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
font-weight: 400;
font-family: '思源黑体 CN';
// border: 1px solid blue;
background-color: #f1faff;
>div {
flex: none;
}
.operate-container {
display: flex;
align-items: center;
justify-content: space-between;
height: 56px;
padding: 0 16px;
background-color: #fff;
border-bottom: 2px solid #e9f3f9;
:deep(.el-input) {
.el-input-group__prepend {
div.el-select {
.el-select__wrapper {
background-color: #fff !important;
}
}
}
}
}
.settle-container {
// border: 1px solid #DDDDDD;
// border-radius: 8px;
width: 100%;
height: 323px;
margin-bottom: 8px;
background-color: #fff;
// padding: 0 16px;
// border: 1px solid greenyellow;
.settle-operate-container {
position: relative;
display: flex;
flex: none;
align-items: center;
justify-content: space-between;
width: 100%;
width: calc(100% - 32px);
height: 56px;
// border: 1px solid black;
padding: 0 16px;
/* 患者状态 */
.patientState {
position: absolute;
top: -56px;
right: 16px;
}
}
:deep(.settle-table-container) {
flex: auto;
width: calc(100% - 32px);
width: 100%;
height: calc(100% - 56px);
// border: 1px solid red;
margin-left: 0 !important;
padding: 0 8px 14px;
.table-child {
height: 100%;
// border: 1px solid red;
}
.nameRight {
border-left: 1px solid !important;
}
th.nameRight {
.cell {
&::before {
border: 0 !important;
}
}
}
}
.costcollect {
.type {
color: #333;
}
:nth-child(2) {
margin-left: 26px;
}
span {
color: #666;
}
}
}
.accounts-container {
display: flex;
flex: auto;
// margin: 0 8px;
width: 100%;
height: 321px;
// border: 1px solid black;
// background: #FFFFFF;
background-color: #f1faff;
.receivable {
flex: none;
width: 426px;
padding: 0 16px;
background-color: #fff;
// border: 1px solid #DDDDDD;
.receivable-operate {
display: flex;
justify-content: space-between;
height: 56px;
border-bottom: 2px solid #e9f3f9;
.receivableName {
color: #666;
font-size: 20px;
}
.receivableValue {
font-size: 32px;
}
.receivableValueReturn {
color: #e95657;
font-size: 32px;
}
}
.eceivableDetails {
padding-top: 29px;
>div {
height: 40px;
margin: 0 20px;
font-size: 22px;
line-height: 40px;
border-bottom: 2px solid #eee;
span:first-child {
display: inline-block;
width: 126px;
color: #666;
font-weight: 400;
text-align: right;
}
span:nth-child(2) {
display: inline-block;
width: 80px;
color: #333;
font-weight: 400;
text-align: right;
}
// span:nth-child(2) {
// color: #333333;
// }
span {
&:nth-child(2) {
min-width: 120px;
color: #333;
text-align: right;
// border: 1px solid red
}
}
}
}
}
.advanced {
flex: auto;
width: 100px;
margin-left: 8px;
background-color: #fff;
.advanced-operate {
display: flex;
justify-content: space-between;
height: 56px;
padding: 0 16px;
.advancedTotal {
color: #666;
}
}
.advancedData-container {
height: calc(100% - 64px);
padding: 0 16px 8px;
}
}
.childs {
flex: none;
width: 188px;
// border: 1px solid rgba(237, 241, 5, 0.894);
margin-left: 8px;
padding: 8px;
background: #fff;
.child {
width: 170px;
padding: 8px;
color: #666;
background: #fff;
border: 1px solid #ddd;
border-radius: 4px;
box-shadow: 0 2px 2px 0 rgba(57.55, 69.04, 86.28, 15%);
.name {
color: #333;
font-weight: 500;
font-size: 16px;
}
.typeValue {
color: #333;
}
}
}
}
.costValue {
color: #ff8616 !important;
}
}
</style>

View File

@@ -0,0 +1,61 @@
<!--
* @Author: sjjh
* @Date: 2025-04-09 14:50:04
* @Description:
-->
<template>
<div class="settlement-container">
<el-tabs v-model="activeTabName" type="card" class="inOut-tabs">
<el-tab-pane label="住院结算" name="first">
<SettlementHome />
</el-tab-pane>
<el-tab-pane label="结算取消" name="second">
<SettlementCancel />
</el-tab-pane>
<el-tab-pane label="中途结算" name="third">
<SettlementMidway />
</el-tab-pane>
</el-tabs>
</div>
</template>
<script setup >
import { getCurrentInstance, onBeforeMount, onMounted, reactive, ref } from 'vue'
import SettlementHome from './components/home/index.vue'
import SettlementCancel from './components/cancel/index.vue'
import SettlementMidway from './components/midway/index.vue'
// const { proxy } = getCurrentInstance()
// const emits = defineEmits([])
// const props = defineProps({})
const state = reactive({})
onBeforeMount(() => { })
onMounted(() => { })
defineExpose({ state })
const activeTabName = ref('first')
</script>
<style lang="scss" scoped>
.settlement-container {
width: 100%;
height: 100%;
display: flex;
padding: 0 8px 8px;
:deep(.inOut-tabs) {
height: 100%;
width: 100%;
.el-tabs__header {
margin: 0;
}
.el-tab-pane {
height: 100%;
}
.el-tabs__content {
height: calc(100% - 40px);
}
}
}
</style>

View File

@@ -0,0 +1,2 @@
<template>
</template>

View File

@@ -0,0 +1,2 @@
<template>
</template>

View File

@@ -0,0 +1,2 @@
<template>
</template>

View File

@@ -0,0 +1,2 @@
<template>
</template>

View File

@@ -0,0 +1,2 @@
<template>
</template>

View File

@@ -0,0 +1,2 @@
<template>
</template>

View File

@@ -0,0 +1,4 @@
# 住院管理
## 住院收费工作站charge
### 住院登记register
### 住院预交金管理 adcanceDeposit

View File

@@ -0,0 +1 @@
<template></template>