Revert "Fix Bug #550: AI修复"

This reverts commit 16c42ca108.
This commit is contained in:
2026-05-27 08:59:07 +08:00
parent bd14563691
commit 9db5ced4e3
5432 changed files with 778638 additions and 171 deletions

View File

@@ -0,0 +1,791 @@
<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.encounterStatus"
style="width: 48%; margin-bottom: 10px; margin-right: 10px"
placeholder="结算状态"
@change="getPatientList"
>
<el-option
v-for="item in chargeStatusOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<div style="width: 100%">
<el-date-picker
v-model="receptionTime"
type="daterange"
range-separator="~"
start-placeholder="开始时间"
end-placeholder="结束时间"
placement="bottom"
value-format="YYYY-MM-DD"
style="width: 84%; margin-bottom: 10px; margin-right: 10px"
@change="getPatientList"
/>
<el-button type="primary" style="margin-bottom: 10px" @click="getPatientList">
搜索
</el-button>
</div>
<el-table
ref="patientListRef"
height="620"
:data="patientList"
row-key="encounterId"
@cell-click="clickRow"
highlight-current-row
>
<el-table-column label="住院号" align="center" prop="encounterBusNo" />
<!-- <el-table-column label="床号" align="center" prop="bedNo" /> -->
<el-table-column label="姓名" align="center" prop="patientName" />
<el-table-column label="账户余额" align="center" prop="balanceAmount" />
<!-- <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="encounterStatus_enumText" />
</el-table>
</div>
</el-card>
<div style="width: 69%">
<el-card style="margin-bottom: 20px">
<template #header>
<span style="vertical-align: middle">基本信息</span>
</template>
<el-descriptions :column="5">
<el-descriptions-item label="姓名:">{{ patientInfo.patientName }}</el-descriptions-item>
<el-descriptions-item label="性别:">
{{ patientInfo.genderEnum_enumText }}
</el-descriptions-item>
<el-descriptions-item label="年龄:">{{ patientInfo.age }}</el-descriptions-item>
<!-- <el-descriptions-item label="科室:">
{{ patientInfo.organizationName }}
</el-descriptions-item> -->
<!-- <el-descriptions-item label="床号:">
{{ patientInfo.bedNo }}
</el-descriptions-item>
<el-descriptions-item label="就诊时间:">
{{ formatDateStr(patientInfo.receptionTime, 'YYYY-MM-DD HH:mm:ss') }}
</el-descriptions-item> -->
</el-descriptions>
</el-card>
<el-card>
<el-date-picker
v-model="costSearchTime"
type="daterange"
range-separator="~"
start-placeholder="开始时间"
end-placeholder="结束时间"
placement="bottom"
value-format="YYYY-MM-DD"
style="width: 40%; margin-bottom: 10px; margin-right: 10px"
@change="getPatientList"
/>
<el-button type="primary" style="margin-bottom: 10px" @click="costSearch"> 搜索 </el-button>
</el-card>
<el-card style="min-width: 1100px; margin-top: 20px">
<template #header>
<span style="vertical-align: middle">收费项目</span>
</template>
<div style="margin-bottom: 10px">
<el-button type="primary" @click="confirmCharge()" :disabled="buttonDisabled">
确认收费
</el-button>
<el-button type="primary" plain @click="handleReadCard('01')" style="width: 65px">
电子凭证
</el-button>
<el-button
type="primary"
plain
@click="handleReadCard('02')"
style="width: 65px"
:disabled="true"
>
身份证
</el-button>
<el-button type="primary" plain @click="handleReadCard('03')" style="width: 65px">
医保卡
</el-button>
<el-button
type="primary"
@click="payToSelt()"
style="margin-left: 20px"
:disabled="buttonDisabled"
>
医保转自费
</el-button>
<el-button
type="primary"
@click="patToMedicalInsurance()"
style="margin-left: 20px"
:disabled="buttonDisabled"
>
自费转医保
</el-button>
<el-button
type="primary"
@click="studentPayTosStudentSelf()"
style="margin-left: 20px"
:disabled="buttonDisabled"
>
学生医保转学生自费
</el-button>
<el-button
type="primary"
@click="studentSelfToStudentPay()"
style="margin-left: 20px"
:disabled="buttonDisabled"
>
学生自费转学生医保
</el-button>
<span style="float: right"
>合计金额{{ totalAmounts ? totalAmounts.toFixed(2) : 0 }}</span
>
</div>
<el-table
ref="chargeListRef"
height="530"
:data="chargeFilterList"
row-key="id"
@selection-change="handleSelectionChange"
v-loading="chargeLoading"
:span-method="objectSpanMethod"
border
>
<el-table-column type="selection" :selectable="checkSelectable" width="55" />
<el-table-column label="单据号" align="center" prop="busNo" width="180" />
<el-table-column label=" 开立科室" align="center" prop="requestingOrgId" width="180" />
<el-table-column label="处方号" align="center" prop="prescriptionNo" 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">
<!-- 1代收费 2代结算 5已收费 8已退费 -->
<el-tag v-if="scope.row.statusEnum === 1" disable-transitions>
{{ scope.row.statusEnum_enumText }}
</el-tag>
<el-tag v-else-if="scope.row.statusEnum === 5" type="success" disable-transitions>
{{ scope.row.statusEnum_enumText }}
</el-tag>
<el-tag v-else-if="scope.row.statusEnum === 8" type="danger" disable-transitions>
{{ scope.row.statusEnum_enumText }}
</el-tag>
<el-tag v-else type="warning" disable-transitions>
{{ scope.row.statusEnum_enumText }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="金额" align="right" prop="totalPrice" header-align="center">
<template #default="scope">
{{ scope.row.totalPrice.toFixed(2) + ' 元' || '0.00' + ' 元' }}
</template>
</el-table-column>
<el-table-column label="收款人" align="center" prop="entererId_dictText" />
<el-table-column label="收费时间" align="center" prop="billDate" width="180" />
<el-table-column
label="应收金额"
align="right"
prop="receivableAmount"
header-align="center"
>
<template #default="scope">
{{ scope.row.receivableAmount.toFixed(2) + ' 元' || '0.00' + ' 元' }}
</template>
</el-table-column>
<el-table-column
label="实收金额"
align="right"
prop="receivedAmount"
header-align="center"
>
<template #default="scope">
{{ scope.row.receivedAmount.toFixed(2) + ' 元' || '0.00' + ' 元' }}
</template>
</el-table-column>
<el-table-column
label="优惠金额"
align="right"
prop="discountAmount"
header-align="center"
>
<template #default="scope">
{{ scope.row.discountAmount.toFixed(2) + ' 元' || '0.00' + ' 元' }}
</template>
</el-table-column>
<el-table-column label="折扣率" align="right" prop="discountRate" header-align="center">
<template #default="scope">
<!-- discountRate是一个字符串类型的 -->
{{ Number(scope.row.discountRate).toFixed(2) + '%' || '0.00' + '%' }}
</template>
</el-table-column>
<el-table-column
label="操作"
align="center"
fixed="right"
header-align="center"
class-name="no-hover-column"
>
<template #default="scope">
<el-button
:disabled="!scope.row.paymentId"
link
type="primary"
@click="printCharge(scope.row)"
>
打印
</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
</div>
<ChargeDialog
ref="chargeDialogRef"
:open="openDialog"
@close="handleClose"
:category="patientInfo.categoryEnum"
:totalAmount="totalAmount"
:patientInfo="patientInfo"
:chargeItemIds="chargeItemIdList"
:consumablesIdList="consumablesIdList"
:chrgBchnoList="chrgBchnoList"
:userCardInfo="userCardInfo"
:paymentId="paymentId"
:details="details"
:chargedItems="chargedItems"
@refresh="getPatientList"
:newId="newId"
:oldId="oldId"
/>
</div>
</template>
<script setup name="ClinicCharge">
import {
changeStudentPayTosStudentSelf,
changeStudentSelfToStudentPay,
changeToMedicalInsurance,
changeToSelfPay,
getChargeInfo,
getChargeList,
getList1,
init1,
precharge,
} from './components/api';
import {invokeYbPlugin5001} from '@/api/public';
import ChargeDialog from './components/chargeDialog.vue';
import {formatDateStr} from '@/utils';
import useUserStore from '@/store/modules/user';
import Decimal from 'decimal.js';
import moment from 'moment';
const { proxy } = getCurrentInstance();
const userStore = useUserStore();
const queryParams = ref({
pageNum: 1,
pageSize: 50,
encounterStatus: 4,
});
const totalAmounts = ref(0);
const selectedRows = ref([]);
const patientList = ref([]);
// 收费项目列表
const chargeList = ref([]);
// 根据时间过滤的收费项目列表
const chargeFilterList = ref([]);
const chargeItemIdList = ref([]);
const chrgBchnoList = ref([]);
const chargeLoading = ref(false);
const encounterId = ref('');
const paymentId = ref('');
const newId = ref('');
const oldId = ref('');
const patientInfo = ref({});
const openDialog = ref(false);
const totalAmount = ref(0);
const chargeListRef = ref();
const details = ref({});
const chargeStatusOptions = ref([]);
const receptionTime = ref([
formatDateStr(new Date(), 'YYYY-MM-DD'),
formatDateStr(new Date(), 'YYYY-MM-DD'),
]);
// 计算当前时间+6天
const accumulateDay = () => {
// 获取当前时间
let now = moment();
// 在当前时间上加一天
let tomorrow = now.add(6, 'days');
// 格式化为年-月-日的格式
let formattedDate = tomorrow.format('YYYY-MM-DD');
return formattedDate;
};
// 收费项目时间段搜索
const costSearchTime = ref([formatDateStr(new Date(), 'YYYY-MM-DD'), accumulateDay()]);
// 测试数据
const items = [
{ id: 1, name: 'Item 1', date: '2025-12-15' },
{ id: 2, name: 'Item 2', date: '2025-12-18' },
{ id: 3, name: 'Item 3', date: '2025-12-20' },
];
// 根据时间短搜索
const costSearch = () => {
console.log(costSearchTime.value === null);
if (costSearchTime.value === null) {
chargeFilterList.value = chargeList.value;
} else {
const startTime = moment(costSearchTime.value[0], 'YYYY-MM-DD');
const endTime = moment(costSearchTime.value[1], 'YYYY-MM-DD');
const filterData = chargeList.value.filter((item) => {
const itemDate = moment(item.billDate || '', 'YYYY-MM-DD'); // 将数据项的日期也格式化为moment对象
return itemDate.isBetween(startTime, endTime, null, '[]'); // 使用isBetween方法进行范围判断'[]'表示包含边界值
});
chargeFilterList.value = filterData;
}
};
const buttonDisabled = computed(() => {
return Object.keys(patientInfo.value).length === 0;
});
const chargedItems = ref([]);
watch(
() => selectedRows.value,
(newVlaue) => {
if (newVlaue && newVlaue.length > 0) {
handleTotalAmount();
} else {
totalAmounts.value = 0;
}
},
{ immediate: true }
);
watch(
() => chargeList.value,
(newVlaue) => {
if (newVlaue && newVlaue.length > 0) {
chargeFilterList.value = newVlaue;
}
},
{ immediate: true }
);
function handleSelectionChange(selection) {
selectedRows.value = selection;
}
function handleTotalAmount() {
totalAmounts.value = selectedRows.value.reduce((accumulator, currentRow) => {
return new Decimal(accumulator).add(currentRow.totalPrice.toFixed(2) || 0);
}, 0);
}
getPatientList();
initOption();
/**
* 患者列表
*/
function getPatientList() {
if (receptionTime.value.length > 0) {
queryParams.value.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;
}
getList1(queryParams.value).then((res) => {
console.log('患者列表', res);
patientList.value = res.data.records;
});
}
function initOption() {
init1().then((res) => {
console.log('初始化收费项目状态', res);
chargeStatusOptions.value = res.data.encounterStatusOptions;
console.log('res.data.chargeItemStatusOptions======>', JSON.stringify(res.data));
});
}
function checkSelectable(row, index) {
// 已结算时禁用选择框
return row.statusEnum == 1 || row.statusEnum == 2;
}
/**
* 点击患者列表行 获取处方列表
*/
function clickRow(row) {
patientInfo.value = row;
chargeLoading.value = true;
encounterId.value = row.encounterId;
getChargeList(row.encounterId).then((res) => {
chargeList.value = res.data;
setTimeout(() => {
chargeLoading.value = false;
chargeListRef.value.toggleAllSelection();
}, 100);
});
}
function handleClose(value, msg) {
openDialog.value = false;
if (value == 'success') {
proxy.$modal.msgSuccess(msg);
chargeLoading.value = true;
getChargeList(patientInfo.value.encounterId).then((res) => {
chargeList.value = res.data;
setTimeout(() => {
chargeLoading.value = false;
}, 100);
});
}
}
const consumablesIdList = ref([]);
// 确认收费
function confirmCharge() {
let selectRows = chargeListRef.value.getSelectionRows();
if (selectRows.length == 0) {
proxy.$modal.msgWarning('请选择一条收费项目');
return;
}
chargeItemIdList.value = selectRows.map((item) => {
return item.id;
});
//wor_device_request 器材
consumablesIdList.value = selectRows
.filter((item) => {
return item.serviceTable == 'wor_device_request';
})
.map((item) => {
return item.id;
});
chargedItems.value = selectRows;
// totalAmount.value = selectRows.reduce((accumulator, currentRow) => {
// return accumulator + (currentRow.totalPrice || 0);
// }, 0);
precharge({
patientId: patientInfo.value.patientId,
encounterId: patientInfo.value.encounterId,
chargeItemIds: chargeItemIdList.value,
}).then((res) => {
if (res.code == 200 && res.data) {
const item = res.data.paymentRecDetailDtoList?.find((i) => {
return i.payEnum == 220000;
});
totalAmount.value = item?.amount ?? 0;
paymentId.value = res.data.id;
newId.value = res.data.newId;
oldId.value = res.data.oldId;
chrgBchnoList.value = res.data.chrgBchnoList;
details.value = res.data.paymentRecDetailDtoList?.filter((item) => {
return item.amount > 0;
}) || [];
openDialog.value = true;
} else {
proxy.$modal.msgError(res?.msg || '预结算失败');
}
});
// console.log(patientInfo)
}
let userCardInfo = ref({});
const readCardLoading = ref(false);
const loadingText = ref('');
const BusiCardInfo = ref(''); // miyao
async function handleReadCard(value) {
// if (window.CefSharp === undefined) {
// alert('请在医保版本中调用读卡功能!');
// } else {
try {
// await CefSharp.BindObjectAsync('boundAsync');
// string url,
// string fixmedins_code,
// string businessType,
// string operatorCode,
// string operatorName,
// string officeId,
// string officeName
// readCardLoading.value = true;
let jsonResult;
let cardInfo;
let userMessage = undefined;
switch (value) {
case '01': // 电子凭证
// readCardLoading.value = true;
await invokeYbPlugin5001({
FunctionId: 3,
url: 'http://10.47.0.67:8089/localcfc/api/hsecfc/localQrCodeQuery',
orgId: 'H22010200672',
businessType: '01101',
operatorId: userStore.id.toString(),
operatorName: userStore.name,
officeId: 'D83',
officeName: '财务科',
})
.then((res) => {
readCardLoading.value = true;
loadingText.value = '正在读取...';
jsonResult = res.data;
})
.catch(() => {
readCardLoading.value = false;
})
.finally(() => {
readCardLoading.value = false;
});
cardInfo = JSON.parse(JSON.stringify(jsonResult));
let message = JSON.parse(cardInfo.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 invokeYbPlugin5001(
JSON.stringify({
FunctionId: 1,
IP: 'ddjk.jlhs.gov.cn',
PORT: 20215,
TIMEOUT: 60,
SFZ_DRIVER_TYPE: 1,
})
)
.then((res) => {
jsonResult = JSON.stringify(res.data);
})
.finally(() => {
readCardLoading.value = false;
});
// console.log(
// 'jsonResult',
// JSON.parse({
// IssuingAreaCode: '310000',
// SocialSecurityNumber: '371324198810224515',
// CardNumber: 'M501A1A78',
// CardIdentificationCode: '310000D15600000535925154E880AB97',
// Name: '\u5218\u5CF0',
// CardResetInfo: '00814A444686603100333E4FA9',
// SpecificationVersion: '3.00',
// IssuingDate: '20190313',
// ExpirationDate: '20290313',
// TerminalNumber: '000000000000',
// TerminalDeviceNumber: '00041161201901000005',
// Code: 0,
// ErrorMessage: null,
// })
// );
let message1 = JSON.parse(jsonResult);
userMessage = {
certType: '02', // 证件类型
certNo: message1.SocialSecurityNumber, // 身份证号
psnCertType: '02', // 居民身份证
};
userCardInfo = {
certType: '02', // 证件类型
certNo: message1.SocialSecurityNumber, // 身份证号
psnCertType: '02', // 居民身份证
busiCardInfo: message1.BusiCardInfo, //卡号
};
BusiCardInfo.value = message1.BusiCardInfo;
console.log(message1.BusiCardInfo);
break;
case '99':
break;
}
readCardLoading.value = false;
if (userMessage.certNo) {
let selectRows = chargeListRef.value.getSelectionRows();
if (selectRows.length == 0) {
proxy.$modal.msgWarning('请选择一条收费项目');
return;
}
chargeItemIdList.value = selectRows.map((item) => {
return item.id;
});
totalAmount.value = selectRows.reduce((accumulator, currentRow) => {
return accumulator + (currentRow.totalPrice || 0);
}, 0);
precharge({
patientId: patientInfo.value.patientId,
encounterId: patientInfo.value.encounterId,
chargeItemIds: chargeItemIdList.value,
ybMdtrtCertType: userCardInfo.psnCertType,
busiCardInfo: userCardInfo.busiCardInfo,
}).then((res) => {
if (res.code == 200 && res.data) {
paymentId.value = res.data.id;
totalAmount.value = res.data.paymentRecDetailDtoList?.find(
(item) => item.payEnum == 220000
)?.amount ?? 0;
details.value = res.data.paymentRecDetailDtoList || [];
// chrgBchnoList.value = res.data.chrgBchnoList;
chargeItemIdList.value = selectRows.map((item) => {
return item.id;
});
// 打印项目赋值
chargedItems.value = selectRows;
newId.value = res.data.newId;
oldId.value = res.data.oldId;
consumablesIdList.value = selectRows
.filter((item) => {
return item.serviceTable == 'wor_device_request';
})
.map((item) => {
return item.id;
});
openDialog.value = true;
} else {
proxy.$modal.msgError(res?.msg || '预结算失败');
}
});
}
} catch (error) {
console.error('调用失败:', error);
readCardLoading.value = false;
}
// }
}
/**
* 医保转自费
*/
function payToSelt() {
changeToSelfPay(encounterId.value).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('操作成功');
}
});
}
/**
* 自费转医保
*/
function patToMedicalInsurance() {
changeToMedicalInsurance(encounterId.value).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('操作成功');
}
});
}
/**
* 学生医保转学生自费
*/
function studentPayTosStudentSelf() {
changeStudentPayTosStudentSelf(encounterId.value).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('操作成功');
}
});
}
/**
* 学生自费转学生医保
*/
function studentSelfToStudentPay() {
changeStudentSelfToStudentPay(encounterId.value).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('操作成功');
}
});
}
// 添加行合并方法
function objectSpanMethod({ row, column, rowIndex, columnIndex }) {
// 只对操作列进行合并(根据列索引判断,操作列为最后一列)
if (columnIndex === 10) {
// 操作列索引为10从0开始计数
// 如果当前行的paymentId为空则不合并
if (!row.paymentId) {
return [1, 1];
}
// 查找相同paymentId的连续行
let spanCount = 1;
if (rowIndex === 0 || chargeList.value[rowIndex - 1].paymentId !== row.paymentId) {
// 这是具有相同paymentId的第一行计算需要合并的行数
for (let i = rowIndex + 1; i < chargeList.value.length; i++) {
if (chargeList.value[i].paymentId === row.paymentId) {
spanCount++;
} else {
break;
}
}
return [spanCount, 1];
} else {
// 这不是具有相同paymentId的第一行返回0表示不显示
return [0, 0];
}
}
// 其他列不合并
return [1, 1];
}
function printCharge(row) {
// 打印功能实现
let rows = [];
chargeList.value.forEach((item, index) => {
if (item.paymentId === row.paymentId) {
rows.push(item);
}
});
chargedItems.value = rows;
getChargeInfo({ paymentId: row.paymentId }).then((res) => {
proxy.$refs['chargeDialogRef'].printReceipt(res.data);
});
}
</script>
<style scoped>
:deep(.no-hover-column) .cell:hover {
background-color: transparent !important;
}
:deep(.el-table__body) tr:hover td.no-hover-column {
background-color: inherit !important;
}
</style>