Revert "```"

This reverts commit abc0674531.
This commit is contained in:
2025-12-26 22:21:21 +08:00
parent ae6c486114
commit 3115e38cc4
920 changed files with 14452 additions and 107025 deletions

View File

@@ -79,9 +79,6 @@
</el-form-item>
<el-form-item label="属性代码" prop="code">
<el-input v-model="form.code" placeholder="请输入属性代码" />
</el-form-item>
<el-form-item label="体温单类型编码" prop="typeCode">
<el-input v-model="form.typeCode" placeholder="请输入体温单属性编码" />
</el-form-item>
<el-form-item label="岗位顺序" prop="displayOrder">
<el-input-number v-model="form.displayOrder" controls-position="right" :min="0" />
@@ -200,7 +197,6 @@ function reset() {
displayOrder: 0, // 显示顺序
dictName: '', //字典名称
dictType: '', //字典类型
typeCode:'',//体温单类型编码
};
proxy.resetForm('statisticsRef');
}

View File

@@ -32,7 +32,7 @@
<PopoverList @search="handleSearch" :width="800" :modelValue="scope.row.name">
<template #popover-content="{}">
<DeviceList
v-if="scope.row.type == '2' || props.tab == 2"
v-if="scope.row.type == '2' || props.tab == 2 "
@selectRow="(row) => selectRow(row, scope.$index)"
:searchKey="searchKey"
/>
@@ -171,7 +171,7 @@
</el-form>
</div>
</template>
<script setup>
import { reactive, watch } from 'vue';
import { bind, deleteBind, init } from './api';
@@ -345,5 +345,6 @@ function selectRow(row, index) {
}
}
</script>
<style scoped></style>
<style scoped>
</style>

View File

@@ -79,12 +79,8 @@ import { getActivityList, getBindList, getRegistrationfeeList } from './componen
import ConsumablesList from './components/consumablesList.vue';
const activityList = ref([]);
const queryParams = ref({
statusEnum: 2,
});
const queryParamsRegistration = ref({
activeFlag: 1,
});
const queryParams = ref({});
const queryParamsRegistration = ref({});
const bindList = ref([]);
const bindInfo = ref({});
const activeTab = ref(1);
@@ -95,18 +91,19 @@ const { proxy } = getCurrentInstance();
const { method_code } = proxy.useDict('method_code');
getList();
getRegistrationList();
getRegistrationList()
function getList() {
// queryParams.value.typeEnum = activeTab.value;
getActivityList(queryParams.value).then((res) => {
activityList.value = res.data.records;
});
}
function getRegistrationList() {
getRegistrationfeeList(queryParamsRegistration.value).then((res) => {
getRegistrationfeeList(queryParamsRegistration.value).then(res => {
RegistrationfeeList.value = res.data.records;
});
})
}
// 点击诊疗列表 获取绑定的耗材
@@ -122,4 +119,5 @@ function clickRow(row) {
}
</script>
<style scoped></style>
<style scoped>
</style>

View File

@@ -5,7 +5,7 @@
<span style="vertical-align: middle">病区</span>
</template>
<div style="width: 100%">
<el-button type="primary" @click="onIncrease" class="mb8"> 新增 </el-button>
<el-button type="primary" @click="open = true" class="mb8"> 新增 </el-button>
<el-button type="success" plain @click="handleEnableBatch('wardRef')" class="mb8">
批量启用
</el-button>
@@ -16,7 +16,7 @@
<el-table
max-height="630"
:data="wardList"
@cell-click="(row) => clickRow(row, 10, 0)"
@cell-click="(row) => clickRow(row, 10)"
highlight-current-row
ref="wardRef"
>
@@ -95,7 +95,7 @@
<el-table
height="280"
:data="houseList"
@cell-click="(row) => clickRow(row, 8, 0, 1)"
@cell-click="(row) => clickRow(row, 8)"
highlight-current-row
v-loading="loading"
ref="hourseRef"
@@ -134,7 +134,7 @@
@click.stop="
() => {
handleUnable(scope.row).then(() => {
getHouseList();
clickRow(houseRow, 10);
});
}
"
@@ -153,7 +153,7 @@
@click.stop="
() => {
handleEnable(scope.row).then(() => {
getHouseList();
clickRow(houseRow, 10);
});
}
"
@@ -206,7 +206,7 @@
@click.stop="
() => {
handleUnable(scope.row, 10).then(() => {
getBedList();
clickRow(bedRow, 8);
});
}
"
@@ -225,7 +225,7 @@
@click.stop="
() => {
handleEnable(scope.row, 10).then(() => {
getBedList();
clickRow(bedRow, 8);
});
}
"
@@ -255,7 +255,7 @@
</el-radio-group>
</el-form-item>
<el-form-item :label="type + '名称'" prop="name">
<el-input v-model="form.name" :placeholder="'请输入' + type + '名称'" />
<el-input v-model="form.name" placeholder="请输入科室名称" />
</el-form-item>
<el-col>
<el-form-item :label="upLabel" prop="busNoParent">
@@ -304,9 +304,8 @@
</el-dialog>
</div>
</template>
<script setup name="Ward">
import { onMounted, ref } from 'vue';
import {
getList,
addLocation,
@@ -316,65 +315,33 @@ import {
unableLocation,
enableLocation,
} from './components/api';
import { ElMessage } from 'element-plus';
const { proxy } = getCurrentInstance();
// 病区参数
const queryParams = ref({
pageNum: 1,
pageSize: 50,
formEnum: 4, //4 病区 10 病房 8床位
formEnum: 4,
// locationFormList: [4],
});
// 病房参数
const queryHouseParams = ref({
pageNum: 1,
pageSize: 50,
formEnum: 10, //4 病区 10 病房 8床位
// locationFormList: [4],
});
// 病床参数
const querybedParams = ref({
pageNum: 1,
pageSize: 50,
formEnum: 8, //4 病区 10 病房 8床位
// locationFormList: [4],
});
// 病区、病房、病床类型
const type = ref('病区');
// 病区列表
const wardList = ref([]);
// 床位列表
const bedList = ref([]);
// 病房列表
const houseList = ref([]);
const wardListOption = ref([]);
const organization = ref([]);
const loading = ref(false);
const isEdit = ref(false);
const open = ref(false);
// 病区row
const wardRow = ref({});
// 床位row
const bedRow = ref({});
// 病房row
const houseRow = ref({});
// 记录点击的是启用
const clickType = ref(0);
const orgRef = ref();
// 新增数据参数
const form = reactive({
formEnum: 4,
busNoParent: '',
organizationId: '',
name: '',
busNo: '',
});
const upLabel = ref('关联科室');
const title = ref('新增');
const rules = ref({
name: [
{ required: true, message: '请输入名称', trigger: 'blur' },
{ required: true, min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur' },
{ required: true, message: '请输入科室名称', trigger: 'blur' },
{ min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur' },
],
busNoParent: [
{
@@ -384,76 +351,23 @@ const rules = ref({
},
],
});
// 获取科室下啦树
/**
* 病区列表
*/
function getWardList() {
queryParams.value.formEnum = 4;
getList(queryParams.value).then((res) => {
wardList.value = res.data.records;
});
}
function init() {
getOrgList().then((res) => {
organization.value = res.data.records;
});
}
/**
* 病区列表
*/
function getWardList() {
houseList.value = [];
bedList.value = [];
getList(queryParams.value).then((res) => {
wardList.value = res.data.records;
});
}
// 获取病房列表
const getHouseList = () => {
// 4病区 10病房 8床位
loading.value = true;
// 病区号
queryHouseParams.value.busNo = wardRow.value.busNo;
bedList.value = [];
getList(queryHouseParams.value).then((res) => {
houseList.value = res.data.records;
loading.value = false;
});
};
// 获取床位列表
const getBedList = () => {
// 4病区 10病房 8床位
loading.value = true;
querybedParams.value.busNo = houseRow.value.busNo;
bedList.value = [];
getList(querybedParams.value).then((res) => {
bedList.value = res.data.records;
loading.value = false;
});
};
// 点击新增按钮
const onIncrease = () => {
open.value = true;
};
// 查询病房和病区的下拉选
const getHomeOrBed = (formEnum) => {
const params = {
formEnum,
pageNum: 1,
pageSize: 50,
};
getList(params).then((res) => {
if (formEnum == 10) {
const datas = res.data?.records || [];
const optionsList = datas.map((item) => {
let obj = {
...item,
};
obj.name = item.parentName + '-' + item.name;
return obj;
});
wardListOption.value = optionsList;
} else {
wardListOption.value = res.data?.records || [];
}
});
};
function handleRadioChange(val) {
let formEnum = 4;
if (val == 4) {
type.value = '病区';
upLabel.value = '关联科室';
@@ -461,56 +375,38 @@ function handleRadioChange(val) {
} else if (val == 10) {
type.value = '病房';
upLabel.value = '所属病区';
formEnum = 4;
// queryParams.value.formEnum = 4;
queryParams.value.formEnum = 4;
} else {
type.value = '床位';
upLabel.value = '所属病房';
formEnum = 10;
// queryParams.value.formEnum = 10;
queryParams.value.formEnum = 10;
}
form.organizationId = '';
form.busNo = '';
form.busNoParent = '';
form.name = '';
getHomeOrBed(formEnum);
getList(queryParams.value).then((res) => {
wardListOption.value = res.data.records;
});
}
/**
* 点击患者列表行 获取处方列表
*/
function clickRow(row, val, type) {
// 1点击了启用
clickType.value = type;
console.log('val=====>', JSON.stringify(row));
console.log('type=====>', JSON.stringify(type));
console.log('val=====>', JSON.stringify(val));
// if (type !== 1) {
// if (val == 10) {
// wardRow.value = row;
// getHouseList();
// } else if (val == 8) {
// houseRow.value = row;
// getBedList();
// }
// } else {
// if (val == 10) {
// houseRow.value = row;
// getHouseList();
// } else if (val == 8) {
// bedRow.value = row;
// getBedList();
// }
// }
if (val == 10) {
wardRow.value = row;
getHouseList();
} else if (val == 8) {
houseRow.value = row;
console.log('houseRow=====>', houseRow.value);
getBedList();
}
function clickRow(row, val) {
loading.value = true;
queryParams.value.formEnum = val;
queryParams.value.busNo = row.busNo;
bedList.value = [];
getList(queryParams.value).then((res) => {
if (val == 10) {
houseList.value = res.data.records;
houseRow.value = row;
} else if (val == 8) {
bedRow.value = row;
bedList.value = res.data.records;
}
setTimeout(() => {
queryParams.value.busNo = undefined;
loading.value = false;
}, 100);
});
}
function checkSelectable(row, index) {
@@ -563,113 +459,38 @@ function handleUnableBatch(tableRef) {
});
}
// 新增病床拆分"busNo": "LOC055.LOC056",
const splitBusNo = (busNo) => {
const busNoArr = busNo.split('.') || [];
let busNoParent = '';
if (busNoArr.length > 1) {
busNoParent = busNoArr[0];
}
return busNoParent;
};
function submitForm() {
if (!orgRef) return;
const params = {
...form,
};
console.log('form========>', JSON.stringify(form));
console.log('params11========>', JSON.stringify(params));
orgRef.value.validate((valid) => {
if (valid) {
console.log('99999999');
if (form.busNoParent) {
if (form.formEnum == 4) {
params.organizationId = form.busNoParent;
} else {
if (!isEdit.value) {
params.busNo = form.busNoParent;
// params.busNoParent = splitBusNo(form.busNoParent);
}
}
} else {
if (form.formEnum == 4) {
if (!(params.organizationId && params.organizationId.length > 0)) {
ElMessage({
type: 'error',
message: '请选择关联科室!',
});
return;
}
} else if (form.formEnum == 10) {
if (!(params.busNo && params.busNo.length > 0)) {
ElMessage({
type: 'error',
message: '请选择所属病区!',
});
return;
}
} else {
if (!(params.busNo && params.busNo.length > 8)) {
ElMessage({
type: 'error',
message: '请选择所属病房!',
});
return;
}
}
}
// console.log('params========>', JSON.stringify(form));
console.log('params========>', JSON.stringify(params));
// console.log('params========>', isEdit.value);
if (!isEdit.value) {
addLocation(params).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('操作成功');
if (params.formEnum == 4) {
cancel();
getWardList();
} else if (params.formEnum == 10) {
getHouseList();
open.value = false;
} else if (params.formEnum == 8) {
getBedList();
open.value = false;
}
}
});
} else {
editLocation(params).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('操作成功');
if (params.formEnum == 4) {
cancel();
getWardList();
} else if (params.formEnum == 10) {
getHouseList();
open.value = false;
} else if (params.formEnum == 8) {
getBedList();
open.value = false;
}
}
});
}
if (form.busNoParent) {
if (form.formEnum == 4) {
form.organizationId = form.busNoParent;
} else {
form.busNo = form.busNoParent;
}
});
}
console.log(form);
if (!isEdit.value) {
addLocation(form).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('操作成功');
cancel();
getWardList();
}
});
} else {
editLocation(form).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('操作成功');
cancel();
getWardList();
}
});
}
}
function handleDelete(row) {
deleteLocation(row.busNo).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('删除成功');
if (row.formEnum == 4) {
getWardList();
} else if (row.formEnum == 10) {
getHouseList();
} else {
getBedList();
}
}
});
}
@@ -680,27 +501,24 @@ function getLastPartOfString(str) {
}
function handleEdit(row, val) {
console.log('editRow=========>', JSON.stringify(row));
form.id = row.id;
form.name = row.name;
form.formEnum = row.formEnum;
form.busNo = row.busNo;
if (row.organizationId) {
form.busNoParent = row.organizationId;
form.organizationId = row.organizationId;
} else {
form.busNoParent = row.busNo.split('.').slice(0, -1).join('.');
}
isEdit.value = true;
title.value = '编辑';
open.value = true;
console.log('editRow1=========>', JSON.stringify(form));
if (val == 4) {
getHomeOrBed(4);
} else if (val == 10) {
getHomeOrBed(10);
if (val) {
queryParams.value.formEnum = val;
getList(queryParams.value).then((res) => {
wardListOption.value = res.data.records;
});
}
open.value = true;
}
function cancel() {
@@ -714,13 +532,10 @@ function cancel() {
isEdit.value = false;
title.value = '新增';
}
// 页面挂在成功
onMounted(() => {
// 获取所有科室
init();
// 获取病区列表
getWardList();
});
init();
getWardList();
</script>
<style scoped></style>
<style scoped>
</style>

View File

@@ -217,7 +217,6 @@
:statusFlagOptions="statusFlagOptions"
:exeOrganizations="exeOrganizations"
:typeEnumOptions="typeEnumOptions"
:isEditInfoDisable="isEditInfoDisable"
:title="title"
:item="currentData"
@submit="getList()"

View File

@@ -197,15 +197,8 @@ const emit = defineEmits(['close']);
function submit() {
console.log(props.chargeItemIds);
console.log(
displayAmount.value,
parseFloat(displayAmount.value),
formData.totalAmount,
formData,
'feeRefund'
);
//比较时,将金额都转换为两位小数的字符串再转换为浮点数,避免浮点数精度问题
if (parseFloat(displayAmount.value) < parseFloat(formData.totalAmount.toFixed(2))) {
if (parseFloat(displayAmount.value) < formData.totalAmount) {
proxy.$modal.msgError('请输入正确的金额');
return;
}
@@ -262,7 +255,7 @@ function submit() {
// returnedAmount: parseFloat(returnedAmount.value),
}).then((res) => {
if (res.code == 200) {
// 长春市朝阳区中医院自动退耗材
// 长春大学自动退耗材
emit('close', 'success');
}
@@ -464,4 +457,4 @@ const getFeeTypeText = computed(() => {
.amount-input .el-input__inner {
padding-right: 30px !important;
}
</style>
</style>

View File

@@ -139,6 +139,16 @@
prop="chargeStatus_enumText"
width="100"
/>
<!-- <el-table-column
label="发药/执行状态"
align="center"
prop="dispenseStatus_enumText"
width="130"
>
<template #default="scope">
{{ scope.row.dispenseStatus_enumText || scope.row.serviceStatus_enumText }}
</template>
</el-table-column> -->
<el-table-column label="数量" align="center" width="100">
<template #default="scope">
{{ scope.row.quantityValue + ' ' + scope.row.quantityUnit_dictText }}

View File

@@ -1,39 +0,0 @@
import request from '@/utils/request';
import { dateEquals } from 'element-plus';
// 获取网银支付参数列表
export function getList (data) {
return request ({
url: '/three-part/pay/page',
method: 'get',
params:data,
});
}
export function getPayinfo (data) {
return request ({
url: '/three-part/pay/pay-query?paymentId='+data.paymentId,
method: 'get',
});
}
export function returnfee (data) {
return request ({
url: '/three-part/pay/return-bill?paymentId='+data.paymentId,
method: 'get',
});
}
export function returnFeednext (data) {
return request ({
url: '/three-part/pay/return-goods?paymentId='+data.paymentId,
method: 'get',
});
}
export function returnResult (data) {
return request ({
url: '/three-part/pay/return-query?id='+data.id,
method: 'get',
});
}

View File

@@ -1,119 +0,0 @@
<template>
<div class="app-continer">
<el-form :model="queryParams" ref="queryRef" :inline="true">
<el-form-item label="患者姓名" prop="patientName">
<el-input v-model="queryParams.searchKey" placeholder="请输入患者姓名" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-table :data="recordList" v-loading="loading" border ref="tableRef">
<el-table-column label="患者姓名" align="center" prop="patientName" :show-overflow-tooltip="true" />
<el-table-column label="支付单号" align="center" prop="paymentBusNo" :show-overflow-tooltip="true" />
<el-table-column label="交易金额(元)" align="right" prop="txnAmt" header-align="center" width="100"
:show-overflow-tooltip="true">
</el-table-column>
<el-table-column label="交易类型" align="center" prop="tranType" :show-overflow-tooltip="true" />
<el-table-column label="支付方式" align="center" prop="payType" :show-overflow-tooltip="true" />
<el-table-column label="交易时间" align="center" prop="txnTime" :show-overflow-tooltip="true">
<template #default="scope">
<span>{{ parseTime(scope.row.txnTime) }}</span>
</template>
</el-table-column>
<el-table-column label="原交易类型" align="center" prop="orgTranType" :show-overflow-tooltip="true" />
<el-table-column label="原交易类型" align="center" prop="orgTranType" :show-overflow-tooltip="true" />
<el-table-column label="第三方优惠说明" align="center" prop="otherMsg" :show-overflow-tooltip="true" />
<el-table-column label="错误信息" align="center" prop="errMsg" :show-overflow-tooltip="true" />
<el-table-column label="查询结果" align="center" prop="queryResult" :show-overflow-tooltip="true" />
<el-table-column label="查询结果说明" align="center" prop="queryResultMsg" :show-overflow-tooltip="true" />
<el-table-column label="操作" align="center" prop="paymentEnum_enumText" width="340">
<template #default="scope">
<el-button type="primary" link :disabled="!scope.row.paymentId"
@click="getPayInfo(scope.row.paymentId)">支付结果查询</el-button>
<el-button type="warning" link :disabled="!scope.row.paymentId"
@click="returnFee(scope.row.paymentId)">退费</el-button>
<el-button type="danger" link auto-insert-space :disabled="!scope.row.paymentId"
@click="returnFeeNext(scope.row.paymentId)">隔天退费</el-button>
<el-button type="success" link @click="returnFeeResultQuery(scope.row.id)">退费结果查询</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
@pagination="getLists" />
</div>
</template>
<script setup name="ClinicRecord">
const { proxy } = getCurrentInstance();
import { getList, getPayinfo, returnfee, returnFeednext, returnResult } from './components/api.js';
const total = ref(0);
const queryParams = ref({
pageNo: 1,
pageSize: 100,
searchKey: '',
});
const recordList = ref([]);
const loading = ref(false);
const getPayInfo = (paymentId) => {
console
getPayinfo({ paymentId }).then((res) => {
proxy.$message.success('支付结果查询成功');
console.log(res);
});
};
const returnFee = (paymentId) => {
returnfee({ paymentId }).then((res) => {
proxy.$message.success('退费成功');
console.log(res);
});
};
const returnFeeNext = (paymentId) => {
returnFeednext({ paymentId }).then((res) => {
proxy.$message.success('隔天退费成功');
console.log(res);
});
};
const returnFeeResultQuery = (id) => {
returnResult({ id }).then((res) => {
proxy.$message.success(res.data);
console.log(res);
});
};
const handleQuery = () => {
//queryParams.value.pageNum = 1;
getList(queryParams.value);
};
const resetQuery = () => {
proxy.resetForm('queryRef');
handleQuery();
};
const getLists = async () => {
loading.value = true;
getList(queryParams.value).then((res) => {
loading.value = false;
recordList.value = res.data.records;
total.value = res.data.total;
});
};
getLists();
</script>
<style scoped>
.app-continer {
padding: 20px;
}
.el-dialog {
height: 90vh !important;
}
.dialog-footer {
text-align: right;
}
.el-textarea__inner {
resize: none;
}
</style>

View File

@@ -12,16 +12,6 @@
width="100"
/>
<el-table-column label="门诊号" align="center" prop="iptOtpNo" />
<el-table-column label="患者姓名" align="center" prop="patnName" />
<el-table-column label="身份证号" align="center" prop="certno" />
<el-table-column label="诊断名" align="center" prop="conditionName" />
<el-table-column
label="慢性诊断名"
align="center"
prop="specialConditionName"
width="180"
/>
<el-table-column label="请求数量" align="center" prop="quantity" />
<el-table-column label="请求单位" align="center" prop="unitCode" />
<el-table-column label="审核状态" align="center" prop="statusEnum_enumText" />
@@ -48,7 +38,8 @@
<el-table-column label="给药间隔" align="center" prop="dispenseInterval" />
<el-table-column label="单次发药数" align="center" prop="dispensePerQuantity" />
<el-table-column label="每次发药供应天数" align="center" prop="dispensePerDuration" />
<el-table-column label="患者姓名" align="center" prop="patnName" />
<el-table-column label="身份证号" align="center" prop="certno" />
<el-table-column label="开方医生名" align="center" prop="practitionerName" />
<el-table-column label="挂号科室" align="center" prop="mdtrtDeptName" />
<el-table-column label="开单科室" align="center" prop="prscDeptName" />
@@ -62,6 +53,7 @@
{{ formatDate(scope.row.prscTime) }}
</template>
</el-table-column>
<el-table-column label="诊断名" align="center" prop="conditionName" />
</el-table>
<!-- <pagination
v-show="total > 0"

View File

@@ -8,73 +8,32 @@
</div>
</template>
<div style="width: 100%">
<el-input
v-model="queryParams.searchKey"
placeholder="搜索患者"
style="width: 48%; margin-bottom: 10px; margin-right: 15px"
@keyup.enter="getEncounterList"
>
<el-input v-model="queryParams.searchKey" placeholder="搜索患者"
style="width: 48%; margin-bottom: 10px; margin-right: 15px" @keyup.enter="getEncounterList">
<template #append>
<el-button icon="Search" @click="getEncounterList" />
</template>
</el-input>
<el-select
v-model="queryParams.refundEnum"
style="width: 48%; margin-bottom: 10px"
placeholder="收费状态"
@change="getEncounterList"
>
<el-option
v-for="item in statusOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
<el-select v-model="queryParams.refundEnum" style="width: 48%; margin-bottom: 10px" placeholder="收费状态"
@change="getEncounterList">
<el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-date-picker
v-model="dateRange"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
style="width: 85%; margin-bottom: 10px"
value-format="YYYY-MM-DD"
placement="bottom"
@change="getEncounterList"
/>
<el-button
type="primary"
@click="getEncounterList"
style="margin-bottom: 10px; margin-left: 18px"
>
<el-date-picker v-model="dateRange" type="daterange" start-placeholder="开始日期" end-placeholder="结束日期"
style="width: 85%; margin-bottom: 10px" value-format="YYYY-MM-DD" placement="bottom"
@change="getEncounterList" />
<el-button type="primary" @click="getEncounterList" style="margin-bottom: 10px; margin-left: 18px">
搜索
</el-button>
</div>
<el-table
:data="encounterList"
border
style="width: 100%"
height="calc(100vh - 300px)"
highlight-current-row
@cell-click="handleGetReturnDrugList"
>
<el-table-column
prop="patientName"
align="center"
label="姓名"
width="130"
show-overflow-tooltip
/>
<el-table-column
prop="genderEnum_enumText"
align="center"
label="性别"
show-overflow-tooltip
/>
<el-table :data="encounterList" border style="width: 100%" height="calc(100vh - 300px)" highlight-current-row
@cell-click="handleGetReturnDrugList">
<el-table-column prop="patientName" align="center" label="姓名" width="130" show-overflow-tooltip />
<el-table-column prop="genderEnum_enumText" align="center" label="性别" show-overflow-tooltip />
<el-table-column align="center" width="140" label="就诊日期" show-overflow-tooltip>
<template #default="scope">
{{
scope.row.receptionTime ? formatDateStr(scope.row.receptionTime, 'YYYY-MM-DD') : '-'
}}
scope.row.receptionTime ? formatDateStr(scope.row.receptionTime, 'YYYY-MM-DD') : '-'
}}
</template>
</el-table-column>
<!-- <el-table-column label="状态" align="center" prop="refundEnum_enumText" /> -->
@@ -93,35 +52,16 @@
</div>
</template>
<el-button
type="primary"
:disabled="!selectedMedicines.length"
@click="handleReturnDrug(undefined)"
style="margin-bottom: 10px"
>
<el-button type="primary" :disabled="!selectedMedicines.length" @click="handleReturnDrug(undefined)"
style="margin-bottom: 10px">
确认退药
</el-button>
<el-button type="primary" @click="handleScan()" style="margin-bottom: 10px"> 扫码 </el-button>
<el-table
ref="returnDrugRef"
:data="returDrugList"
style="width: 100%"
height="calc(100vh - 300px)"
border
@select="handleSelection"
@selection-change="handelSelectRows"
:span-method="handelSpanMethod"
class="no-hover-table"
>
<el-table-column type="selection" width="55" align="center" />
<el-table ref="returnDrugRef" :data="returDrugList" style="width: 100%" height="calc(100vh - 300px)" border
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column prop="itemName" label="药品名称" show-overflow-tooltip align="center" />
<el-table-column
prop="totalPrice"
label="总价"
width="100"
align="right"
header-align="center"
>
<el-table-column prop="totalPrice" label="总价" width="100" align="right" header-align="center">
<template #default="scope">
{{ scope.row.totalPrice ? scope.row.totalPrice.toFixed(2) + ' 元' : '-' }}
</template>
@@ -134,30 +74,29 @@
</el-table-column>
<el-table-column prop="reqStatus_enumText" label="退药状态" width="100" align="center">
<template #default="scope">
{{ scope.row.refundEnum_enumText }}
{{
scope.row.reqStatus_enumText == null
? scope.row.refundEnum_enumText
: scope.row.reqStatus_enumText
}}
</template>
</el-table-column>
<el-table-column prop="waitingQuantity" label="退药数量" width="100" align="center">
<template #default="scope">
<span>{{
scope.row.quantity
? Math.abs(scope.row.quantity) + ' ' + scope.row.unitCode_dictText
: '0' + ' ' + scope.row.unitCode_dictText
}}</span>
scope.row.quantity
? Math.abs(scope.row.quantity)
: '0' + ' ' + scope.row.unitCode_dictText
}}</span>
</template>
</el-table-column>
<el-table-column prop="doctorName" label="开单医生" align="center" width="180" />
<el-table-column label="操作" width="100" align="center" fixed="right">
<template #default="scope">
<el-popconfirm
width="150"
hide-after="10"
title="操作确认"
placement="top-start"
@confirm="handleReturnDrug(scope.row)"
>
<el-popconfirm width="150" hide-after="10" title="操作确认" placement="top-start"
@confirm="handleReturnDrug(scope.row)">
<template #reference>
<el-button type="primary" link :disabled="scope.row.refundEnum != 16">
<el-button type="primary" link :disabled="scope.row.reqStatus != 11">
退药
</el-button>
</template>
@@ -174,17 +113,13 @@
</div>
</div>
</el-card>
<TraceNoDialog
:ypName="ypName"
:openDialog="openTraceNoDialog"
@submit="submit"
@cancel="openTraceNoDialog = false"
/>
<TraceNoDialog :ypName="ypName" :openDialog="openTraceNoDialog" @submit="submit"
@cancel="openTraceNoDialog = false" />
</div>
</template>
<script setup name="ReturnDrug">
import { getCurrentInstance, nextTick } from 'vue';
import { getCurrentInstance } from 'vue';
import { getList, getReturnDrugList, returnDrug, init, itemTraceNo } from './components/api';
import { formatDateStr } from '@/utils/index';
import { debounce } from 'lodash-es';
@@ -193,7 +128,7 @@ import TraceNoDialog from '@/components/OpenHis/TraceNoDialog/index.vue';
const queryParams = ref({
pageSize: 50,
pageNum: 1,
refundEnum: 16,
refundEnum: 5,
});
const openTraceNo = ref(false);
const traceNoList = ref([]);
@@ -203,10 +138,8 @@ const encounterId = ref('');
const returDrugList = ref([]);
const selectedMedicines = ref([]);
const statusOptions = ref([]);
const dateRange = ref([
formatDateStr(new Date(), 'YYYY-MM-DD'),
formatDateStr(new Date(), 'YYYY-MM-DD'),
]);
const dateRange = ref([formatDateStr(new Date(), 'YYYY-MM-DD'),
formatDateStr(new Date(), 'YYYY-MM-DD'),]);
const traceNoTemp = ref('');
const traceNoTempRef = ref();
const totalAmount = ref(0);
@@ -293,16 +226,14 @@ function handleReturnDrug(row) {
console.log(row);
let saveList = [];
if (row) {
saveList = returDrugList.value
.filter((item) => item.requestId == row.requestId)
.map((item) => {
return {
requestId: item.requestId,
dispenseId: item.dispenseId,
tableName: item.serviceTable,
traceNo: item.traceNo,
};
});
saveList = [
{
requestId: row.requestId,
dispenseId: row.dispenseId,
tableName: row.serviceTable,
traceNo: row.traceNo,
},
];
} else {
saveList = proxy.$refs.returnDrugRef.getSelectionRows().map((item) => {
return {
@@ -317,7 +248,7 @@ function handleReturnDrug(row) {
returnDrug(saveList).then((res) => {
if (res.code === 200) {
proxy.$modal.msgSuccess('退药成功');
getEncounterList();
getEncounterList()
getReturnDrugList({
encounterId: encounterId.value,
refundStatus: queryParams.value.refundEnum,
@@ -328,79 +259,12 @@ function handleReturnDrug(row) {
});
}
// 选择框改变时的处理
function handleSelection(selection, row) {
const isSelected = selection.some((item) => item.dispenseId === row.dispenseId);
returDrugList.value
.filter((item) => {
return item.requestId == row.requestId;
})
.forEach((row) => {
proxy.$refs['returnDrugRef'].toggleRowSelection(row, isSelected);
});
nextTick(() => {
selectedMedicines.value = proxy.$refs['returnDrugRef'].getSelectionRows();
totalAmount.value = selectedMedicines.value.reduce((accumulator, currentRow) => {
return accumulator + (currentRow.totalPrice || 0);
}, 0);
});
}
function handelSelectRows(selection) {
selectedMedicines.value = selection;
totalAmount.value = selectedMedicines.value.reduce((accumulator, currentRow) => {
function handleSelectionChange(selectRows) {
selectedMedicines.value = selectRows;
totalAmount.value = selectRows.reduce((accumulator, currentRow) => {
return accumulator + (currentRow.totalPrice || 0);
}, 0);
}
// 根据 requestId 合并相同行的方法(只合并药品名称和总价列)
function handelSpanMethod({ row, column, rowIndex, columnIndex }) {
// 定义需要合并的列索引
// 1: 药品名称列, 2: 总价列
const mergeColumns = [1, 2, 5, 7, 8];
// 检查当前列是否需要合并
if (!mergeColumns.includes(columnIndex)) {
return [1, 1];
}
// 获取当前行的 requestId
const currentRequestId = row.requestId;
// 如果没有 requestId不进行合并
if (!currentRequestId) {
return [1, 1];
}
// 查找具有相同 requestId 的连续行
let rowspan = 1;
let colspan = 1;
// 向上查找相同 requestId 的行
let startIndex = rowIndex;
while (startIndex > 0 && returDrugList.value[startIndex - 1].requestId === currentRequestId) {
startIndex--;
rowspan++;
}
// 如果当前行不是合并组的第一行,则不显示
if (startIndex !== rowIndex) {
return [0, 0];
}
// 向下查找相同 requestId 的行
let endIndex = rowIndex;
while (
endIndex < returDrugList.value.length - 1 &&
returDrugList.value[endIndex + 1].requestId === currentRequestId
) {
endIndex++;
rowspan++;
}
// 只有当 rowspan > 1 时才进行合并
return rowspan > 1 ? [rowspan, colspan] : [1, 1];
}
</script>
<style lang="scss" scoped>
@@ -475,8 +339,4 @@ function handelSpanMethod({ row, column, rowIndex, columnIndex }) {
::v-deep.el-textarea .el-textarea__inner {
resize: none !important;
}
:deep(.no-hover-table) .el-table__body tr:hover > td {
background: inherit !important;
}
</style>

View File

@@ -1,77 +1,34 @@
import request from '@/utils/request';
import request from '@/utils/request'
/**
* 获取患者列表
*/
export function getList(queryParams) {
export function listSkinRecord(query) {
return request({
url: '/outpatient-manage/treatment/encounter-list',
url: '/outpatient-manage/skin-test/outpatient-record-page',
method: 'get',
params: queryParams,
});
params: query
})
}
/**
* 获取皮试记录列表
*/
export function listSkinRecord(queryParams) {
return request({
url: '/outpatient-manage/skin-test/record-info',
method: 'get',
params: queryParams,
});
}
/**后台没有对应接口,暂无
* 更新护士签名
*/
export function updateNurseSign(data) {
return request({
url: '/outpatient-manage/skin-test/nurse-sign',
method: 'put',
data: data,
});
}
/**
* 更新皮试记录
*/
export function updateSkinTestRecord(data) {
return request({
url: '/outpatient-manage/skin-test/save-record-info',
method: 'post',
data: data,
});
}
/**
* 初始化选项
*/
export function lists() {
return request({
url: '/outpatient-manage/skin-test/init',
method: 'get',
});
})
}
/**
* 获取护士列表
*/
export function getNurseList(queryParams) {
return request({
url: '/app-common/nurse-list',
method: 'get',
params: queryParams,
});
}
/**
* 新增皮试记录
*/
export function addSkinTestRecord(data) {
return request({
url: '/outpatient-manage/skin-test/save-record-info',
method: 'post',
data: data,
});
}
export function updateSkinTestRecord(data) {
return request({
url: '/outpatient-manage/skin-test/outpatient-record-skin-test',
method: 'put',
data: data
})
}
export function updateNurseSign(data) {
return request({
url: '/outpatient-manage/skin-test/outpatient-record-sign-check',
method: 'put',
data: data
})
}

File diff suppressed because it is too large Load Diff

View File

@@ -101,9 +101,9 @@
>
<el-option
v-for="item in diagnosisListOption"
:key="item.definitionId"
:label="item.name + '--' + item.ybNo"
:value="item.definitionId"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
@@ -432,7 +432,7 @@ import { computed, onMounted, ref } from 'vue';
import { reactive } from 'vue';
// import { useModal, useDict } from '@/hooks';
import { parseTime, formatNumber } from '@/utils/his';
import { queryYbCatalogue, getDiagnosisListEle } from './api';
import { queryYbCatalogue, getDiagnosisList } from './api';
import { debounce } from 'lodash-es';
import {
@@ -565,7 +565,7 @@ const unitMap = ref({
function getInit(searchKey) {
if(searchKey) {
getDiagnosisListEle(searchKey,infoForm.encounterId).then(res => {
getDiagnosisList(searchKey).then(res => {
diagnosisListOption.value = res.data
})
}

View File

@@ -150,12 +150,12 @@
</el-col>
<el-col :span="12">
<el-form-item label="入院诊断" prop="diagnosisDefinitionId">
<!-- <el-select
<el-select
v-model="submitForm.diagnosisDefinitionId"
placeholder="诊断"
clearable
filterable
remote
remote
:remote-method="getDiagnosisInfo"
style="width: 400px"
>
@@ -166,10 +166,7 @@
:value="item.id"
@click="handleDiagnosisChange(item)"
/>
</el-select> -->
<el-input v-model="props.mainDiagnosis.name" disabled style="width: 400px" />
<!-- 隐藏存储ID的字段 -->
<input type="hidden" v-model="submitForm.diagnosisDefinitionId" />
</el-select>
</el-form-item>
</el-col>
</el-row>
@@ -182,7 +179,7 @@
</template>
</el-dialog>
</template>
<script setup>
import {
getInit,
@@ -209,7 +206,6 @@ const props = defineProps({
type: String,
default: '',
},
mainDiagnosis: { type: Object, default: null },
});
const emit = defineEmits(['close']);
@@ -248,17 +244,9 @@ const rules = reactive({
});
function openDialog() {
console.log('orgId==========>', props.patientInfo.orgId);
getOrgList().then((res) => {
// organization.value = res.data.records;
organization.value = res.data.records[0].children.filter(
(record) => record.typeEnum === 2 && record.classEnum === 2
);
console.log('organization==========>', organization.value);
submitForm.inHospitalOrgId =
organization.value.find((item) => item.id === props.patientInfo.orgId)?.id || '';
organization.value = res.data.records;
});
// wardList().then((res) => {
// wardListOptions.value = res.data;
// });
@@ -268,14 +256,6 @@ function openDialog() {
});
console.log(props.patientInfo, 'patientInfo');
getDiagnosisInfo(undefined);
console.log(props.mainDiagnosis, 'mainDiagnosis');
if (props.mainDiagnosis) {
submitForm.diagnosisDefinitionId = props.mainDiagnosis.definitionId;
diagnosisDefinitionId = props.mainDiagnosis.definitionId;
diagnosisYbNo = props.mainDiagnosis.ybNo || '';
submitForm.medTypeCode = props.mainDiagnosis.medTypeCode;
diagnosisDefinitionList.value = [props.mainDiagnosis];
}
}
function getDiagnosisInfo(value) {
@@ -353,4 +333,4 @@ function close() {
.patInfo-value {
width: 100px;
}
</style>
</style>

View File

@@ -1,195 +0,0 @@
<!-- consumableDialog.vue -->
<template>
<el-dialog
v-model="dialogVisible"
title="皮试检查"
width="700px"
:close-on-click-modal="false"
:before-close="handleClose"
>
<div class="consumable-dialog">
<div class="dialog-header">
<el-alert
title="下列药品需要执行皮试项目,请确认,点击确定将自动添加皮试检查项目到医嘱列表"
type="warning"
show-icon
:closable="false"
/>
</div>
<div class="table-container">
<el-table
ref="consumableTableRef"
:data="consumableList"
row-key="orderDefinitionId"
border
style="width: 100%"
>
<el-table-column type="selection" width="50" align="center" />
<el-table-column prop="adviceName" align="center" label="项目名称" />
<el-table-column prop="unitCodeName" label="单位" align="center" width="80">
<template #default="scope">
{{ scope.row.unitCodeName || '-' }}
</template>
</el-table-column>
<el-table-column label="执行次数" align="center" width="120">
<template #default="scope">
{{ '1' }}
</template>
</el-table-column>
<el-table-column label="操作" width="80" align="center" fixed="right">
<template #default="scope">
<el-button type="danger" link size="small" @click="handleDeleteRow(scope.row)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<!-- 下次不再提示复选框 -->
<div class="dont-show-again">
<!-- <el-checkbox v-model="dontShowAgain" @change="handleDontShowAgainChange">
下次不再提示
</el-checkbox> -->
</div>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="handleClose">取消</el-button>
<el-button ref="submitRef" type="primary" @click="handleSubmit">确定</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
import { ElMessageBox, ElMessage } from 'element-plus';
import { ref, nextTick, onBeforeUnmount } from 'vue';
import useUserStore from '@/store/modules/user';
const dialogVisible = ref(false);
const consumableList = ref([]);
const consumableTableRef = ref();
const submitRef = ref();
const dontShowAgain = ref(false); // 下次不再提示的状态
const userStore = useUserStore();
// 定义事件
const emit = defineEmits(['submit']);
// 键盘事件处理函数
const handleKeyDown = (event) => {
// 检查是否按下了回车键
if (event.key === 'Enter' && dialogVisible.value) {
event.preventDefault();
handleSubmit();
}
};
// 打开弹窗方法
const open = (data) => {
consumableList.value = data;
dialogVisible.value = true;
// 默认全选
nextTick(() => {
if (consumableTableRef.value) {
consumableList.value.forEach((row) => {
consumableTableRef.value.toggleRowSelection(row, true);
});
}
// 注册键盘事件监听器
document.addEventListener('keydown', handleKeyDown);
});
};
// 关闭弹窗方法
const handleClose = () => {
// 移除键盘事件监听器
document.removeEventListener('keydown', handleKeyDown);
dialogVisible.value = false;
consumableList.value = [];
};
// 页面卸载前清理事件监听器
onBeforeUnmount(() => {
document.removeEventListener('keydown', handleKeyDown);
});
// 删除行处理
const handleDeleteRow = (row) => {
ElMessageBox.confirm(`确定要删除 "${row.orderDefinitionName}" 吗?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
const index = consumableList.value.findIndex(
(item) => item.orderDefinitionId === row.orderDefinitionId
);
if (index > -1) {
consumableList.value.splice(index, 1);
}
});
};
// 提交处理
const handleSubmit = () => {
const selectedRows = consumableTableRef.value.getSelectionRows();
// 保存到本地存储
// localStorage.setItem('doctor' + userStore.id.toString(), dontShowAgain.value);
if (selectedRows.length === 0) {
ElMessage.warning('请至少选择一项');
return;
}
// 发送事件给父组件
emit('submit', selectedRows);
// 关闭弹窗并清理事件监听器
document.removeEventListener('keydown', handleKeyDown);
dialogVisible.value = false;
consumableList.value = [];
};
// 暴露方法给父组件
defineExpose({
open,
close: handleClose,
});
</script>
<style lang="scss" scoped>
.consumable-dialog {
.dialog-header {
margin-bottom: 20px;
}
.table-container {
margin-bottom: 20px;
}
.dont-show-again {
margin-top: 10px;
text-align: left;
}
.dialog-footer-summary {
text-align: right;
.summary-text {
font-size: 14px;
color: #606266;
.total-amount {
font-size: 16px;
font-weight: bold;
color: #e64545;
}
}
}
}
.dialog-footer {
display: flex;
justify-content: flex-end;
align-items: center;
}
</style>

View File

@@ -1,243 +0,0 @@
<template>
<div class="report-container">
<div class="report-section">
<div class="report-title">
<span>检查报告</span>
<el-icon
class="report-refresh-icon"
:class="{ 'is-loading': loadingCheck }"
@click="handleRefreshCheck"
>
<Refresh />
</el-icon>
</div>
<div class="report-table-wrapper">
<el-table
v-loading="loadingCheck"
:data="checkReportList"
border
size="small"
height="100%"
style="width: 100%"
>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="adviceName" label="报告名称" width="140" />
<el-table-column prop="reportNo" label="报告号" width="140" />
<el-table-column label="链接" min-width="140">
<template #default="scope">
<a
v-if="scope.row.requestUrl"
class="report-link"
:href="scope.row.requestUrl"
target="_blank"
rel="noopener noreferrer"
>
查看报告
</a>
<span v-else class="report-link-disabled">暂无链接</span>
</template>
</el-table-column>
</el-table>
</div>
</div>
<div class="report-section">
<div class="report-title">
<span>检验报告</span>
<el-icon
class="report-refresh-icon"
:class="{ 'is-loading': loadingInspection }"
@click="handleRefreshInspection"
>
<Refresh />
</el-icon>
</div>
<div class="report-table-wrapper">
<el-table
v-loading="loadingInspection"
:data="inspectionReportList"
border
size="small"
height="100%"
style="width: 100%"
>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="adviceName" label="报告名称" width="140" />
<el-table-column prop="reportNo" label="报告号" width="140" />
<el-table-column label="链接" min-width="140">
<template #default="scope">
<a
v-if="scope.row.requestUrl"
class="report-link"
:href="scope.row.requestUrl"
target="_blank"
rel="noopener noreferrer"
>
查看报告
</a>
<span v-else class="report-link-disabled">暂无链接</span>
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
</template>
<script setup>
import { getCurrentInstance, ref, watch } from 'vue';
import { Refresh } from '@element-plus/icons-vue';
import { getProofResult, getTestResult } from './api';
const { proxy } = getCurrentInstance();
const props = defineProps({
patientInfo: {
type: Object,
required: true,
},
});
const checkReportList = ref([]);
const inspectionReportList = ref([]);
const loadingCheck = ref(false);
const loadingInspection = ref(false);
const fetchCheckReport = async () => {
if (!props.patientInfo?.encounterId) return;
const res = await getTestResult({ encounterId: props.patientInfo.encounterId });
if (res.code === 200 && res.data) {
const raw = res.data?.records || res.data;
const list = Array.isArray(raw) ? raw : [raw];
checkReportList.value = list.filter(Boolean).map((item) => ({
reportNo: item.busNo,
requestUrl: item.requestUrl,
adviceName: item.adviceName,
_raw: item,
}));
} else {
checkReportList.value = [];
}
};
const fetchInspectionReport = async () => {
if (!props.patientInfo?.encounterId) return;
const res = await getProofResult({ encounterId: props.patientInfo.encounterId });
if (res.code === 200 && res.data) {
const raw = res.data?.records || res.data;
const list = Array.isArray(raw) ? raw : [raw];
inspectionReportList.value = list.filter(Boolean).map((item) => ({
reportNo: item.busNo,
requestUrl: item.requestUrl,
adviceName: item.adviceName,
_raw: item,
}));
} else {
inspectionReportList.value = [];
}
};
const fetchAll = async () => {
if (!props.patientInfo?.encounterId) {
checkReportList.value = [];
inspectionReportList.value = [];
loadingCheck.value = false;
loadingInspection.value = false;
return;
}
loadingCheck.value = true;
loadingInspection.value = true;
try {
await Promise.all([fetchCheckReport(), fetchInspectionReport()]);
} catch (e) {
proxy.$modal?.msgError?.(e.message || '查询报告失败');
} finally {
loadingCheck.value = false;
loadingInspection.value = false;
}
};
const handleRefreshCheck = async () => {
if (loadingCheck.value || !props.patientInfo?.encounterId) return;
loadingCheck.value = true;
try {
await fetchCheckReport();
} finally {
loadingCheck.value = false;
}
};
const handleRefreshInspection = async () => {
if (loadingInspection.value || !props.patientInfo?.encounterId) return;
loadingInspection.value = true;
try {
await fetchInspectionReport();
} finally {
loadingInspection.value = false;
}
};
watch(
() => props.patientInfo?.encounterId,
(val) => {
if (val) {
fetchAll();
} else {
checkReportList.value = [];
inspectionReportList.value = [];
}
},
{ immediate: true }
);
</script>
<style scoped lang="scss">
.report-container {
display: flex;
flex-direction: column;
gap: 12px;
padding: 8px 0;
height: 100%;
}
.report-section {
background: #fff;
flex: 1;
max-height: 55%;
min-height: 0;
display: flex;
flex-direction: column;
}
.report-title {
font-weight: 600;
margin-bottom: 8px;
display: flex;
align-items: center;
justify-content: space-between;
}
.report-table-wrapper {
flex: 1;
min-height: 0;
overflow: auto;
}
.report-refresh-icon {
cursor: pointer;
color: #909399;
transition: color 0.2s;
}
.report-refresh-icon:hover {
color: #409eff;
}
.report-link {
color: #409eff;
cursor: pointer;
text-decoration: underline;
}
.report-link-disabled {
color: #c0c4cc;
}
</style>

View File

@@ -1,259 +0,0 @@
const formData = reactive({
//医院信息
hospitalInfo: {
//组织机构代码
medins_orgcode: '',
//医疗付款方式
medfee_paymtd_code: '',
},
//患者信息
patientInfo: {
// 健康卡号
healthCardNo: '',
// 患者姓名
patient_name: '',
// 患者性别
gend: '',
// 出生日期
brdy: '',
// 年龄
age: '',
// 国籍
ntly: '中国',
// 籍贯
napl: '',
// 民族
naty: '1',
// 身份证号
certno: '',
// 户口住址
resd_addr: '',
// 工作单位地址
empr_addr: '',
// 联系人姓名
coner_name: '',
// 关系
coner_rlts_code: '',
// 联系人地址
coner_addr: '',
// 联系人电话
coner_tel: '',
},
// 住院信息
admission: {
// 第几次住院
patn_ipt_cnt: 1,
// 住院号
ipt_no: '',
// 病案号
medcasno: '',
// 入院途径
adm_way_code: '',
// 入院时间
adm_time: '',
// 入院科室
adm_dept_name: '',
// 病房
adm_ward: '',
// 确诊日期
adm_date: '',
// 出院时间
dscg_date: '',
// 出院科室
dscg_caty: '',
// 病房
dscg_ward: '',
// 实际住院天数
act_ipt_days: '',
},
// 诊断信息
diagnosis: {
// 主要诊断
mainDiagnosis: '',
// 其他诊断
otherDiagnosis: '',
},
// 诊断信息
diagnosisList: [],
// 医疗信息
medicalInfo: {
// 是否输血
bloodTransfusion: '',
// 血型
abo_code: '',
// rh类型
rh_code: '',
// 药物过敏史
die_autp_flag: '',
},
// 医师信息
doctorInfo: {
// 科主任
deptdrt_name: '',
// 副主任
chfdr_name: '',
// 主治医师
chfpdr_name: '',
// 住院医师
ipt_dr_name: '',
// 责任护士
resp_nurs_name: '',
// 住院总医师
chiefResident: '',
// 实习医师
intn_dr_name: '',
// 病案质量
medcas_qlt_code: '',
// 编码员
codr_name: '',
// 控制日期
qltctrl_date: '',
},
// 病案首页2
medicalSecond: {
// 手术方式
surgeryType: '',
// 离院方式
dscg_way: '',
// 31天是否计划出院
dscg_31days_rinp_flag: '',
// 目的
dscg_31days_rinp_pup: '',
//昏迷时间---入院前
brn_damg_bfadm_coma_dura: '',
//昏迷时间---入院后
brn_damg_afadm_coma_dura: '',
// 肿瘤分期
tumorStaging: '',
// T
tumor_T: '',
// N
tumor_N: '',
// M
tumor_M: '',
// 判断依据
judgmentBase: '',
// 分化程度
bkup_deg_code: '',
// 临床路径
enterPath: '',
// 变异
mutation: '',
// 退出路径
outPath: '',
// 特级护理
nursingLevel_spec: '',
// 1级护理
nursingLevel_1: '',
// 2级护理
nursingLevel_2: '',
// 3级护理
nursingLevel_3: '',
// 呼吸机使用
use_vent_flag: '',
// 有创呼吸机使用小时
vent_used_dura: '',
// 手术表
surgery_tableData: [],
},
// 病案首页3
// 住院费用
hospitalization: {
// 总费用
medfee_sumamt: '',
// 自付金额
selfpay_amt: '',
},
// 综合医疗服务类
medicalServices: {
// 一般医疗服务类
ordn_med_servfee: '',
// 一般治疗操作费
ordn_trt_oprt_fee: '',
// 护理费
nurs_fee: '',
// 其他费用
com_med_serv_oth_fee: '',
},
// 诊断类
diagnosisClass: {
// 病理诊断
palg_diag_fee: '',
// 实验室诊断
lab_diag_fee: '',
// 影像学诊断
rdhy_diag_fee: '',
// 临床诊断
clnc_dise_fee: '',
},
// 治疗类
treatmentClass: {
// 非手术治疗项目费
nsrgtrt_item_fee: '',
// 临床物理治疗
clnc_phys_trt_fee: '',
// 手术治疗费
rgtrt_trt_fee: '',
// 麻醉费
anst_fee: '',
// 手术费
rgtrt_fee: '',
},
// 康复类
recoveryClass: {
// 康复费
rhab_fee: '',
},
// 中医类
TCMClass: {
// 中医治疗费
tcm_trt_fee: '',
},
// 西药类
WesternClass: {
// 西药费
wm_fee: '',
// 抗菌药物费
abtl_medn_fee: '',
},
// 中药类
chineseClass: {
//中成药
tcmpat_fee: '',
// 中草药
tcmherb_fee: '',
},
// 血液和血液制品类
bloodClass: {
// 血费
blo_fee: '',
// 蛋白类制品费
albu_fee: '',
// 球蛋白制品费
glon_fee: '',
// 凝血因子制品费
clotfac_fee: '',
// 细胞因子制品费
cyki_fee: '',
},
// 耗材类
consumablesClass: {
// 检查用一次性医用材料费
exam_dspo_matl_fee: '',
// 治疗用一次性医用材料费
trt_dspo_matl_fee: '',
// 手术用一次性医用材料费
oprn_dspo_matl_fee: '',
},
// 其他类
otherClass: {
// 其他费用
oth_fee: '',
},
// 其他诊断及手术附加页
other_tableData: [],
// 手术操作数组
surgery_tableData: [],
});
export default formData;

View File

@@ -1,256 +0,0 @@
<template>
<div class="med-summary-container">
<div style="width: 40%">
<el-card style="height: 80vh">
<template #header>
{{ '汇总单' }}
</template>
<div style="display: flex; justify-content: space-between; margin-bottom: 10px">
<div>
<el-input style="width: 250px" v-model="queryParams.searchKey" placeholder="单据号">
<template #append>
<el-button icon="Search" @click="getSummaryList" />
</template>
</el-input>
<el-select
placeholder="发放状态"
style="width: 250px; margin-left: 10px"
v-model="queryParams.statusEnum"
@change="getSummaryList"
>
<el-option
v-for="item in statusEnumOptions"
:key="item.value"
:value="item.value"
:label="item.label"
/>
</el-select>
</div>
</div>
<div style="display: flex; justify-content: space-between; margin-bottom: 10px">
<div>
<el-date-picker
v-model="queryParams.applyTime"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
style="width: 510px"
value-format="YYYY-MM-DD"
:clearable="false"
@change="getSummaryList"
/>
</div>
<div>
<el-button type="primary" plain @click="handleSend">批量发药</el-button>
<el-button type="warning" plain>批量作废</el-button>
</div>
</div>
<el-table
:data="summaryList"
max-height="85vh"
border
ref="summaryTableRef"
highlight-current-row
@row-click="getDetails"
>
<el-table-column type="selection" align="center" width="50" />
<el-table-column prop="busNo" label="单据号" align="center" width="150" />
<el-table-column prop="applicantName" label="申请人" align="center" width="100" />
<el-table-column prop="locationName" label="发药药房" align="center" />
<el-table-column prop="statusEnum_enumText" label="状态" align="center" />
<el-table-column prop="applyTime" label="汇总日期" align="center" width="140">
<template #default="scope">
{{ scope.row.applyTime ? parseTime(scope.row.applyTime, '{y}-{m}-{d}') : '-' }}
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button type="primary" link @click="handleSend(scope.row)">发药</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
</div>
<!-- <el-row :gutter="10" justify="end" align="middle" style="margin-bottom: 10px">
<el-button type="danger" plain icon="Refresh" @click="handleSendDrug" :disabled="!busNo">
发药
</el-button>
<el-button type="primary" plain icon="Download" @click="handleExport" :disabled="!busNo">
导出
</el-button>
</el-row> -->
<div style="width: 59%">
<el-card style="height: 80vh">
<template #header>
{{ '汇总单详情' }}
</template>
<el-table
:data="summaryDetailsData"
style="width: 100%"
border
v-loading="loading"
:cell-style="{ textAlign: 'center' }"
>
<el-table-column type="index" label="序号" min-width="50" />
<el-table-column prop="itemName" label="项目名称" min-width="150">
<template #default="scope">
{{ scope.row.itemName || '-' }}
</template>
</el-table-column>
<el-table-column prop="totalVolume" label="规格" min-width="120">
<template #default="scope">
{{ scope.row.totalVolume || '-' }}
</template>
</el-table-column>
<el-table-column prop="lotNumber" label="批次号" min-width="100">
<template #default="scope">
{{ scope.row.lotNumber || '-' }}
</template>
</el-table-column>
<el-table-column prop="quantity" label="数量" min-width="80" align="center">
<template #default="scope">
{{ scope.row.itemQuantity + ' ' + scope.row.minUnitCode_dictText }}
</template>
</el-table-column>
<el-table-column prop="categoryCode_dictText" label="药品类型" min-width="100">
<template #default="scope">
{{ scope.row.categoryCode_dictText || '-' }}
</template>
</el-table-column>
<el-table-column
prop="manufacturerText"
label="生产厂家"
min-width="120"
:show-overflow-tooltip="true"
>
<template #default="scope">
{{ scope.row.manufacturerText || '-' }}
</template>
</el-table-column>
</el-table>
</el-card>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
import {
totalSendDrug,
getFromSummaryList,
getFromSummaryDetails,
getFromSummaryInit,
} from './api.js';
import { getCurrentInstance } from 'vue';
const { proxy } = getCurrentInstance();
const statusEnumOptions = ref([]);
const summaryList = ref([]);
const queryParams = ref({
applyTime: [
proxy.formatDateStr(new Date().setMonth(new Date().getMonth() - 1), 'YYYY-MM-DD'),
proxy.formatDateStr(new Date(), 'YYYY-MM-DD'),
],
});
// 定义组件属性
const props = defineProps({
tableData: {
type: Array,
default: () => [],
},
selectedId: {
type: String,
default: '',
},
busNo: {
type: String,
default: '',
},
});
const selectedRows = ref([]);
const summaryDetailsData = ref([]);
// 定义loading状态
const loading = ref(false);
getSummaryList();
// 获取汇总单信息
function getSummaryList() {
queryParams.value.applyTimeSTime = queryParams.value.applyTime[0] + ' 00:00:00';
queryParams.value.applyTimeETime = queryParams.value.applyTime[1] + ' 23:59:59';
getFromSummaryList(queryParams.value).then((res) => {
summaryList.value = res.data.records;
});
}
function getDetails(row) {
loading.value = true;
getFromSummaryDetails({ summaryNo: row.busNo }).then((res) => {
summaryDetailsData.value = res.data;
loading.value = false;
});
}
// 发药
function handleSend(row) {
let sendList = [];
if (row.busNo) {
sendList.push(row.busNo);
} else {
proxy.$refs['summaryTableRef'].getSelectionRows().forEach((item) => {
sendList.push(item.busNo);
});
}
console.log(sendList);
totalSendDrug(sendList).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('操作成功');
getSummaryList();
}
});
}
// 获取发药状态
const getStatusOption = async () => {
try {
const res = await getFromSummaryInit();
statusEnumOptions.value = res.data.dispenseStatusOptions;
} catch (error) {}
};
getStatusOption();
// 定义暴露给父组件的数据和方法
defineExpose({
selectedRows,
});
</script>
<style lang="scss" scoped>
.med-summary-container {
height: 100%;
display: flex;
justify-content: space-between;
}
.medicationTableDetail {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
.buttonGroup {
display: flex;
justify-content: flex-end;
padding: 10px 0;
gap: 10px;
margin-right: 20px;
:deep(.el-button) {
padding: 6px 16px;
font-size: 14px;
}
}
}
</style>

View File

@@ -1,481 +0,0 @@
<template>
<div class="container">
<!-- 左侧患者列表 -->
<el-card class="patient-list">
<template #header>
<div class="card-header">
<span>患者列表</span>
</div>
</template>
<div style="width: 100%">
<el-input
v-model="queryParams.searchKey"
placeholder="搜索患者"
style="width: 48%; margin-bottom: 10px; margin-right: 15px"
@keyup.enter="getEncounterList"
>
<template #append>
<el-button icon="Search" @click="getEncounterList" />
</template>
</el-input>
<el-select
v-model="queryParams.refundEnum"
style="width: 48%; margin-bottom: 10px"
placeholder="收费状态"
@change="getEncounterList"
>
<el-option
v-for="item in statusOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-date-picker
v-model="dateRange"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
style="width: 85%; margin-bottom: 10px"
value-format="YYYY-MM-DD"
placement="bottom"
@change="getEncounterList"
/>
<el-button
type="primary"
@click="getEncounterList"
style="margin-bottom: 10px; margin-left: 18px"
>
搜索
</el-button>
</div>
<el-table
:data="encounterList"
border
style="width: 100%"
height="calc(100vh - 300px)"
highlight-current-row
@cell-click="handleGetReturnDrugList"
>
<el-table-column
prop="patientName"
align="center"
label="姓名"
width="130"
show-overflow-tooltip
/>
<el-table-column
prop="genderEnum_enumText"
align="center"
label="性别"
show-overflow-tooltip
/>
<el-table-column align="center" width="140" label="就诊日期" show-overflow-tooltip>
<template #default="scope">
{{
scope.row.receptionTime ? formatDateStr(scope.row.receptionTime, 'YYYY-MM-DD') : '-'
}}
</template>
</el-table-column>
<!-- <el-table-column label="状态" align="center" prop="refundEnum_enumText" /> -->
</el-table>
</el-card>
<!-- 右侧退药列表 -->
<el-card class="refund-list">
<template #header>
<div class="card-header">
<span>退药单</span>
<!-- <div v-if="selectedPatient">
<span class="patient-info">{{ selectedPatient.name }}</span>
<el-tag type="info">{{ selectedPatient.visitNo }}</el-tag>
</div> -->
</div>
</template>
<el-button
type="primary"
:disabled="!selectedMedicines.length"
@click="handleReturnDrug(undefined)"
style="margin-bottom: 10px"
>
确认退药
</el-button>
<el-button type="primary" @click="handleScan()" style="margin-bottom: 10px"> 扫码 </el-button>
<el-table
ref="returnDrugRef"
:data="returDrugList"
style="width: 100%"
height="calc(100vh - 300px)"
border
@select="handleSelection"
@selection-change="handelSelectRows"
:span-method="handelSpanMethod"
class="no-hover-table"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column prop="itemName" label="药品名称" show-overflow-tooltip align="center" />
<el-table-column
prop="totalPrice"
label="总价"
width="100"
align="right"
header-align="center"
>
<template #default="scope">
{{ scope.row.totalPrice ? scope.row.totalPrice.toFixed(2) + ' 元' : '-' }}
</template>
</el-table-column>
<el-table-column prop="lotNumber" label="批号" width="180" align="center" />
<el-table-column prop="traceNo" label="追溯码" width="180" align="center">
<template #default="scope">
<el-input v-model="scope.row.traceNo" placeholder="请输入追溯码" />
</template>
</el-table-column>
<el-table-column prop="reqStatus_enumText" label="退药状态" width="100" align="center">
<template #default="scope">
{{ scope.row.refundEnum_enumText }}
</template>
</el-table-column>
<el-table-column prop="waitingQuantity" label="退药数量" width="100" align="center">
<template #default="scope">
<span>{{
scope.row.quantity
? Math.abs(scope.row.quantity) + ' ' + scope.row.unitCode_dictText
: '0' + ' ' + scope.row.unitCode_dictText
}}</span>
</template>
</el-table-column>
<el-table-column prop="doctorName" label="开单医生" align="center" width="180" />
<el-table-column label="操作" width="100" align="center" fixed="right">
<template #default="scope">
<el-popconfirm
width="150"
hide-after="10"
title="操作确认"
placement="top-start"
@confirm="handleReturnDrug(scope.row)"
>
<template #reference>
<el-button type="primary" link :disabled="scope.row.refundEnum != 16">
退药
</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<!-- 底部操作栏 -->
<div class="footer">
<div class="statistics">
<span>已选 {{ selectedMedicines.length }} 种药品</span>
<span class="total">合计金额¥ {{ totalAmount.toFixed(2) }}</span>
</div>
</div>
</el-card>
<TraceNoDialog
:ypName="ypName"
:openDialog="openTraceNoDialog"
@submit="submit"
@cancel="openTraceNoDialog = false"
/>
</div>
</template>
<script setup name="ReturnDrug">
import { getCurrentInstance, nextTick } from 'vue';
import { getList, getReturnDrugList, returnDrug, init, itemTraceNo } from './api';
import { formatDateStr } from '@/utils/index';
import { debounce } from 'lodash-es';
import TraceNoDialog from '@/components/OpenHis/TraceNoDialog/index.vue';
const queryParams = ref({
pageSize: 50,
pageNum: 1,
refundEnum: 16,
classEnum: 1,
});
const openTraceNo = ref(false);
const traceNoList = ref([]);
const traceNo = ref('');
const encounterList = ref([]);
const encounterId = ref('');
const returDrugList = ref([]);
const selectedMedicines = ref([]);
const statusOptions = ref([]);
const dateRange = ref([
formatDateStr(new Date(), 'YYYY-MM-DD'),
formatDateStr(new Date(), 'YYYY-MM-DD'),
]);
const traceNoTemp = ref('');
const traceNoTempRef = ref();
const totalAmount = ref(0);
const openTraceNoDialog = ref(false);
const ypName = ref('');
const { proxy } = getCurrentInstance();
getEncounterList();
function getEncounterList() {
queryParams.value.startTimeSTime = dateRange.value[0] + ' 00:00:00';
queryParams.value.startTimeETime = dateRange.value[1] + ' 23:59:59';
getList(queryParams.value).then((res) => {
encounterList.value = res.data.records;
});
}
initOptions();
function initOptions() {
init().then((res) => {
statusOptions.value = res.data.refundStatusOptions;
});
}
function handleGetReturnDrugList(row) {
encounterId.value = row.encounterId;
getReturnDrugList({
encounterId: row.encounterId,
refundStatus: queryParams.value.refundEnum,
}).then((res) => {
returDrugList.value = res.data;
});
}
function handleScan() {
openTraceNoDialog.value = true;
}
function submit(value) {
let list = [];
if (value) {
list = value.split(',');
}
itemTraceNo(list).then((res) => {
if (res.code === 200) {
returDrugList.value.forEach((item, index) => {
if (res.data[item.itemId] && res.data[item.itemId].split(',') > item.quantity) {
proxy.$modal.msgWarning('操作失败');
return;
}
returDrugList.value[index].traceNo = res.data[item.itemId];
});
openTraceNoDialog.value = false;
// proxy.$modal.msgSuccess('退药成功');
// getReturnDrugList(encounterId.value);
}
});
}
const throttledGetList = debounce(handelTraceNo, 500);
let inputValue = '';
function handelTraceNo(value) {
traceNoList.value.push(value);
traceNo.value = traceNo.value + '[' + traceNoList.value.length + ']' + ' ' + value + '\n';
traceNoTemp.value = '';
// let saveValue = value.substring(inputValue.length + 5, value.length);
// inputValue = value;
// console.log(value);
// console.log(saveValue);
// traceNoList.value.push(saveValue);
// traceNo.value = value + '[' + (traceNoList.value.length + 1) + ']' + ' ';
}
function handleClear() {
traceNo.value = '';
traceNoList.value = [];
}
function cancel() {
openTraceNo.value = false;
traceNoList.value = [];
traceNo.value = '';
}
/**
* 退药
*/
function handleReturnDrug(row) {
console.log(row);
let saveList = [];
if (row) {
saveList = returDrugList.value
.filter((item) => item.requestId == row.requestId)
.map((item) => {
return {
requestId: item.requestId,
dispenseId: item.dispenseId,
tableName: item.serviceTable,
traceNo: item.traceNo,
};
});
} else {
saveList = proxy.$refs.returnDrugRef.getSelectionRows().map((item) => {
return {
requestId: item.requestId,
dispenseId: item.dispenseId,
tableName: item.serviceTable,
traceNo: item.traceNo,
};
});
console.log(saveList);
}
returnDrug(saveList).then((res) => {
if (res.code === 200) {
proxy.$modal.msgSuccess('退药成功');
getEncounterList();
getReturnDrugList({
encounterId: encounterId.value,
refundStatus: queryParams.value.refundEnum,
}).then((res) => {
returDrugList.value = res.data;
});
}
});
}
// 选择框改变时的处理
function handleSelection(selection, row) {
const isSelected = selection.some((item) => item.dispenseId === row.dispenseId);
returDrugList.value
.filter((item) => {
return item.requestId == row.requestId;
})
.forEach((row) => {
proxy.$refs['returnDrugRef'].toggleRowSelection(row, isSelected);
});
nextTick(() => {
selectedMedicines.value = proxy.$refs['returnDrugRef'].getSelectionRows();
totalAmount.value = selectedMedicines.value.reduce((accumulator, currentRow) => {
return accumulator + (currentRow.totalPrice || 0);
}, 0);
});
}
function handelSelectRows(selection) {
selectedMedicines.value = selection;
totalAmount.value = selectedMedicines.value.reduce((accumulator, currentRow) => {
return accumulator + (currentRow.totalPrice || 0);
}, 0);
}
// 根据 requestId 合并相同行的方法(只合并药品名称和总价列)
function handelSpanMethod({ row, column, rowIndex, columnIndex }) {
// 定义需要合并的列索引
// 1: 药品名称列, 2: 总价列
const mergeColumns = [1, 2, 5, 7, 8];
// 检查当前列是否需要合并
if (!mergeColumns.includes(columnIndex)) {
return [1, 1];
}
// 获取当前行的 requestId
const currentRequestId = row.requestId;
// 如果没有 requestId不进行合并
if (!currentRequestId) {
return [1, 1];
}
// 查找具有相同 requestId 的连续行
let rowspan = 1;
let colspan = 1;
// 向上查找相同 requestId 的行
let startIndex = rowIndex;
while (startIndex > 0 && returDrugList.value[startIndex - 1].requestId === currentRequestId) {
startIndex--;
rowspan++;
}
// 如果当前行不是合并组的第一行,则不显示
if (startIndex !== rowIndex) {
return [0, 0];
}
// 向下查找相同 requestId 的行
let endIndex = rowIndex;
while (
endIndex < returDrugList.value.length - 1 &&
returDrugList.value[endIndex + 1].requestId === currentRequestId
) {
endIndex++;
rowspan++;
}
// 只有当 rowspan > 1 时才进行合并
return rowspan > 1 ? [rowspan, colspan] : [1, 1];
}
</script>
<style lang="scss" scoped>
.container {
display: flex;
height: 80vh;
gap: 16px;
}
.patient-list {
width: 600px;
flex-shrink: 0;
}
.refund-list {
flex: 1;
}
.patient-item {
padding: 12px;
margin-bottom: 8px;
cursor: pointer;
border-radius: 4px;
transition: all 0.3s;
&:hover {
background-color: #f5f7fa;
}
&.active {
background-color: #ecf5ff;
border-left: 4px solid #409eff;
}
}
.patient-info {
display: flex;
justify-content: space-between;
margin-bottom: 8px;
.name {
font-weight: 500;
}
.visit-no {
color: #666;
font-size: 12px;
}
}
.visit-time {
color: #999;
font-size: 12px;
}
.footer {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px;
border-top: 1px solid #ebeef5;
.total {
margin-left: 20px;
color: #f56c6c;
font-weight: 500;
}
}
::v-deep.el-textarea .el-textarea__inner {
resize: none !important;
}
:deep(.no-hover-table) .el-table__body tr:hover > td {
background: inherit !important;
}
</style>

View File

@@ -1,725 +0,0 @@
<template>
<div style="padding: 20px; max-width: 1200px; margin: 0 auto" ref="bodyRef">
<!-- 标题区域 - 居中加粗增加层次感 -->
<div style="text-align: center; margin-bottom: 30px">
<div style="font-size: 22px; color: #333; letter-spacing: 1px">长春市朝阳区中医院</div>
<div
style="
font-size: 32px;
font-weight: 700;
color: #222;
padding: 12px 0;
border-bottom: 2px solid #333;
display: inline-block;
"
>
入院记录
</div>
<div style="margin-top: 8px; font-size: 14px; color: #666"> 1 1 </div>
</div>
<!-- 基本信息模块 - 卡片式布局优化间距和对齐 -->
<div
style="
border: 1px solid #ddd;
border-radius: 8px;
padding: 25px;
margin-bottom: 25px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.03);
"
>
<div
style="
font-size: 18px;
font-weight: 600;
color: #333;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid #eee;
"
>
基本信息
</div>
<div
style="
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 18px;
"
>
<!-- 第一列 -->
<div>
<div style="display: flex; align-items: flex-start; margin-bottom: 16px">
<span style="font-weight: 500; color: #333; min-width: 80px; font-size: 15px"
>姓名</span
>
<span style="font-size: 14px; color: #666; line-height: 1.5">{{
formData.patientName
}}</span>
</div>
<div style="display: flex; align-items: flex-start; margin-bottom: 16px">
<span style="font-weight: 500; color: #333; min-width: 80px; font-size: 15px"
>性别</span
>
<span style="font-size: 14px; color: #666; line-height: 1.5">{{
formData.gender
}}</span>
</div>
<div style="display: flex; align-items: flex-start; margin-bottom: 16px">
<span style="font-weight: 500; color: #333; min-width: 80px; font-size: 15px"
>民族</span
>
<span style="font-size: 14px; color: #666; line-height: 1.5">{{
formData.nation || '汉族'
}}</span>
</div>
<div style="display: flex; align-items: flex-start; margin-bottom: 16px">
<span style="font-weight: 500; color: #333; min-width: 80px; font-size: 15px"
>婚姻状况</span
>
<span style="font-size: 14px; color: #666; line-height: 1.5">{{
formData.marriage || ''
}}</span>
</div>
<div style="display: flex; align-items: flex-start; margin-bottom: 16px">
<span style="font-weight: 500; color: #333; min-width: 80px; font-size: 15px"
>入院时间</span
>
<span style="font-size: 14px; color: #666; line-height: 1.5">{{
formData.admissionTime || ''
}}</span>
</div>
<div style="display: flex; align-items: flex-start">
<span style="font-weight: 500; color: #333; min-width: 80px; font-size: 15px"
>病史陈述</span
>
<span style="font-size: 14px; color: #666; line-height: 1.5">{{
formData.historyReporter || ''
}}</span>
</div>
</div>
<!-- 第二列 -->
<div>
<div style="display: flex; align-items: flex-start; margin-bottom: 16px">
<span style="font-weight: 500; color: #333; min-width: 80px; font-size: 15px"
>住院号</span
>
<span style="font-size: 14px; color: #666; line-height: 1.5">{{
formData.hospitalNo || '123456'
}}</span>
</div>
<div style="display: flex; align-items: flex-start; margin-bottom: 16px">
<span style="font-weight: 500; color: #333; min-width: 80px; font-size: 15px"
>年龄</span
>
<span style="font-size: 14px; color: #666; line-height: 1.5">{{
formData.age || '16 岁'
}}</span>
</div>
<div style="display: flex; align-items: flex-start; margin-bottom: 16px">
<span style="font-weight: 500; color: #333; min-width: 80px; font-size: 15px"
>职业</span
>
<span style="font-size: 14px; color: #666; line-height: 1.5">{{
formData.occupation || '中医'
}}</span>
</div>
<div style="display: flex; align-items: flex-start; margin-bottom: 16px">
<span style="font-weight: 500; color: #333; min-width: 80px; font-size: 15px"
>出生地</span
>
<span style="font-size: 14px; color: #666; line-height: 1.5">{{
formData.birthplace || '阿拉善'
}}</span>
</div>
<div style="display: flex; align-items: flex-start; margin-bottom: 16px">
<span style="font-weight: 500; color: #333; min-width: 80px; font-size: 15px"
>记录时间</span
>
<span style="font-size: 14px; color: #666; line-height: 1.5">{{
formData.recordTime || '2025-12-18 14:04:00'
}}</span>
</div>
<div style="display: flex; align-items: flex-start">
<span style="font-weight: 500; color: #333; min-width: 80px; font-size: 15px"
>可靠程度</span
>
<span style="font-size: 14px; color: #666; line-height: 1.5">{{
formData.reliability
}}</span>
</div>
</div>
</div>
</div>
<!-- 病史信息模块 - 优化布局内容可换行 -->
<div
style="
border: 1px solid #ddd;
border-radius: 8px;
padding: 25px;
margin-bottom: 25px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.03);
"
>
<div
style="
font-size: 18px;
font-weight: 600;
color: #333;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid #eee;
"
>
病史信息
</div>
<div
style="
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 18px;
"
>
<!-- 第一列 -->
<div>
<div style="display: flex; align-items: flex-start; margin-bottom: 16px">
<span style="font-weight: 500; color: #333; min-width: 80px; font-size: 15px"
>家族史</span
>
<span style="font-size: 14px; color: #666; line-height: 1.6">{{
formData.familyHistory || ''
}}</span>
</div>
<div style="display: flex; align-items: flex-start; margin-bottom: 16px">
<span style="font-weight: 500; color: #333; min-width: 80px; font-size: 15px"
>现病史</span
>
<span style="font-size: 14px; color: #666; line-height: 1.6">{{
formData.presentIllness || ''
}}</span>
</div>
<div style="display: flex; align-items: flex-start; margin-bottom: 16px">
<span style="font-weight: 500; color: #333; min-width: 80px; font-size: 15px"
>既往史</span
>
<span style="font-size: 14px; color: #666; line-height: 1.6">{{
formData.pastIllness || formData.pastHistory || ''
}}</span>
</div>
<div style="display: flex; align-items: flex-start">
<span style="font-weight: 500; color: #333; min-width: 80px; font-size: 15px"
>主诉</span
>
<span style="font-size: 14px; color: #666; line-height: 1.6">{{
formData.complaint || ''
}}</span>
</div>
</div>
<!-- 第二列 -->
<div>
<div style="display: flex; align-items: flex-start; margin-bottom: 16px">
<span style="font-weight: 500; color: #333; min-width: 80px; font-size: 15px"
>婚育史</span
>
<span style="font-size: 14px; color: #666; line-height: 1.6">{{
formData.maritalHistory || ''
}}</span>
</div>
<div style="display: flex; align-items: flex-start; margin-bottom: 16px">
<span style="font-weight: 500; color: #333; min-width: 80px; font-size: 15px"
>月经史</span
>
<span style="font-size: 14px; color: #666; line-height: 1.6">{{
formData.menstrualHistory || ''
}}</span>
</div>
<div style="display: flex; align-items: flex-start">
<span style="font-weight: 500; color: #333; min-width: 80px; font-size: 15px"
>个人史</span
>
<span style="font-size: 14px; color: #666; line-height: 1.6">{{
formData.personalHistory || ''
}}</span>
</div>
</div>
</div>
</div>
<!-- 中医望闻问切模块 -->
<div
style="
border: 1px solid #ddd;
border-radius: 8px;
padding: 25px;
margin-bottom: 25px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.03);
"
>
<div
style="
font-size: 18px;
font-weight: 600;
color: #333;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid #eee;
"
>
中医望闻问切
</div>
<div style="display: flex; align-items: flex-start">
<span style="font-weight: 500; color: #333; min-width: 120px; font-size: 15px"
>详细记录</span
>
<span style="font-size: 14px; color: #666; line-height: 1.8">{{
formData.tcmInfo || ''
}}</span>
</div>
</div>
<!-- 体格检查模块 - 优化两列布局信息对齐 -->
<div
style="
border: 1px solid #ddd;
border-radius: 8px;
padding: 25px;
margin-bottom: 25px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.03);
"
>
<div
style="
font-size: 18px;
font-weight: 600;
color: #333;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid #eee;
"
>
体格检查
</div>
<div
style="
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 25px;
"
>
<!-- 第一列生命体征 -->
<div>
<div
style="
font-size: 16px;
font-weight: 500;
color: #333;
margin-bottom: 15px;
padding-bottom: 8px;
border-bottom: 1px solid #f0f0f0;
"
>
生命体征
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px">
<div style="padding: 10px; background: #f8f8f8; border-radius: 4px; text-align: center">
<div style="font-size: 13px; color: #666; margin-bottom: 4px">体温</div>
<div style="font-size: 14px; color: #333; font-weight: 500">
{{ formData.temp || '' }}
</div>
</div>
<div style="padding: 10px; background: #f8f8f8; border-radius: 4px; text-align: center">
<div style="font-size: 13px; color: #666; margin-bottom: 4px">脉搏</div>
<div style="font-size: 14px; color: #333; font-weight: 500">
{{ formData.pulse || '' }}
</div>
</div>
<div style="padding: 10px; background: #f8f8f8; border-radius: 4px; text-align: center">
<div style="font-size: 13px; color: #666; margin-bottom: 4px">呼吸</div>
<div style="font-size: 14px; color: #333; font-weight: 500">
{{ formData.respiration || '' }}
</div>
</div>
<div style="padding: 10px; background: #f8f8f8; border-radius: 4px; text-align: center">
<div style="font-size: 13px; color: #666; margin-bottom: 4px">血压</div>
<div style="font-size: 14px; color: #333; font-weight: 500">
{{ formData.bp || '' }}
</div>
</div>
<div style="padding: 10px; background: #f8f8f8; border-radius: 4px; text-align: center">
<div style="font-size: 13px; color: #666; margin-bottom: 4px">身高</div>
<div style="font-size: 14px; color: #333; font-weight: 500">
{{ formData.height || '' }}
</div>
</div>
<div style="padding: 10px; background: #f8f8f8; border-radius: 4px; text-align: center">
<div style="font-size: 13px; color: #666; margin-bottom: 4px">体重</div>
<div style="font-size: 14px; color: #333; font-weight: 500">
{{ formData.weight || '' }}
</div>
</div>
<div
style="
padding: 10px;
background: #f8f8f8;
border-radius: 4px;
text-align: center;
grid-column: 1/3;
"
>
<div style="font-size: 13px; color: #666; margin-bottom: 4px">BMI</div>
<div style="font-size: 14px; color: #333; font-weight: 500">
{{ formData.bmi || '' }}
</div>
</div>
</div>
</div>
<!-- 第二列检查详情 -->
<div>
<div
style="
font-size: 16px;
font-weight: 500;
color: #333;
margin-bottom: 15px;
padding-bottom: 8px;
border-bottom: 1px solid #f0f0f0;
"
>
检查详情
</div>
<div style="display: flex; align-items: flex-start; margin-bottom: 14px">
<span style="font-weight: 500; color: #333; min-width: 100px; font-size: 14px"
>皮肤粘膜</span
>
<span style="font-size: 13px; color: #666; line-height: 1.5">{{
formData.skin || ''
}}</span>
</div>
<div style="display: flex; align-items: flex-start; margin-bottom: 14px">
<span style="font-weight: 500; color: #333; min-width: 100px; font-size: 14px"
>胸部</span
>
<span style="font-size: 13px; color: #666; line-height: 1.5">{{
formData.chest || ''
}}</span>
</div>
<div style="display: flex; align-items: flex-start; margin-bottom: 14px">
<span style="font-weight: 500; color: #333; min-width: 100px; font-size: 14px"
>腹部</span
>
<span style="font-size: 13px; color: #666; line-height: 1.5">{{
formData.abdomen || ''
}}</span>
</div>
<div style="display: flex; align-items: flex-start; margin-bottom: 14px">
<span style="font-weight: 500; color: #333; min-width: 100px; font-size: 14px"
>一般情况</span
>
<span style="font-size: 13px; color: #666; line-height: 1.5">{{
formData.general || ''
}}</span>
</div>
<div style="display: flex; align-items: flex-start">
<span style="font-weight: 500; color: #333; min-width: 100px; font-size: 14px"
>四肢/神经</span
>
<span style="font-size: 13px; color: #666; line-height: 1.5">{{
formData.limbsNervous || ''
}}</span>
</div>
</div>
</div>
</div>
<!-- 辅助检查模块 - 合并重复模块优化显示 -->
<div
style="
border: 1px solid #ddd;
border-radius: 8px;
padding: 25px;
margin-bottom: 25px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.03);
"
>
<div
style="
font-size: 18px;
font-weight: 600;
color: #333;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid #eee;
"
>
辅助检查
</div>
<div
style="
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 20px;
"
>
<div style="padding: 15px; background: #f8f8f8; border-radius: 6px">
<div style="font-weight: 500; color: #333; font-size: 15px; margin-bottom: 8px">
检查结果
</div>
<div style="font-size: 14px; color: #666; line-height: 1.6">
{{ formData.auxExam || '' }}
</div>
</div>
</div>
</div>
<!-- 诊断信息模块 - 修正分类优化布局 -->
<div
style="
border: 1px solid #ddd;
border-radius: 8px;
padding: 25px;
margin-bottom: 25px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.03);
"
>
<div
style="
font-size: 18px;
font-weight: 600;
color: #333;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid #eee;
"
>
诊断信息
</div>
<div
style="
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 20px;
"
>
<div style="padding: 18px; background: #f8f8f8; border-radius: 6px">
<div style="font-weight: 500; color: #333; font-size: 15px; margin-bottom: 10px">
中医诊断
</div>
<div style="font-size: 14px; color: #666; line-height: 1.8">
{{ formData.tcmDiagnosis || '' }}
</div>
</div>
<div style="padding: 18px; background: #f8f8f8; border-radius: 6px">
<div style="font-weight: 500; color: #333; font-size: 15px; margin-bottom: 10px">
西医诊断
</div>
<div style="font-size: 14px; color: #666; line-height: 1.8">
{{ formData.westernDiagnosis || '' }}
</div>
</div>
</div>
</div>
<!-- 签名信息模块 -->
<div
style="
border: 1px solid #ddd;
border-radius: 8px;
padding: 25px;
margin-bottom: 30px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.03);
"
>
<div
style="
font-size: 18px;
font-weight: 600;
color: #333;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid #eee;
"
>
签名信息
</div>
<div
style="
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 30px;
max-width: 800px;
margin: 0 auto;
"
>
<div style="text-align: center">
<div
style="
font-weight: 500;
color: #333;
font-size: 15px;
margin-bottom: 40px;
border-bottom: 1px solid #333;
padding-bottom: 2px;
display: inline-block;
"
>
医师签名
</div>
<div style="font-size: 14px; color: #666">{{ formData.doctorSign || '' }}</div>
</div>
<div style="text-align: center">
<div
style="
font-weight: 500;
color: #333;
font-size: 15px;
margin-bottom: 40px;
border-bottom: 1px solid #333;
padding-bottom: 2px;
display: inline-block;
"
>
上级医师
</div>
<div style="font-size: 14px; color: #666">{{ formData.superiorSign || '' }}</div>
</div>
<div style="text-align: center">
<div
style="
font-weight: 500;
color: #333;
font-size: 15px;
margin-bottom: 40px;
border-bottom: 1px solid #333;
padding-bottom: 2px;
display: inline-block;
"
>
记录日期
</div>
<div style="font-size: 14px; color: #666">{{ formData.signDate || '' }}</div>
</div>
</div>
</div>
<!-- 底部备注 -->
<div
style="
text-align: center;
font-size: 13px;
color: #888;
margin-bottom: 20px;
padding-top: 10px;
border-top: 1px solid #eee;
"
>
本记录由长春市朝阳区中医院医师根据患者病情如实记录仅供临床诊疗参考 |
地址长春市朝阳区XX街XX号 | 联系电话0431-XXXXXXX
</div>
<!-- 打印按钮 - 优化样式居中显示 -->
<!-- <div style="text-align: center; margin-bottom: 30px">
<el-button type="primary" @click="onPrint" style="padding: 10px 30px; font-size: 15px"
>打印预览</el-button
>
</div> -->
</div>
</template>
<script setup>
import { ref, reactive } from 'vue';
import { previewPrint } from '../../../utils/printUtils';
const bodyRef = ref();
// 响应式表单数据
const formData = reactive({
// 基础信息
patientName: '', // 原patient?.name
hospitalNo: '', // 原patient?.busNo
gender: '', // 原patient?.genderEnum_enumText
age: '',
nation: '',
occupation: '', // 职业
marriage: '', // 婚姻状况
birthplace: '', // 出生地
admissionTime: '', // 入院时间
recordTime: '', // 记录时间
historyReporter: '', // 病史陈述者
reliability: '可靠', // 可靠程度
// 病史信息
complaint: '', // 主诉
presentIllness: '', // 现病史
pastIllness: '', // 既往史
personalHistory: '', // 个人史
allergyHistory: '', // 过敏史
pastHistory: '', // 既往史(重复字段,保留兼容)
familyHistory: '', // 家族史
maritalHistory: '', // 婚姻史
menstrualHistory: '', // 月经史
// 中医信息
tcmInfo: '',
// 体格检查
temp: '',
pulse: '',
respiration: '',
bp: '',
height: '',
weight: '',
bmi: '',
general: '',
skin: '',
chest: '',
abdomen: '',
limbsNervous: '',
// 辅助检查
auxExam: '',
// 诊断信息
tcmDiagnosis: '',
westernDiagnosis: '',
// 签名信息
doctorSign: '',
superiorSign: '',
signDate: '',
});
// 打印方法
const onPrint = () => {
// previewPrint(bodyRef.value);
};
const getDom = () => {
return bodyRef.value;
};
const setData = (data) => {
console.log('设置数据=========>', JSON.stringify(data));
Object.assign(formData, data);
};
defineExpose({
setData,
getDom,
});
</script>
<style scoped>
/* 打印样式优化,隐藏不必要元素 */
@media print {
.el-button {
display: none !important;
}
body {
print-color-adjust: exact;
-webkit-print-color-adjust: exact;
}
div[style*='box-shadow'] {
box-shadow: none !important;
}
}
</style>

View File

@@ -1,543 +0,0 @@
<template>
<div
ref="bodyRef"
style="
padding: 30px 20px;
max-width: 1200px;
margin: 0 auto;
min-height: 100vh;
background: #f8f9fa;
font-family: 'Microsoft YaHei', 'PingFang SC', sans-serif;
"
>
<!-- 标题区域 - 强化正式感与层次感 -->
<div style="text-align: center; margin-bottom: 35px; padding: 20px 0">
<div
style="
font-size: 24px;
color: #2c3e50;
letter-spacing: 2px;
font-weight: 500;
margin-bottom: 8px;
"
>
长春市朝阳区中医院
</div>
<div
style="
font-size: 32px;
font-weight: 700;
color: #1a2b48;
padding: 12px 0;
border-bottom: 2px solid #2c3e50;
display: inline-block;
letter-spacing: 1px;
"
>
出院诊断病历
</div>
</div>
<!-- 基础信息卡片 -->
<div
style="
border: 1px solid #e5e8eb;
border-radius: 12px;
padding: 25px;
margin-bottom: 25px;
background: #ffffff;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03);
"
>
<div
style="
font-size: 18px;
font-weight: 600;
color: #2c3e50;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid #f0f2f5;
position: relative;
"
>
基础信息
</div>
<div
style="
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 18px;
"
>
<div
style="
display: flex;
align-items: flex-start;
margin-bottom: 16px;
line-height: 1.6;
word-wrap: break-word;
"
>
<span
style="
font-weight: 500;
color: #34495e;
min-width: 80px;
font-size: 15px;
flex-shrink: 0;
word-wrap: break-word;
"
>姓名</span
>
<span
style="
font-size: 14px;
color: #606266;
flex: 1;
word-wrap: break-word;
word-break: break-all;
white-space: normal;
"
>{{ formData.patientName }}</span
>
</div>
<div
style="
display: flex;
align-items: flex-start;
margin-bottom: 16px;
line-height: 1.6;
word-wrap: break-word;
"
>
<span
style="
font-weight: 500;
color: #34495e;
min-width: 80px;
font-size: 15px;
flex-shrink: 0;
word-wrap: break-word;
"
>性别</span
>
<span
style="
font-size: 14px;
color: #606266;
flex: 1;
word-wrap: break-word;
word-break: break-all;
white-space: normal;
"
>{{ formData.gender }}</span
>
</div>
<div
style="
display: flex;
align-items: flex-start;
margin-bottom: 16px;
line-height: 1.6;
word-wrap: break-word;
"
>
<span
style="
font-weight: 500;
color: #34495e;
min-width: 80px;
font-size: 15px;
flex-shrink: 0;
word-wrap: break-word;
"
>年龄</span
>
<span
style="
font-size: 14px;
color: #606266;
flex: 1;
word-wrap: break-word;
word-break: break-all;
white-space: normal;
"
>{{ formData.age }}</span
>
</div>
<div
style="
display: flex;
align-items: flex-start;
margin-bottom: 16px;
line-height: 1.6;
word-wrap: break-word;
"
>
<span
style="
font-weight: 500;
color: #34495e;
min-width: 80px;
font-size: 15px;
flex-shrink: 0;
word-wrap: break-word;
"
>住院号</span
>
<span
style="
font-size: 14px;
color: #606266;
flex: 1;
word-wrap: break-word;
word-break: break-all;
white-space: normal;
"
>{{ formData.busNo }}</span
>
</div>
<div
style="
display: flex;
align-items: flex-start;
margin-bottom: 16px;
line-height: 1.6;
word-wrap: break-word;
"
>
<span
style="
font-weight: 500;
color: #34495e;
min-width: 80px;
font-size: 15px;
flex-shrink: 0;
word-wrap: break-word;
"
>职业</span
>
<span
style="
font-size: 14px;
color: #606266;
flex: 1;
word-wrap: break-word;
word-break: break-all;
white-space: normal;
"
>{{ formData.temperature }}</span
>
</div>
<div
style="
display: flex;
align-items: flex-start;
margin-bottom: 16px;
line-height: 1.6;
word-wrap: break-word;
"
>
<span
style="
font-weight: 500;
color: #34495e;
min-width: 80px;
font-size: 15px;
flex-shrink: 0;
word-wrap: break-word;
"
>入院时间</span
>
<span
style="
font-size: 14px;
color: #606266;
flex: 1;
word-wrap: break-word;
word-break: break-all;
white-space: normal;
"
>{{ formData.admissionDate }}</span
>
</div>
<div
style="
display: flex;
align-items: flex-start;
margin-bottom: 16px;
line-height: 1.6;
word-wrap: break-word;
"
>
<span
style="
font-weight: 500;
color: #34495e;
min-width: 80px;
font-size: 15px;
flex-shrink: 0;
word-wrap: break-word;
"
>出院时间</span
>
<span
style="
font-size: 14px;
color: #606266;
flex: 1;
word-wrap: break-word;
word-break: break-all;
white-space: normal;
"
>{{ formData.dischargeDate }}</span
>
</div>
<div
style="
display: flex;
align-items: flex-start;
margin-bottom: 16px;
line-height: 1.6;
word-wrap: break-word;
"
>
<span
style="
font-weight: 500;
color: #34495e;
min-width: 80px;
font-size: 15px;
flex-shrink: 0;
word-wrap: break-word;
"
>住院天数</span
>
<span
style="
font-size: 14px;
color: #606266;
flex: 1;
word-wrap: break-word;
word-break: break-all;
white-space: normal;
"
>{{ formData.hospitalDays }}</span
>
</div>
</div>
</div>
<!-- 诊断信息卡片 -->
<div
style="
border: 1px solid #e5e8eb;
border-radius: 12px;
padding: 25px;
margin-bottom: 25px;
background: #ffffff;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03);
"
>
<div
style="
font-size: 18px;
font-weight: 600;
color: #2c3e50;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid #f0f2f5;
position: relative;
"
>
诊断
</div>
<div
style="
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 18px;
"
>
<div
style="
display: flex;
align-items: flex-start;
margin-bottom: 16px;
line-height: 1.6;
word-wrap: break-word;
"
>
<span
style="
font-weight: 500;
color: #34495e;
min-width: 80px;
font-size: 15px;
flex-shrink: 0;
word-wrap: break-word;
"
>出诊诊断</span
>
<span
style="
font-size: 14px;
color: #606266;
flex: 1;
word-wrap: break-word;
word-break: break-all;
white-space: normal;
"
>{{ formData.DischargeDiagnosis }}</span
>
</div>
<div
style="
display: flex;
align-items: flex-start;
margin-bottom: 16px;
line-height: 1.6;
word-wrap: break-word;
grid-column: 1 / -1;
padding: 4px 0;
"
>
<span
style="
font-weight: 500;
color: #34495e;
min-width: 80px;
font-size: 15px;
flex-shrink: 0;
word-wrap: break-word;
"
>出院病情摘要</span
>
<span
style="
font-size: 14px;
color: #606266;
flex: 1;
word-wrap: break-word;
word-break: break-all;
white-space: normal;
"
>{{ formData.SummaryAndDiagnosisAndTreatmentProcess }}</span
>
</div>
<div
style="
display: flex;
align-items: flex-start;
margin-bottom: 16px;
line-height: 1.6;
word-wrap: break-word;
grid-column: 1 / -1;
padding: 4px 0;
"
>
<span
style="
font-weight: 500;
color: #34495e;
min-width: 80px;
font-size: 15px;
flex-shrink: 0;
word-wrap: break-word;
"
>出院后要求及注意事项</span
>
<span
style="
font-size: 14px;
color: #606266;
flex: 1;
word-wrap: break-word;
word-break: break-all;
white-space: normal;
"
>{{ formData.RequirementsAndPrecautionsAfterDischarge }}</span
>
</div>
<div
style="
display: flex;
align-items: flex-start;
margin-bottom: 16px;
line-height: 1.6;
word-wrap: break-word;
grid-column: 1 / -1;
padding: 4px 0;
"
>
<span
style="
font-weight: 500;
color: #34495e;
min-width: 80px;
font-size: 15px;
flex-shrink: 0;
word-wrap: break-word;
"
>中医调护</span
>
<span
style="
font-size: 14px;
color: #606266;
flex: 1;
word-wrap: break-word;
word-break: break-all;
white-space: normal;
"
>{{ formData.TraditionalChineseMedicineNursing }}</span
>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'; // 补充缺失的reactive导入
const bodyRef = ref(null);
const showPrintPreview = ref(false); // 控制弹窗显隐
// 表单数据
const formData = reactive({
patientName: '', // 姓名
age: '', // 年龄
gender: '', // 性别
busNo: '', // 住院号
admissionDate: '', // 入院日期
dischargeDate: '', // 出院日期
hospitalDays: '', // 住院天数
DischargeDiagnosis: '', // 出院诊断
SummaryAndDiagnosisAndTreatmentProcess: '', // 出院病情摘要及诊疗经过
RequirementsAndPrecautionsAfterDischarge: '', // 出院后要求及注意事项
TraditionalChineseMedicineNursing: '', // 中医调护
});
const getDom = () => {
return bodyRef.value;
};
const setData = (data) => {
console.log('设置数据=========>', JSON.stringify(data));
Object.assign(formData, data);
};
defineExpose({
setData,
getDom,
});
</script>
<style scoped>
/* 以下是内联样式无法实现的样式(保留说明) */
/* 1. 伪元素样式card-title::after内联样式不支持伪元素 */
/* 2. hover效果内联样式不支持:hover伪类 */
/* 3. 媒体查询响应式:内联样式无法编写@media规则 */
/* 4. 打印预览相关样式:若需要打印功能,需单独处理 */
</style>

View File

@@ -1,347 +0,0 @@
<template>
<div style="padding: 20px; background: #f8f9fa; min-height: 100vh;" ref="bodyRef">
<!-- 标题区域 - 强化正式感 -->
<div
style="text-align: center; margin-bottom: 30px; padding: 20px; background: #fff; border-radius: 12px; box-shadow: 0 2px 6px rgba(0,0,0,0.03);">
<div style="font-size: 22px; color: #2d3748; letter-spacing: 1px;">长春市朝阳区中医院</div>
<div
style="font-size: 28px; font-weight: 700; margin: 12px 0; padding: 8px 0; border-bottom: 2px solid #e8f4f8; display: inline-block;">
住院患者入院沟通记录单</div>
<div style="display: flex; justify-content: center; align-items: center; gap: 10px; font-size: 15px; ">
<span style="font-weight: 500;">住院号</span>
<span style="font-weight: 600; text-decoration: underline;">20210001</span>
</div>
</div>
<!-- 基本信息模块 -->
<div class="card-container">
<div class="card-header">
<span class="card-title">基本信息</span>
</div>
<div class="card-content grid-2col">
<div class="info-item">
<span class="info-label">姓名</span>
<span class="info-value">张三</span>
</div>
<div class="info-item">
<span class="info-label">性别</span>
<span class="info-value"></span>
</div>
<div class="info-item">
<span class="info-label">年龄</span>
<span class="info-value">34 </span>
</div>
<div class="info-item">
<span class="info-label">科室/病区</span>
<span class="info-value">中医科</span>
</div>
<div class="info-item">
<span class="info-label">病房/床号</span>
<span class="info-value">305-2</span>
</div>
<div class="info-item">
<span class="info-label">入院日期</span>
<span class="info-value">2025-02-14</span>
</div>
</div>
</div>
<!-- 团队信息模块 -->
<div class="card-container">
<div class="card-header">
<span class="card-title">团队信息</span>
</div>
<div class="card-content grid-2col">
<div class="info-item">
<span class="info-label">经治医生</span>
<span class="info-value">华佗</span>
</div>
<div class="info-item">
<span class="info-label">主治医生</span>
<span class="info-value">王海明</span>
</div>
<div class="info-item">
<span class="info-label">科主任</span>
<span class="info-value">特斯拉</span>
</div>
</div>
</div>
<!-- 病情与诊断模块 -->
<div class="card-container">
<div class="card-header">
<span class="card-title">病情与诊断</span>
</div>
<div class="card-content grid-2col">
<div class="info-item">
<span class="info-label">病情状况</span>
<div class="info-value multi-line">
1111111111111111111111111111111111111111111111111111111111111111111111111111</div>
</div>
<div class="info-item">
<span class="info-label">中医诊断</span>
<div class="info-value multi-line">
1111111111111111111111111111111111111111111111111111111111111111111111111111</div>
</div>
<div class="info-item">
<span class="info-label">西医诊断</span>
<div class="info-value multi-line">
1111111111111111111111111111111111111111111111111111111111111111111111111111</div>
</div>
</div>
</div>
<!-- 治疗与检查计划模块 -->
<div class="card-container">
<div class="card-header">
<span class="card-title">治疗与检查计划</span>
</div>
<div class="card-content grid-2col">
<div class="info-item">
<span class="info-label">治疗方案</span>
<div class="info-value multi-line">
1111111111111111111111111111111111111111111111111111111111111111111111111111</div>
</div>
<div class="info-item">
<span class="info-label">进一步检查项目</span>
<div class="info-value multi-line">血常规肝肾功能腹部B超心电图中医辨证分型检查肿瘤标志物筛查</div>
</div>
</div>
</div>
<!-- 风险告知模块 -->
<div class="card-container">
<div class="card-header">
<span class="card-title">风险告知</span>
</div>
<div class="card-content">
<div class="info-item full-width">
<span class="info-label">告知内容</span>
<div class="info-value multi-line">
1. 治疗过程中可能出现药物不良反应如过敏胃肠道不适等若出现不适需及时告知医护人员<br />
2. 检查项目存在一定的操作风险如穿刺出血感染等医护人员将严格按照规范操作<br />
3. 病情可能因个体差异出现变化需根据实际情况调整治疗方案<br />
4. 若患者存在隐瞒病史不配合治疗等情况可能影响治疗效果相关风险由患者自行承担
</div>
</div>
</div>
</div>
<!-- 签署确认模块 -->
<div class="card-container">
<div class="card-header">
<span class="card-title">签署确认</span>
</div>
<div class="card-content grid-2col">
<div class="info-item">
<span class="info-label">患者或家属</span>
<span class="info-value">张三</span>
</div>
<div class="info-item">
<span class="info-label">与患者关系</span>
<span class="info-value">妻子</span>
</div>
<div class="info-item">
<span class="info-label">签字日期</span>
<span class="info-value">2025-02-14</span>
</div>
<div class="info-item">
<span class="info-label">沟通医师签字</span>
<span class="info-value">华佗</span>
</div>
<div class="info-item">
<span class="info-label">沟通日期</span>
<span class="info-value">2025-02-14</span>
</div>
</div>
</div>
</div>
</template>
<style scoped>
/* 全局卡片容器统一样式 */
.card-container {
border: 1px solid #e0e0e0;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
margin-bottom: 20px;
background: #fff;
transition: box-shadow 0.3s ease, transform 0.2s ease;
}
/* 卡片hover效果 */
.card-container:hover {
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.08);
transform: translateY(-1px);
}
/* 卡片头部样式 */
.card-header {
padding: 14px 20px;
border-bottom: 1px solid #f0f0f0;
background-color: #f5fafe;
display: flex;
align-items: center;
}
/* 卡片标题样式 */
.card-title {
font-size: 18px;
font-weight: 600;
letter-spacing: 0.5px;
}
/* 卡片内容区统一样式 */
.card-content {
padding: 22px;
gap: 20px;
}
/* 2列网格布局桌面端 */
.grid-2col {
display: grid;
grid-template-columns: repeat(2, 1fr);
}
/* 信息项统一样式 */
.info-item {
display: flex;
align-items: flex-start;
/* 改为顶端对齐,适配多行文本 */
padding: 9px 0;
gap: 8px;
}
/* 信息标签样式 */
.info-label {
font-weight: 500;
color: #333;
min-width: 110px;
font-size: 15px;
padding-top: 5px;
/* 对齐多行文本的顶部 */
}
/* 信息值样式(单行) */
.info-value {
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
min-height: 28px;
/* 确保单行和多行高度一致 */
display: flex;
align-items: center;
}
/* 多行文本样式(适配长内容) */
.info-value.multi-line {
align-items: flex-start;
padding: 10px 12px;
line-height: 1.6;
min-height: 80px;
/* 最小高度,避免内容过少时显得空旷 */
white-space: pre-line;
/* 支持换行符和空格 */
}
/* 全屏宽度信息项(如风险告知) */
.info-item.full-width {
width: 100%;
}
/* 信息值hover效果 */
.info-value:hover {
background: #f2f2f2;
border-color: #e0e0e0;
}
/* 响应式适配移动端1列布局 */
@media (max-width: 768px) {
.grid-2col {
grid-template-columns: 1fr;
}
.card-content {
padding: 16px;
gap: 16px;
}
.card-header {
padding: 12px 16px;
}
.card-title {
font-size: 16px;
}
.info-item {
padding: 10px 0;
}
.info-label {
min-width: 90px;
font-size: 14px;
padding-top: 4px;
}
.info-value {
font-size: 14px;
padding: 4px 10px;
min-height: 24px;
}
.info-value.multi-line {
padding: 8px 10px;
min-height: 60px;
line-height: 1.5;
}
/* 标题区域适配移动端 */
div[style*="font-size: 28px"] {
font-size: 24px !important;
}
div[style*="font-size: 22px"] {
font-size: 20px !important;
}
}
/* 打印样式优化 */
@media print {
body {
print-color-adjust: exact;
-webkit-print-color-adjust: exact;
background: #fff !important;
}
.card-container {
box-shadow: none !important;
border: 1px solid #ddd !important;
margin-bottom: 15px !important;
transform: none !important;
}
.card-header {
background: #f8f8f8 !important;
border-bottom: 1px solid #ddd !important;
}
.info-value {
background: #fff !important;
border: 1px dashed #eee !important;
}
.card-container:hover {
box-shadow: none !important;
}
}
</style>
<script setup>
</script>

View File

@@ -1,877 +0,0 @@
<template>
<div style="padding: 20px; background: #f8f9fa; min-height: 100vh" ref="bodyRef">
<!-- 标题区域 - 强化正式感 -->
<div
style="
text-align: center;
margin-bottom: 30px;
padding: 20px;
background: #fff;
border-radius: 12px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.03);
"
>
<div style="font-size: 22px; color: #2d3748; letter-spacing: 1px">长春市朝阳区中医院</div>
<div
style="
font-size: 28px;
font-weight: 700;
margin: 12px 0;
padding: 8px 0;
border-bottom: 2px solid #e8f4f8;
display: inline-block;
"
>
患者与手术基础信息
</div>
<div
style="
display: flex;
justify-content: center;
align-items: center;
gap: 10px;
font-size: 15px;
color: #4a5568;
"
>
<span style="font-weight: 500">住院号</span>
<span style="font-weight: 600; text-decoration: underline">{{ formData.busNo }}</span>
</div>
</div>
<!-- 基本信息模块统一为card样式 -->
<div
style="
border: 1px solid #e0e0e0;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
margin-bottom: 20px;
background: #fff;
transition: box-shadow 0.3s ease, transform 0.2s ease;
"
>
<div
style="
padding: 14px 20px;
border-bottom: 1px solid #f0f0f0;
display: flex;
align-items: center;
"
>
<span style="font-size: 18px; font-weight: 600; letter-spacing: 0.5px">基本信息</span>
</div>
<div style="padding: 22px; gap: 20px; display: grid; grid-template-columns: repeat(2, 1fr)">
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>姓名</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.patientName }}</span
>
</div>
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>性别</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.gender }}</span
>
</div>
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>年龄</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.age }}</span
>
</div>
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>科室</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.department }}</span
>
</div>
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>病房/床号</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.bedNo }}</span
>
</div>
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>手术日期</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.operationDateTime }}</span
>
</div>
</div>
</div>
<!-- 手术团队信息模块 -->
<div
style="
border: 1px solid #e0e0e0;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
margin-bottom: 20px;
background: #fff;
transition: box-shadow 0.3s ease, transform 0.2s ease;
"
>
<div
style="
padding: 14px 20px;
border-bottom: 1px solid #f0f0f0;
display: flex;
align-items: center;
"
>
<span style="font-size: 18px; font-weight: 600; letter-spacing: 0.5px">手术团队信息</span>
</div>
<div style="padding: 22px; gap: 20px; display: grid; grid-template-columns: repeat(2, 1fr)">
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>手术者</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.surgeon }}</span
>
</div>
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>第一助手</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.firstAssistant }}</span
>
</div>
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>第二助手</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.secondAssistant }}</span
>
</div>
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>器械护士</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.scrubNurse }}</span
>
</div>
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>麻醉医师</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.anesthesiologist }}</span
>
</div>
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>巡逻护士</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.circulatingNurse }}</span
>
</div>
</div>
</div>
<!-- 手术详情模块 -->
<div
style="
border: 1px solid #e0e0e0;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
margin-bottom: 20px;
background: #fff;
transition: box-shadow 0.3s ease, transform 0.2s ease;
"
>
<div
style="
padding: 14px 20px;
border-bottom: 1px solid #f0f0f0;
display: flex;
align-items: center;
"
>
<span style="font-size: 18px; font-weight: 600; letter-spacing: 0.5px">手术详情</span>
</div>
<div style="padding: 22px; gap: 20px; display: grid; grid-template-columns: repeat(2, 1fr)">
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>手术名称</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.operationName }}</span
>
</div>
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>手术方式</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.operationMethod }}</span
>
</div>
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>手术入路</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.surgicalApproach }}</span
>
</div>
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>术中发现</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.intraoperativeFindings }}</span
>
</div>
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>手术过程</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.operationProcess }}</span
>
</div>
</div>
</div>
<!-- 术后情况模块 -->
<div
style="
border: 1px solid #e0e0e0;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
margin-bottom: 20px;
background: #fff;
transition: box-shadow 0.3s ease, transform 0.2s ease;
"
>
<div
style="
padding: 14px 20px;
border-bottom: 1px solid #f0f0f0;
display: flex;
align-items: center;
"
>
<span style="font-size: 18px; font-weight: 600; letter-spacing: 0.5px">术后情况</span>
</div>
<div style="padding: 22px; gap: 20px; display: grid; grid-template-columns: repeat(2, 1fr)">
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>术中出血量</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.bloodLoss }}ml</span
>
</div>
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>输血情况</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.bloodTransfusion }}</span
>
</div>
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>引流管放置</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.drainageTube }}</span
>
</div>
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>标本处理</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.specimenDisposal }}</span
>
</div>
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>手术结束时间</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.operationEndTime }}</span
>
</div>
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>患者去向</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.patientDestination }}</span
>
</div>
</div>
</div>
<!-- 签署确认模块 -->
<div
style="
border: 1px solid #e0e0e0;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
margin-bottom: 20px;
background: #fff;
transition: box-shadow 0.3s ease, transform 0.2s ease;
"
>
<div
style="
padding: 14px 20px;
border-bottom: 1px solid #f0f0f0;
display: flex;
align-items: center;
"
>
<span style="font-size: 18px; font-weight: 600; letter-spacing: 0.5px">签署确认</span>
</div>
<div style="padding: 22px; gap: 20px; display: grid; grid-template-columns: repeat(2, 1fr)">
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>手术者签名</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.surgeonSignature }}</span
>
</div>
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>记录者签名</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.recorderSignature }}</span
>
</div>
<div style="display: flex; align-items: center; padding: 9px 0">
<span
style="
font-weight: 500;
color: #333;
min-width: 100px;
font-size: 15px;
margin-right: 10px;
"
>记录日期</span
>
<span
style="
font-size: 15px;
color: #222;
padding: 5px 12px;
background: #f9f9f9;
border-radius: 4px;
flex: 1;
border: 1px solid #f0f0f0;
transition: all 0.2s ease;
"
>{{ formData.recordDate }}</span
>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, reactive, defineExpose } from 'vue';
const bodyRef = ref();
// 响应式表单数据
const formData = reactive({
// 患者与手术基础信息
busNo: '',
patientName: '',
gender: '',
age: '',
department: '',
bedNo: '',
operationDateTime: '', // 手术日期时间
// 手术团队信息
surgeon: '', // 主刀医师
firstAssistant: '', // 第一助手
secondAssistant: '', // 第二助手
anesthesiologist: '', // 麻醉医师
circulatingNurse: '', // 巡回护士
scrubNurse: '', // 器械护士
// 手术详情
operationName: '', // 规范手术名称
operationMethod: '', // 手术方式
surgicalApproach: '', // 手术入路
intraoperativeFindings: '', // 术中发现
operationProcess: '', // 手术过程
// 术后情况
bloodLoss: '', // 术中出血量
bloodTransfusion: '', // 输血情况
drainageTube: '', // 引流管放置
specimenDisposal: '', // 标本处理
operationEndTime: '', // 手术结束时间
patientDestination: '', // 患者去向
// 签署信息
surgeonSignature: '', // 手术者签名
recorderSignature: '', // 记录者签名
recordDate: '', // 记录日期
});
const getDom = () => {
return bodyRef.value;
};
const setData = (data) => {
console.log('设置数据=========>', JSON.stringify(data));
Object.assign(formData, data);
};
defineExpose({
setData,
getDom,
});
</script>

File diff suppressed because one or more lines are too long

View File

@@ -18,31 +18,24 @@
<el-text size="large">
<!-- <el-form-item label="费用性质:" prop="currentDate"> {{ '自费' }} </el-form-item> -->
</el-text>
<!-- 支付方式选择 -->
<div class="payment-method-container">
<el-form-item label="支付方式:">
<div class="payment-type-list">
<div
class="payment-type-item"
:class="{ active: currentPayType === item.value }"
v-for="item in payTypeOptions"
:key="item.value"
@click="selectPayType(item.value)"
>
<svg-icon
:icon-class="item.iconClass || item.value"
class="payment-icon"
:style="{ color: currentPayType === item.value ? '#13C0B3' : '#666666' }"
/>
<span class="payment-label">{{ item.label }}</span>
</div>
</div>
</el-form-item>
</div>
<!-- 自费支付 -->
<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
@@ -58,7 +51,6 @@
</div>
</el-form-item>
</div>
<!-- 金额汇总 -->
<div class="summary">
<el-space :size="30">
@@ -73,7 +65,6 @@
</div>
</el-form>
</div>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submit"> </el-button>
@@ -82,12 +73,11 @@
</template>
</el-dialog>
</template>
<script setup>
// 原有逻辑代码保持不变
import { savePayment } from './api';
import { computed, watch, reactive, ref, getCurrentInstance, nextTick } from 'vue';
import { ElMessage } from 'element-plus';
const props = defineProps({
open: {
type: Boolean,
@@ -109,92 +99,58 @@ const props = defineProps({
const { proxy } = getCurrentInstance();
const data = reactive({
form: {
amount: undefined,
displayAmount: 0,
payLevelEnum: undefined,
},
rules: {
amount: [
{ required: true, message: '请输入支付金额', trigger: 'blur' },
{ type: 'number', min: 0.01, message: '支付金额必须大于0', trigger: 'blur' },
],
},
form: {},
rules: {},
});
const { form, rules } = toRefs(data);
// 支付方式选项
const payTypeOptions = [
{ label: '现金', value: 220400 },
{ label: '微信', value: 220100 },
{ label: '支付宝', value: 220200 },
{ label: '银联', value: 220300 },
];
// 定义当前选中的支付方式,默认选中现金
const currentPayType = ref(220400);
// 选择支付方式方法
const selectPayType = (value) => {
currentPayType.value = value;
form.value.payLevelEnum = value;
};
const { queryParams, form, rules } = toRefs(data);
const emit = defineEmits(['close']);
const payMethods = ref(undefined);
async function submit() {
// 表单验证
if (!form.value.amount || form.value.amount <= 0) {
ElMessage.error('请输入有效的支付金额');
return;
}
if (!form.value.payLevelEnum) {
ElMessage.error('请选择支付方式');
return;
}
form.value.patientId = props.patientInfo?.patientId;
form.value.encounterId = props.patientInfo?.encounterId;
form.value.accountId = props.patientInfo?.accountId;
console.log('表单数据:', form.value);
try {
const res = await savePayment(form.value);
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) {
ElMessage.success('收费成功');
reset();
emit('close', {
status: 'success',
busNo: props.patientInfo?.busNo,
});
} else {
ElMessage.error(res.msg || '收费失败');
emit('close', 'success');
}
} catch (error) {
ElMessage.error('网络错误,请重试');
console.error(error);
}
});
}
/** 重置操作表单 */
function reset() {
form.value.amount = undefined;
form.value.displayAmount = 0;
form.value.payLevelEnum = undefined;
currentPayType.value = 220400; // 重置选中状态为现金
if (proxy && proxy.resetForm) {
proxy.resetForm('chargeDialogRef');
}
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 || 0;
form.value.displayAmount = form.value.amount;
}
/**
* 变化支付方式事件
*
*/
function clearAmount() {
form.value.amount = 0;
}
@@ -204,24 +160,12 @@ function close() {
emit('close');
}
// 监听总金额变化,如果有默认值则自动填充
watch(
() => props.totalAmount,
(newVal) => {
if (newVal && newVal > 0) {
form.value.amount = newVal;
form.value.displayAmount = newVal;
}
},
{ immediate: true }
);
</script>
<style scoped>
:deep(.pagination-container .el-pagination) {
right: 20px !important;
}
.charge-container {
max-width: 600px;
margin: 20px auto;
@@ -244,49 +188,10 @@ watch(
font-weight: bold;
}
/* 支付方式容器样式 */
.payment-method-container {
.payment-type {
margin: 15px 0;
}
.payment-type-list {
display: flex;
gap: 16px;
flex-wrap: wrap;
}
.payment-type-item {
display: flex;
align-items: center;
gap: 8px;
padding: 12px 20px;
background-color: #f5f7fa;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s ease;
border: 2px solid transparent;
}
.payment-type-item:hover {
background-color: #eef2f7;
}
.payment-type-item.active {
background-color: #e8f8f5;
border-color: #13c0b3;
color: #13c0b3;
}
.payment-icon {
width: 20px;
height: 20px;
transition: color 0.3s ease;
}
.payment-label {
font-size: 14px;
}
.payment-container {
margin: 15px 0;
}
@@ -343,7 +248,7 @@ watch(
.suffix-wrapper {
position: relative;
display: inline-block;
display: inline-block; /* 保持行内布局 */
}
.suffix-text {
@@ -352,9 +257,10 @@ watch(
top: 50%;
transform: translateY(-50%);
color: #999;
pointer-events: none;
pointer-events: none; /* 避免点击干扰 */
}
/* 调整输入框内边距 */
.amount-input .el-input__inner {
padding-right: 30px !important;
}

View File

@@ -47,7 +47,7 @@
<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>
@@ -66,7 +66,6 @@
<script setup>
import { reactive } from 'vue';
import { getWardList } from '../../../../drug/inpatientMedicationDispensing/components/api';
import { getDepositInfo } from './api';
// Props
@@ -79,6 +78,10 @@ const props = defineProps({
type: Boolean,
default: false,
},
wardListOptions: {
type: Array,
default: () => [],
},
});
const data = reactive({
@@ -94,7 +97,7 @@ const data = reactive({
const { queryParams, form, rules } = toRefs(data);
// Emits
const emits = defineEmits(['confirm', 'cancel', 'patientSelected', 'triggerSearch']);
const emits = defineEmits(['confirm', 'cancel', 'patientSelected']);
const total = ref(0);
// // v-model for drawer visibility
// const drawerVisible = defineModel('drawerVisible', {
@@ -153,7 +156,6 @@ function viewPatient(patient) {
console.log('View patient:', patient);
selectedPatient.value = patient; // 选中患者
emits('patientSelected', selectedPatient.value); // 发送选中的患者数据
emits('triggerSearch', patient.busNo); // 触发预交金查询事件
drawerVisible.value = false;
reset(); // 重置筛选条件
// 可以在这里做一些操作比如高亮行或者如果“查看”是选择并关闭则触发confirm
@@ -185,20 +187,7 @@ function show() {
console.log('show', props);
wardListOptions.value = props.wardListOptions;
drawerVisible.value = props.drawerVisible;
getWardList()
.then((res) => {
if (res.length > 0) {
wardListOptions.value = res.map((ward) => ({
label: ward.name,
value: ward.id,
}));
}
getList();
})
.catch((error) => {
console.error('获取病区列表失败:', error);
getList();
});
getList();
}
/**
@@ -206,8 +195,8 @@ function show() {
*/
function getList() {
console.log('queryParams', queryParams.value);
getDepositInfo(queryParams.value).then((res) => {
patientData.value = res.data?.records || [];
getDepositInfo().then((res) => {
patientData.value = res.data.records;
total.value = res.data.total;
});
}

View File

@@ -118,10 +118,7 @@ async function submit() {
refund(form.value).then((res) => {
if (res.code == 200) {
reset();
emit('close', {
status: 'success',
busNo: props.patientInfo?.busNo,
});
emit('close', 'success');
}
});
}

View File

@@ -139,7 +139,6 @@
ref="showPatientRef"
:wardListOptions="wardListOptions"
@patientSelected="handlePatientSelected"
@triggerSearch="handleTriggerSearch"
/>
<ChargeDialog
ref="chargeListRef"
@@ -179,6 +178,7 @@ const queryParams = ref({
pageNo: 1,
pageSize: 10,
searchKey: undefined, // 供应商名称
searchKey: 'ZY202507310001',
});
const tableRowClassName = ({ row, rowIndex }) => {
if (row.amount < 0) {
@@ -201,7 +201,6 @@ function getPatientInfo() {
}
console.log(queryParams.value, 'queryParams.value');
getDepositInfo({ busNo: queryParams.value.searchKey }).then((res) => {
queryParams.value.searchKey = '';
if (res.code == 200 && res.data.records[0].encounterId) {
patientInfo.value = res.data.records[0];
getDepositInfoPage({ encounterId: res.data.records[0].encounterId }).then((res) => {
@@ -241,12 +240,12 @@ function refund() {
/** 选择病人 */
function handlePatientSelected(row) {
// console.log(row, 'rowwwwwwwwhandlePatientSelected');
// queryParams.value.searchKey = row.admissionNo;
console.log(row, 'rowwwwwwwwhandlePatientSelected');
queryParams.value.searchKey = row.admissionNo;
patientInfo.value = row;
// nextTick(() => {
// getPatientInfo();
// });
nextTick(() => {
getPatientInfo();
});
}
/** 重置操作表单 */
function reset() {
@@ -287,19 +286,14 @@ function formatValue(value) {
*
* @returns {void} 无返回值
*/
function handleClose(data) {
function handleClose(str) {
openDialog.value = false;
openRefundDialog.value = false;
if (data?.status === 'success' && data?.busNo) {
queryParams.value.searchKey = data.busNo;
if (str === 'success') {
getPatientInfo();
proxy.$modal.msgSuccess('操作成功!');
}
}
//在院患者查询
function handleTriggerSearch(busNo) {
queryParams.value.searchKey = busNo; // 将选中患者的住院号赋值给搜索参数
getPatientInfo(); // 调用现有查询方法
}
</script>
<style lang="scss" scoped>

View File

@@ -1,166 +1,100 @@
import request from '@/utils/request';
import request from '@/utils/request'
/**
* 收费患者列表
*/
export function getList(queryParams) {
return request({
url: '/charge-manage/inpa-charge/encounter-patient-page',
method: 'get',
params: queryParams,
});
return request({
url: '/charge-manage/inpa-charge/encounter-patient-page',
method: 'get',
params: queryParams
})
}
/**
* 收费患者列表 新
*/
export function getList1(queryParams) {
return request({
url: '/charge-manage/inpatient-charge/encounter-patient-page',
method: 'get',
params: queryParams,
});
}
/**
* 患者处方列表
*/
export function getChargeList(encounterId) {
return request({
url: '/charge-manage/inpatient-charge/patient-prescription?encounterId=' + encounterId,
method: 'get',
});
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/inpatient-charge/self-pay?encounterId=' + encounterId,
method: 'put',
});
return request({
url: '/charge-manage/inpa-charge/self-pay?encounterId=' + encounterId,
method: 'put',
})
}
/**
* 自费转医保
*/
export function changeToMedicalInsurance(encounterId) {
return request({
url: '/charge-manage/charge/medical-insurance?encounterId=' + encounterId,
method: 'put',
});
return request({
url: '/charge-manage/inpa-charge/medical-insurance?encounterId=' + encounterId,
method: 'put',
})
}
/**
* 学生医保转学生自
*/
export function changeStudentPayTosStudentSelf(encounterId) {
return request({
url: '/charge-manage/charge/student-self-pay?encounterId=' + encounterId,
method: 'put',
});
}
/**
* 学生自费转学生医保
*/
export function changeStudentSelfToStudentPay(encounterId) {
return request({
url: '/charge-manage/charge/student-yb-pay?encounterId=' + encounterId,
method: 'put',
});
}
/**
* 住院结算
*
*/
export function savePayment(data) {
return request({
url: '/payment/payment/inpa-pay',
method: 'post',
data: 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 init1() {
return request({
url: '/charge-manage/inpatient-charge/init',
method: 'get',
});
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,
});
return request({
url: '/payment/payment/inpa-pre-pay',
method: 'post',
data: data
})
}
/**
* 取消预结算
*/
export function unprecharge(data) {
return request({
url: '/payment/payment/inpa-un-pay',
method: 'post',
params: data,
});
return request({
url: '/payment/payment/unprecharge',
method: 'post',
params: data
})
}
/**
* 发耗材
*/
export function dispenseMedicalConsumables(data) {
return request({
url: '/pharmacy-manage/device-dispense/consumables-dispense',
method: 'put',
data: data,
});
}
/**
* 补打小票
*/
export function getChargeInfo(param) {
return request({
url: '/payment/bill/getDetail',
method: 'get',
params: param,
});
}
/**
* 微信支付
*/
export function wxPay(data) {
return request({
url: '/three-part/pay/pay-for',
method: 'post',
data: data,
});
}
/**
* 微信支付
*/
export function WxPayResult(data) {
return request({
url: '/three-part/pay/pay-query',
method: 'post',
data: data,
});
return request({
url: '/pharmacy-manage/medical-consumables-dispense/consumables-dispense',
method: 'put',
data: data
})
}

View File

@@ -1,11 +1,10 @@
<template>
<el-dialog
title="确认收费"
:title="props.paymentEnum == 1 ? '确认退费' : '确认收费'"
v-model="props.open"
width="700px"
append-to-body
destroy-on-close
@open="handleOpen"
@close="close"
>
<div v-loading="dialogLoading">
@@ -19,60 +18,47 @@
{{ props.totalAmount.toFixed(2) + ' 元' }}
</el-text>
</div>
<div class="amount-row">
<el-text size="large">折扣金额</el-text>
<el-text size="large" type="warning" class="amount">
{{ discountAmount.toFixed(2) + ' 元' }}
</el-text>
</div>
<!-- 自费支付 -->
<div class="payment-container">
<template v-for="(item, index) in formData.selfPay" :key="index">
<div v-show="item.payEnum != 220500" class="payment-item">
<span>支付方式</span>
<img
v-if="item.payEnum == 220100 || item.payEnum == 220200"
:src="imgs[item.payEnum == 220100 ? 0 : 1]"
style="width: 20px; height: 20px"
<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
v-model="item.payEnum"
placeholder="选择支付方式"
style="width: 160px"
@change="(value) => clearAmount(index, value)"
>
<el-option
v-for="payEnum in selfPayMethods"
:key="payEnum.value"
:label="payEnum.label"
:value="payEnum.value"
:disabled="isMethodDisabled(payEnum)"
/>
</el-select>
<span>支付金额</span>
<div class="suffix-wrapper">
<el-input-number
v-model="item.amount"
:precision="2"
:min="0"
:max="getMax(index)"
:controls="false"
placeholder="金额"
class="amount-input"
@change="handleAmountChange"
/>
<span class="suffix-text"></span>
</div>
<el-button
type="danger"
circle
:icon="Delete"
@click="removePayment(index)"
v-if="index > 0"
</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>
</template>
<el-button
type="danger"
circle
:icon="Delete"
@click="removePayment(index)"
v-if="index > 0"
/>
</div>
<div class="add-payment">
<el-button
type="primary"
@@ -86,29 +72,6 @@
金额已满足应收不可继续添加
</el-text>
</div>
<div style="margin-top: 10px" v-if="userStore.hospitalName == '长春市朝阳区中医院'">
<span>折扣</span>
<el-radio-group v-model="discountRadio" @change="handleDiscountChange">
<el-radio-button
v-for="item in charge_discount"
:key="item.value"
link
:label="item.label"
:value="item.value"
/>
</el-radio-group>
</div>
</div>
<div class="payment-item">
<span>{{ payTypeText }}支付</span>
<el-input
ref="txtCodeRef"
v-model="txtCode"
style="width: 300px"
:placeholder="payTypePlaceholder"
/>
<el-button link type="primary" @click="handleWxPay()">扫码支付</el-button>
<el-button link type="primary" @click="getWxPayResult()">查看结果</el-button>
</div>
<div>
<el-table :data="props.details" max-height="200" border>
@@ -130,7 +93,7 @@
<div class="summary">
<el-space :size="30">
<div class="summary-item">
<el-text type="info">实收合计</el-text>
<el-text type="info">{{ props.paymentEnum == 1 ? '退费合计:' : '收费合计:' }}</el-text>
<el-text type="success">{{ displayAmount + ' 元' }}</el-text>
</div>
<div class="summary-item">
@@ -142,10 +105,9 @@
</div>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="throttledGetList" :disabled="dialogLoading">
</el-button>
<!-- <el-button type="primary" @click="print()" :disabled="dialogLoading"> </el-button> -->
<el-button type="primary" @click="throttledGetList" :disabled="dialogLoading"
> </el-button
>
<el-button @click="close" :disabled="dialogLoading"> </el-button>
</div>
</template>
@@ -153,24 +115,12 @@
</template>
<script setup>
import {
savePayment,
unprecharge,
dispenseMedicalConsumables,
wxPay,
WxPayResult,
getChargeInfo,
} from './api';
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';
import { hiprint } from 'vue-plugin-hiprint';
import templateJson from './template.json';
import { pa } from 'element-plus/es/locales.mjs';
import image1 from '../../../../../assets/images/weixinzhifu.png';
import image2 from '../../../../../assets/images/zhifubaozhifu.png';
const imgs = ref([image1, image2]);
const props = defineProps({
open: {
type: Boolean,
@@ -194,43 +144,36 @@ const props = defineProps({
default: undefined,
},
chargeItemIds: {
type: Array,
default: () => [],
type: [],
default: [],
},
consumablesIdList: {
type: Array,
default: () => [],
type: [],
default: [],
},
chrgBchnoList: {
type: Array,
default: () => [],
type: [],
default: [],
},
details: {
type: Object,
default: undefined,
},
chargedItems: {
type: Array,
default: () => [],
paymentEnum: {
type: String,
},
newId: {
type: String,
default: '',
},
oldId: {
type: String,
default: '',
},
}
});
const { proxy } = getCurrentInstance();
const { charge_discount } = proxy.useDict('charge_discount');
const userStore = useUserStore();
const discountRadio = ref();
const discountAmount = ref(0);
const txtCode = ref('');
const formData = reactive({
totalAmount: 0,
selfPay: [{ payEnum: 220100, amount: 0.0, payLevelEnum: 2 }],
@@ -252,186 +195,154 @@ watch(
);
const emit = defineEmits(['close']);
let displayAmountTemp = 0;
async function printReceipt(param) {
console.log(param, 'param');
console.log(props.patientInfo, 'props.patientInfo');
// 打印小票
function printReceipt(param) {
let total = 0;
props.chargedItems.forEach((item) => {
total += item.totalPrice || 0;
});
// 构造一个新的对象,添加头 "data"
const result = {
data: [
{
...param,
// 基础支付类型
YB_FUND_PAY:
param.detail?.find((t) => t.payEnum === 100000)?.amount.toFixed(2) + ' 元' ?? 0, // 基金支付总
SELF_PAY: param.detail?.find((t) => t.payEnum === 200000)?.amount.toFixed(2) + ' 元' ?? 0, // 个人负担金额
OTHER_PAY: param.detail?.find((t) => t.payEnum === 300000)?.amount ?? 0, // 其他(如医院负担金额)
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.toFixed(2) + ' 元' ?? 0, // 基本医保统筹基金支出
YB_BC_FUND_AMOUNT:
param.detail?.find((t) => t.payEnum === 120000)?.amount.toFixed(2) + ' 元' ?? 0, // 补充医疗保险基金支出
YB_JZ_FUND_AMOUNT:
param.detail?.find((t) => t.payEnum === 130000)?.amount.toFixed(2) + ' 元' ?? 0, // 医疗救助基金支出
// YB_OTHER_AMOUNT: param.detail.find((t) => t.payEnum === 140000)?.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_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, // 公务员医疗补助
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, // 医院负担金额
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.toFixed(2) + ' 元' ?? 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.toFixed(2) + ' 元' ?? 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, // 余额
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.toFixed(2) + ' 元' ?? 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_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, // 个人现金支付金额(银联)
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, // 保健预支基金
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 + '门诊收费明细',
name: props.patientInfo.patientName, // 姓名
gender: props.patientInfo.genderEnum_enumText, // 性别
age: props.patientInfo.age, // 年龄
encounterBusNo: props.patientInfo.encounterBusNo, // 病例号
currentDate: currentDate.value, // 收费日期
chargedItems: props.chargedItems, // 收费项目
totalAmount: props.totalAmount.toFixed(2) + ' 元', // 应收金额
itemTotalAmount: total.toFixed(2) + ' 元', // 应收金额
displayAmount: displayAmountTemp + ' 元', // 实收金额
returnedAmount: returnedAmount.value + ' 元', // 应找零
userName: userStore.nickName,
},
],
// feeDetial: param.detail, //收费项目,后端还未返回
};
const printElements = templateJson;
var hiprintTemplate = new hiprint.PrintTemplate({ template: printElements }); // 定义模板
hiprintTemplate.print2(result.data[0], {
printer: 'xp',
title: '门诊收费结算单',
});
// 将对象转换为 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);
function handleWxPay() {
wxPay({
txtCode: txtCode.value,
chargeItemIds: props.chargeItemIds,
encounterId: props.patientInfo.encounterId,
id: props.paymentId,
paymentDetails: formData.selfPay,
ybMdtrtCertType: props.userCardInfo.psnCertType,
busiCardInfo: props.userCardInfo.busiCardInfo,
});
}
function getWxPayResult() {
WxPayResult({
txtCode: txtCode.value,
chargeItemIds: props.chargeItemIds,
encounterId: props.patientInfo.encounterId,
id: props.paymentId,
paymentDetails: formData.selfPay,
ybMdtrtCertType: props.userCardInfo.psnCertType,
busiCardInfo: props.userCardInfo.busiCardInfo,
});
}
function handleOpen() {
formData.totalAmount = props.totalAmount;
formData.selfPay[0].amount = props.totalAmount;
}
async function submit() {
displayAmountTemp = displayAmount.value;
console.log(parseFloat(displayAmount.value), 'parseFloat(displayAmount.value)');
console.log(formData.totalAmount, 'formData.totalAmount');
let amount = formData.selfPay
.reduce((sum, item) => {
return sum + (Number(item.amount) || 0);
}, 0)
.toFixed(2);
if (parseFloat(amount) < formData.totalAmount.toFixed(2)) {
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;
console.log(props.newId, props.oldId);
savePayment({
chargeItemIds: props.chargeItemIds,
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,
newId: props.newId,
oldId: props.oldId,
})
.then((res) => {
if (res.code == 200) {
getChargeInfo({ paymentId: props.paymentId }).then((res) => {
// printReceipt(res.data);
});
formData.selfPay = [{ payEnum: 220100, amount: 0.0, payLevelEnum: 2 }];
emit('close', 'success', res.msg);
emit('refresh'); // 发送刷新事件给父组件
// 长春市朝阳区中医院自动发耗材
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);
}
@@ -442,51 +353,13 @@ async function submit() {
});
}
/** 打印收费结算单 */
async function print() {
console.log('patientInfo', props.patientInfo);
console.log('category', props.category);
console.log('totalAmount', props.totalAmount);
console.log('chargeItemIds', props.chargeItemIds);
console.log('consumablesIdList', props.consumablesIdList);
console.log('userCardInfo', props.userCardInfo);
console.log('paymentId', props.paymentId);
console.log('details', props.details);
console.log('chargedItems', props.chargedItems);
const result = {
data: [
{
name: props.patientInfo.patientName, // 姓名
gender: props.patientInfo.genderEnum_enumText, // 性别
age: props.patientInfo.age, // 年龄
encounterBusNo: props.patientInfo.encounterBusNo, // 病例号
currentDate: currentDate.value, // 收费日期
chargedItems: props.chargedItems, // 收费项目
totalAmount: props.totalAmount.toFixed(2) + ' 元', // 应收金额
displayAmount: displayAmount.value + ' 元', // 实收金额
returnedAmount: returnedAmount.value + ' 元', // 应找零
},
],
};
console.log(result, '==result.data==');
const printElements = templateJson;
var hiprintTemplate = new hiprint.PrintTemplate({ template: printElements }); // 定义模板
const printerList = hiprintTemplate.getPrinterList();
console.log(hiprintTemplate, '打印机列表');
hiprintTemplate.print2(result.data[0], {
title: '门诊收费结算单',
});
}
const currentDate = ref(new Date().toLocaleString());
const selfPayMethods = [
{ label: '现金', value: 220400, isWebPay: false },
{ label: '微信', value: 220100, isWebPay: true },
{ label: '支付宝', value: 220200, isWebPay: true },
{ label: '银联', value: 220300, isWebPay: true },
{ label: '优惠', value: 220500, isWebPay: false },
{ label: '现金', value: 220400 },
{ label: '微信', value: 220100 },
{ label: '支付宝', value: 220200 },
{ label: '银联', value: 220300 },
];
// 计算剩余可输入金额
@@ -508,36 +381,9 @@ const getMax = (index) => {
return formData.totalAmount - otherSum;
};
// 折扣计算
function handleDiscountChange(value) {
let amount = props.totalAmount * Number(value);
discountAmount.value = props.totalAmount - amount;
formData.selfPay = [
{ payEnum: 220100, amount: amount, payLevelEnum: 2 },
{ payEnum: 220500, amount: discountAmount.value, payLevelEnum: 2 },
];
}
// 检查支付方式是否已使用
const isMethodDisabled = (option) => {
if (formData.selfPay.length > 1) {
// 禁用已被选择的相同方式,避免重复选择
const selectedEnums = formData.selfPay.map((item) => item.payEnum);
if (selectedEnums.includes(option.value)) {
return true;
}
// 若已经选择了任一线上支付方式,则其他线上方式不可再选,仅允许现金等线下方式
const hasSelectedWebPay = selectedEnums.some((val) => {
const found = selfPayMethods.find((m) => m.value === val);
return found ? found.isWebPay === true : false;
});
if (hasSelectedWebPay && option.isWebPay) {
return true;
}
return false;
} else {
return false;
}
const isMethodDisabled = (payEnum) => {
return formData.selfPay.some((item) => item.payEnum === payEnum);
};
const handleAmountChange = () => {
@@ -555,31 +401,15 @@ const removePayment = (index) => {
formData.selfPay.splice(index, 1);
};
const payTypeText = ref('微信');
const payTypePlaceholder = computed(() => {
if (payTypeText.value === '现金') {
return '请输入现金金额';
}
return payTypeText.value + '支付二维码';
});
const clearAmount = (index, value) => {
const selectedOption = selfPayMethods.find((item) => item.value === value);
if (selectedOption) {
payTypeText.value = selectedOption.label;
}
const clearAmount = (index) => {
// formData.selfPay[index].amount = 0;
};
// 计算属性
const displayAmount = computed(() => {
return formData.selfPay
.reduce((sum, item) => {
if (item.payEnum !== 220500) {
return sum + (Number(item.amount) || 0);
}
return sum;
}, 0)
.toFixed(2);
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) {
@@ -597,25 +427,8 @@ function close() {
// proxy.$modal.msgError(res.message);
// }
// });
txtCode.value = '';
formData.totalAmount = 0;
formData.selfPay = [{ payEnum: 220100, amount: 0.0, payLevelEnum: 2 }];
formData.medicalInsurance = {
account: '',
poolPay: 0,
personalPay: 0,
};
// 重置折扣相关状态
discountRadio.value = undefined;
discountAmount.value = 0;
emit('close');
}
defineExpose({
printReceipt,
});
</script>
<style scoped>

View File

@@ -1,433 +0,0 @@
{
"panels": [
{
"index": 0,
"name": 1,
"paperType": "自定义",
"height": 160,
"width": 80,
"paperHeader": 0,
"paperFooter": 450.7086614173229,
"paperNumberDisabled": true,
"paperNumberContinue": true,
"expandCss": "",
"overPrintOptions": {
"content": "",
"opacity": 0.7,
"type": 1
},
"watermarkOptions": {
"content": "",
"fillStyle": "rgba(184, 184, 184, 0.3)",
"fontSize": "36px",
"rotate": 25,
"width": 413,
"height": 310,
"timestamp": false,
"format": "YYYY-MM-DD HH:mm"
},
"panelLayoutOptions": {
"layoutType": "column",
"layoutRowGap": 0,
"layoutColumnGap": 0
},
"printElements": [
{
"options": {
"left": 45,
"top": 15,
"height": 16.5,
"width": 142.5,
"title": "长春市朝阳区中医院门诊收费结算单",
"coordinateSync": false,
"widthHeightSync": false,
"fontWeight": "bold",
"letterSpacing": 0.75,
"textAlign": "center",
"qrCodeLevel": 0,
"fontSize": 12
},
"printElementType": {
"title": "文本",
"type": "text"
}
},
{
"options": {
"left": 15,
"top": 39,
"height": 14,
"width": 80,
"title": "姓名",
"coordinateSync": false,
"widthHeightSync": false,
"qrCodeLevel": 0,
"field": "name"
},
"printElementType": {
"title": "文本",
"type": "text"
}
},
{
"options": {
"left": 99,
"top": 39,
"height": 14,
"width": 60,
"title": "性别",
"coordinateSync": false,
"widthHeightSync": false,
"qrCodeLevel": 0,
"field": "gender"
},
"printElementType": {
"title": "文本",
"type": "text"
}
},
{
"options": {
"left": 163.5,
"top": 39,
"height": 14,
"width": 60,
"title": "年龄",
"coordinateSync": false,
"widthHeightSync": false,
"qrCodeLevel": 0,
"field": "age"
},
"printElementType": {
"title": "文本",
"type": "text"
}
},
{
"options": {
"left": 15,
"top": 60,
"height": 14,
"width": 120,
"title": "病人类型",
"coordinateSync": false,
"widthHeightSync": false,
"qrCodeLevel": 0,
"field": "medType"
},
"printElementType": {
"title": "文本",
"type": "text"
}
},
{
"options": {
"left": 13.5,
"top": 82.5,
"height": 14,
"width": 120,
"title": "病历号",
"coordinateSync": false,
"widthHeightSync": false,
"qrCodeLevel": 0,
"field": "encounterBusNo"
},
"printElementType": {
"title": "文本",
"type": "text"
}
},
{
"options": {
"left": 13.5,
"top": 102,
"height": 37.5,
"width": 208.5,
"title": "undefined+beforeDragIn",
"field": "chargedItems",
"coordinateSync": false,
"widthHeightSync": false,
"textAlign": "center",
"tableBodyRowBorder": "border",
"tableBodyCellBorder": "border",
"columns": [
[
{
"title": "项目名称",
"titleSync": false,
"tableQRCodeLevel": 0,
"tableSummaryTitle": true,
"tableSummary": "",
"width": 61.93559159547676,
"field": "itemName",
"checked": true,
"columnId": "itemName",
"fixed": false,
"rowspan": 1,
"colspan": 1
},
{
"title": "单价",
"titleSync": false,
"tableQRCodeLevel": 0,
"tableSummaryTitle": true,
"tableSummary": "",
"width": 37.1097311853845,
"field": "unitPrice",
"checked": true,
"columnId": "unitPrice",
"fixed": false,
"rowspan": 1,
"colspan": 1
},
{
"title": "数量",
"titleSync": false,
"tableQRCodeLevel": 0,
"tableSummaryTitle": true,
"tableSummary": "",
"width": 37.12571954521698,
"field": "quantityValue",
"checked": true,
"columnId": "quantityValue",
"fixed": false,
"rowspan": 1,
"colspan": 1
},
{
"title": "总价",
"titleSync": false,
"tableQRCodeLevel": 0,
"tableSummaryTitle": true,
"tableSummary": "",
"width": 35.15170328143829,
"field": "totalPrice",
"checked": true,
"columnId": "totalPrice",
"fixed": false,
"rowspan": 1,
"colspan": 1
},
{
"title": "费用性质",
"titleSync": false,
"tableQRCodeLevel": 0,
"tableSummaryTitle": true,
"tableSummary": "",
"width": 37.17725439248345,
"field": "contractName",
"checked": true,
"columnId": "contractName",
"fixed": false,
"rowspan": 1,
"colspan": 1
},
{
"title": "收费名称",
"titleSync": false,
"tableQRCodeLevel": 0,
"tableSummaryTitle": true,
"tableSummary": "",
"width": 56.86712269302148,
"field": "chargeItem",
"checked": false,
"columnId": "chargeItem",
"fixed": false,
"rowspan": 1,
"colspan": 1
}
]
]
},
"printElementType": {
"title": "表格",
"type": "table",
"editable": true,
"columnDisplayEditable": true,
"columnDisplayIndexEditable": true,
"columnTitleEditable": true,
"columnResizable": true,
"columnAlignEditable": true,
"isEnableEditField": true,
"isEnableContextMenu": true,
"isEnableInsertRow": true,
"isEnableDeleteRow": true,
"isEnableInsertColumn": true,
"isEnableDeleteColumn": true,
"isEnableMergeCell": true
}
},
{
"options": {
"left": 99,
"top": 147,
"height": 15,
"width": 123,
"title": "合计金额",
"field": "itemTotalAmount",
"coordinateSync": false,
"widthHeightSync": false,
"qrCodeLevel": 0
},
"printElementType": {
"title": "文本",
"type": "text"
}
},
{
"options": {
"left": 6,
"top": 171,
"height": 14,
"width": 108,
"title": "应收金额",
"coordinateSync": false,
"widthHeightSync": false,
"qrCodeLevel": 0,
"field": "totalAmount"
},
"printElementType": {
"title": "文本",
"type": "text"
}
},
{
"options": {
"left": 124.5,
"top": 171,
"height": 14,
"width": 97.5,
"title": "实收金额",
"coordinateSync": false,
"widthHeightSync": false,
"qrCodeLevel": 0,
"field": "displayAmount"
},
"printElementType": {
"title": "文本",
"type": "text"
}
},
{
"options": {
"left": 6,
"top": 193.5,
"height": 14,
"width": 108,
"title": "全自费金额",
"coordinateSync": false,
"widthHeightSync": false,
"qrCodeLevel": 0,
"field": "FULAMT_OWNPAY_AMT"
},
"printElementType": {
"title": "文本",
"type": "text"
}
},
{
"options": {
"left": 124.5,
"top": 193.5,
"height": 13.5,
"width": 97.5,
"title": "医保政策金额",
"coordinateSync": false,
"widthHeightSync": false,
"qrCodeLevel": 0,
"field": "INSCP_SCP_AMT"
},
"printElementType": {
"title": "文本",
"type": "text"
}
},
{
"options": {
"left": 6,
"top": 216,
"height": 14,
"width": 108,
"title": "基金支付",
"coordinateSync": false,
"widthHeightSync": false,
"qrCodeLevel": 0,
"field": "YB_FUND_PAY"
},
"printElementType": {
"title": "文本",
"type": "text"
}
},
{
"options": {
"left": 124.5,
"top": 216,
"height": 13.5,
"width": 97.5,
"title": "统筹支付",
"coordinateSync": false,
"widthHeightSync": false,
"qrCodeLevel": 0,
"field": "YB_TC_FUND_AMOUNT"
},
"printElementType": {
"title": "文本",
"type": "text"
}
},
{
"options": {
"left": 6,
"top": 240,
"height": 14,
"width": 216,
"title": "个人医保账户支付",
"coordinateSync": false,
"widthHeightSync": false,
"qrCodeLevel": 0,
"field": "SELF_YB_ZH_PAY"
},
"printElementType": {
"title": "文本",
"type": "text"
}
},
{
"options": {
"left": 6,
"top": 268.5,
"height": 14,
"width": 106.5,
"title": "收费员",
"coordinateSync": false,
"widthHeightSync": false,
"qrCodeLevel": 0,
"field": "userName"
},
"printElementType": {
"title": "文本",
"type": "text"
}
},
{
"options": {
"left": 6,
"top": 294,
"height": 14,
"width": 214.5,
"title": "收费时间",
"coordinateSync": false,
"widthHeightSync": false,
"qrCodeLevel": 0,
"field": "currentDate"
},
"printElementType": {
"title": "文本",
"type": "text"
}
}
]
}
]
}

View File

@@ -12,7 +12,7 @@
<div style="width: 100%">
<el-input
v-model="queryParams.searchKey"
placeholder="请输入患者名/住院号/床号"
placeholder="请输入患者名/病历号"
clearable
style="width: 48%; margin-bottom: 10px; margin-right: 10px"
@keyup.enter="getPatientList"
@@ -22,9 +22,9 @@
</template>
</el-input>
<el-select
v-model="queryParams.encounterStatus"
v-model="queryParams.statusEnum"
style="width: 48%; margin-bottom: 10px; margin-right: 10px"
placeholder="结算状态"
placeholder="收费状态"
@change="getPatientList"
>
<el-option
@@ -44,7 +44,6 @@
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">
搜索
@@ -58,17 +57,14 @@
@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="encounterBusNo" />
<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-column label="收费状态" align="center" prop="statusEnum_enumText" />
</el-table>
</div>
</el-card>
@@ -77,39 +73,21 @@
<template #header>
<span style="vertical-align: middle">基本信息</span>
</template>
<el-descriptions :column="5">
<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.organizationName }}
</el-descriptions-item> -->
<!-- <el-descriptions-item label="床号:">
{{ patientInfo.bedNo }}
<el-descriptions-item label="合同类型:">
{{ patientInfo.categoryEnum_enumText }}
</el-descriptions-item>
<el-descriptions-item label="就诊时间:">
{{ formatDateStr(patientInfo.receptionTime, 'YYYY-MM-DD HH:mm:ss') }}
</el-descriptions-item> -->
<!-- <el-descriptions-item label="身份证号:">{{ patientInfo.idCard }}</el-descriptions-item> -->
<!-- <el-descriptions-item label="手机号">{{ patientInfo.name }}</el-descriptions-item>
<el-descriptions-item label="出生日期">{{ patientInfo.name }}</el-descriptions-item> -->
</el-descriptions>
</el-card>
<el-card>
<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">
<el-card style="min-width: 1100px">
<template #header>
<span style="vertical-align: middle">收费项目</span>
</template>
@@ -148,22 +126,6 @@
>
自费转医保
</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
>
@@ -171,35 +133,25 @@
<el-table
ref="chargeListRef"
height="530"
:data="chargeFilterList"
:data="chargeList"
row-key="id"
@selection-change="handleSelectionChange"
v-loading="chargeLoading"
:span-method="objectSpanMethod"
border
>
<el-table-column type="selection" :selectable="checkSelectable" width="55" />
<el-table-column label="单据号" align="center" prop="busNo" width="180" />
<el-table-column label=" 开立科室" align="center" prop="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">
<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>
<el-tag
:type="scope.row.statusEnum === 1 ? 'default' : 'success'"
disable-transitions
>
{{ scope.row.statusEnum_enumText }}
</el-tag>
</template>
@@ -210,66 +162,10 @@
</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"
@@ -280,122 +176,66 @@
:chrgBchnoList="chrgBchnoList"
:userCardInfo="userCardInfo"
:paymentId="paymentId"
:details="details"
:chargedItems="chargedItems"
@refresh="getPatientList"
:newId="newId"
:oldId="oldId"
:details="details"
:paymentEnum="paymentEnum"
/>
</div>
</template>
<script setup name="ClinicCharge">
import {
getList1,
getList,
getChargeList,
changeToSelfPay,
changeToMedicalInsurance,
init1,
init,
precharge,
getChargeInfo,
changeStudentPayTosStudentSelf,
changeStudentSelfToStudentPay,
} 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';
import { onMounted } from 'vue';
const { proxy } = getCurrentInstance();
const userStore = useUserStore();
const queryParams = ref({
pageNum: 1,
pageSize: 50,
encounterStatus: 4,
statusEnum: 1,
});
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 consumablesIdList = 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 newId = ref('');
const oldId = ref('');
const paymentEnum = ref(1);
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 }
@@ -405,7 +245,7 @@ function handleSelectionChange(selection) {
}
function handleTotalAmount() {
totalAmounts.value = selectedRows.value.reduce((accumulator, currentRow) => {
return new Decimal(accumulator).add(currentRow.totalPrice.toFixed(2) || 0);
return accumulator + (Number(currentRow.totalPrice) || 0);
}, 0);
}
getPatientList();
@@ -421,23 +261,20 @@ function getPatientList() {
queryParams.value.startTimeSTime = undefined;
queryParams.value.startTimeETime = undefined;
}
getList1(queryParams.value).then((res) => {
console.log('患者列表', res);
patientList.value = res.data.records;
getList(queryParams.value).then((res) => {
patientList.value = res.data.data.records;
});
}
function initOption() {
init1().then((res) => {
console.log('初始化收费项目状态', res);
chargeStatusOptions.value = res.data.encounterStatusOptions;
console.log('res.data.chargeItemStatusOptions======>', JSON.stringify(res.data));
init().then((res) => {
chargeStatusOptions.value = res.data.chargeItemStatusOptions;
});
}
function checkSelectable(row, index) {
// 已结算时禁用选择框
return row.statusEnum == 1 || row.statusEnum == 2;
return row.statusEnum === 1;
}
/**
@@ -447,7 +284,8 @@ function clickRow(row) {
patientInfo.value = row;
chargeLoading.value = true;
encounterId.value = row.encounterId;
getChargeList(row.encounterId).then((res) => {
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;
@@ -461,7 +299,7 @@ function handleClose(value, msg) {
if (value == 'success') {
proxy.$modal.msgSuccess(msg);
chargeLoading.value = true;
getChargeList(patientInfo.value.encounterId).then((res) => {
getChargeList({encounterId: patientInfo.value.encounterId, startTime:date, endTime: formatDateStr(new Date(), 'YYYYMMDD'),}).then((res) => {
chargeList.value = res.data;
setTimeout(() => {
chargeLoading.value = false;
@@ -470,7 +308,7 @@ function handleClose(value, msg) {
}
}
const consumablesIdList = ref([]);
// 确认收费
function confirmCharge() {
let selectRows = chargeListRef.value.getSelectionRows();
@@ -481,7 +319,6 @@ function confirmCharge() {
chargeItemIdList.value = selectRows.map((item) => {
return item.id;
});
//wor_device_request 器材
consumablesIdList.value = selectRows
.filter((item) => {
return item.serviceTable == 'wor_device_request';
@@ -489,7 +326,6 @@ function confirmCharge() {
.map((item) => {
return item.id;
});
chargedItems.value = selectRows;
// totalAmount.value = selectRows.reduce((accumulator, currentRow) => {
// return accumulator + (currentRow.totalPrice || 0);
@@ -500,18 +336,21 @@ function confirmCharge() {
chargeItemIds: chargeItemIdList.value,
}).then((res) => {
if (res.code == 200) {
const item = res.data.paymentRecDetailDtoList.find((i) => {
return i.payEnum == 220000;
});
totalAmount.value = item?.amount;
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;
// 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);
}
@@ -524,172 +363,161 @@ 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
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 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) {
paymentId.value = res.data.id;
totalAmount.value = res.data.paymentRecDetailDtoList.find(
(item) => item.payEnum == 220000
).amount;
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';
// 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;
})
.map((item) => {
return item.id;
.catch(() => {
readCardLoading.value = false;
})
.finally(() => {
readCardLoading.value = false;
});
openDialog.value = true;
} else {
proxy.$modal.msgError(res.msg);
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;
}
} catch (error) {
console.error('调用失败:', error);
readCardLoading.value = false;
}
// }
}
/**
@@ -713,80 +541,6 @@ function patToMedicalInsurance() {
}
});
}
/**
* 学生医保转学生自费
*/
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>
</style>

View File

@@ -23,14 +23,8 @@
</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-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>
@@ -52,12 +46,7 @@
<el-row>
<el-col :span="8">
<el-form-item label="重复住院">
<el-switch
inline-prompt
v-model="formData.isRepeatHospitalization"
active-text=""
inactive-text=""
/>
<el-switch inline-prompt v-model="formData.isRepeatHospitalization" active-text="是" inactive-text="否" />
</el-form-item>
</el-col>
<el-col :span="8">
@@ -86,12 +75,7 @@
</el-col>
<el-col :span="8">
<el-form-item label="急诊标志">
<el-switch
inline-prompt
v-model="formData.isEmergency"
active-text=""
inactive-text=""
/>
<el-switch inline-prompt v-model="formData.isEmergency" active-text="是" inactive-text="否" />
</el-form-item>
</el-col>
<el-col :span="8">
@@ -113,11 +97,9 @@
</div>
</template>
<script setup>
<script setup >
import { ref } from 'vue';
defineOptions({
name: 'YbregisterEdit',
});
// interface FormData {
// medicalType: string;
// diseaseName: string;
@@ -159,6 +141,7 @@ defineOptions({
const handleSubmit = () => {
// 处理表单提交
};
</script>

View File

@@ -1,12 +1,12 @@
import request from '@/utils/request';
import request from '@/utils/request'
// 获取住院信息初期数据列表
export function getInit(query) {
return request({
url: '/inpatient-manage/init',
method: 'get',
params: query,
});
params: query
})
}
// 获取住院信息 分页显示
@@ -22,8 +22,8 @@ export function getAdmissionPage(query) {
return request({
url: '/inhospital-charge/register/register-info',
method: 'get',
params: query,
});
params: query
})
}
// 住院无档登记
@@ -31,8 +31,8 @@ export function addAdmissionInfo(data) {
return request({
url: '/inpatient-manage/admission-information',
method: 'post',
data: data,
});
data: data
})
}
// 住院登记
@@ -40,8 +40,8 @@ export function admissionInfo(data) {
return request({
url: '/inpatient-manage/admission-information',
method: 'put',
data: data,
});
data: data
})
}
/**
@@ -51,18 +51,17 @@ export function getOrgList() {
return request({
url: '/base-data-manage/organization/organization',
method: 'get',
});
})
}
/**
* 查询病区下拉列表
*/
export function wardList({ orgId } = {}) {
export function wardList() {
return request({
url: '/inhospital-charge/register/ward-list',
method: 'get',
params: { orgId },
});
url: '/app-common/ward-list',
method: 'get'
})
}
/**
@@ -72,55 +71,56 @@ export function diagnosisInit() {
return request({
url: '/doctor-station/diagnosis/init',
method: 'get',
});
})
}
// 查询患者相关
export function patientlLists() {
return request({
url: '/patient-manage/information/init',
method: 'get',
});
method: 'get'
})
}
// 查询患者相关
export function doctorList(id) {
return request({
url: '/inpatient-manage/doctor-list?orgId=' + id,
method: 'get',
});
method: 'get'
})
}
// 查询患者相关
export function getPatientInfo(id, statusEnum) {
return request({
url: `/inpatient-manage/admission-one?id=${id}&statusEnum=${statusEnum}`,
method: 'get',
});
method: 'get'
})
}
// 获取患者基础信息
export function getPatientBasicInfo(patientId) {
return request({
url: `/inhospital-charge/register/patient-info?patientId=${patientId}`,
method: 'get',
});
method: 'get'
})
}
// 获取患者入院信息
export function getInHospitalInfo(encounterId) {
return request({
url: `/inhospital-charge/register/in-hospital-info?encounterId=${encounterId}`,
method: 'get',
});
method: 'get'
})
}
// 获取病区床位信息
export function getBedInfo(wardBusNo) {
return request({
url: `/inhospital-charge/register/beds-num?wardBusNo=${wardBusNo}`,
method: 'get',
});
method: 'get'
})
}
// 住院登记
@@ -128,8 +128,8 @@ export function registerInHospital(data) {
return request({
url: '/inhospital-charge/register/by-cashier',
method: 'post',
data: data,
});
data: data
})
}
// 无档登记
@@ -137,16 +137,16 @@ export function noFilesRegister(data) {
return request({
url: '/inhospital-charge/register/no-files',
method: 'post',
data: data,
});
data: data
})
}
// 表单初始化
export function patientFormInit() {
return request({
url: '/patient-manage/information/init',
method: 'get',
});
method: 'get'
})
}
// 合同
@@ -154,7 +154,7 @@ export function getContractList() {
return request({
url: '/app-common/contract-list',
method: 'get',
});
})
}
/**
@@ -164,31 +164,6 @@ export function getDiagnosisDefinitionList(queryParams) {
return request({
url: '/doctor-station/diagnosis/condition-definition-metadata',
method: 'get',
params: queryParams,
});
}
// 获取患者医保信息
export function gerPreInfo(userMaessage) {
return request({
url: '/yb-inpatient-request/inpatient-per-info',
method: 'post',
data: userMaessage,
});
}
// export function gerPreInfo(userMaessage) {
// return request({
// url: '/yb-request/per-info',
// method: 'post',
// params: userMaessage,
// });
// }
//获取省市医保字符串
export function getProvincesAndCities(encounterId) {
return request({
url: `/payment/bill/get-encounter-type?encounterId=${encounterId}`,
method: 'get',
});
}
params: queryParams
})
}

View File

@@ -56,7 +56,6 @@
:inHospitalInfo="inHospitalInfo"
title="登记"
:registrationType="registrationType"
:is-registered="false"
@okAct="patientRegisterOK"
@cancelAct="cancelAct"
:noFile="noFile"
@@ -128,12 +127,10 @@ const patientYbRegisterVisible = ref(false);
const patientRegisterOK = () => {
patientRegisterVisible.value = false;
queryParams.value.searchKey = '';
getList();
emits('okList');
};
const cancelAct = () => {
getList();
patientRegisterVisible.value = false;
};

View File

@@ -11,7 +11,7 @@
{{ isEditing ? '取消' : '编辑' }}
</div> -->
<div>
<el-radio-group v-model="typeCode" :disabled="props.isRegistered">
<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>
@@ -19,7 +19,6 @@
<span
@click="handleReadCard(typeCode)"
style="cursor: pointer; margin: 0 12px 0 30px; color: #409eff"
v-if="!props.isRegistered"
>
{{ '读卡' }}
</span>
@@ -39,22 +38,16 @@
<el-text truncated>患者姓名</el-text>
</el-col>
<el-col :span="4" class="patInfo-value">
<el-text truncated>{{ patientInfo?.patientName || '-' }}</el-text>
<el-text truncated>{{ patientInfo?.name || '-' }}</el-text>
</el-col>
<!-- <el-col :span="2" class="patInfo-label">
<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"
v-if="!props.isRegistered"
/>
</el-col> -->
<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">
@@ -80,7 +73,7 @@
<el-text truncated>年龄</el-text>
</el-col>
<el-col :span="4" class="patInfo-value">
<el-text truncated>{{ patientInfo?.age || '-' }}</el-text>
<el-text truncated>{{ patientInfo?.ageString || '-' }}</el-text>
</el-col>
</el-row>
<el-row class="patientInfos">
@@ -94,7 +87,7 @@
<el-text truncated>民族</el-text>
</el-col>
<el-col :span="4" class="patInfo-value">
<div>{{ getDictLabel(nationality_code, patientInfo?.nationalityCode) || '-' }}</div>
<div>{{ patientInfo?.nationalityCode || '-' }}</div>
</el-col>
<el-col :span="2" class="patInfo-label">
<el-text truncated>国籍</el-text>
@@ -146,7 +139,7 @@
<el-text truncated>病人来源</el-text>
</el-col>
<el-col :span="4" class="patInfo-value">
<div>{{ props.inHospitalInfo?.inHospitalOrgName || '-' }}</div>
<div>{{ patientInfo?.organizationId_dictText || '-' }}</div>
</el-col>
<el-col :span="2" class="patInfo-label">
<el-text truncated>单位名称</el-text>
@@ -157,37 +150,24 @@
</el-row>
</div>
<div v-else>
<PatientInfoForm ref="patientInfoFormRef" :is-view-mode="props.isRegistered" />
<PatientInfoForm ref="patientInfoFormRef" />
</div>
</div>
</template>
<script setup>
import { ref, reactive, watch, onMounted } from 'vue';
import { ref, reactive, watch } from 'vue';
import PatientInfoForm from './patientInfoForm.vue';
import { patientlLists, getOrgList, gerPreInfo } from './api';
import { invokeYbPlugin5001 } from '@/api/public';
import useUserStore from '@/store/modules/user';
import { useRouter } from 'vue-router';
import { patientlLists, getOrgList } from './api';
const { proxy } = getCurrentInstance();
const typeList = ref({});
const patientInfoFormRef = ref();
let userCardInfo = ref({});
const BusiCardInfo = ref('');
const userStore = useUserStore();
const router = useRouter();
const props = defineProps({
patientInfo: {
type: Object,
require: true,
default: () => ({}),
},
inHospitalInfo: {
type: Object,
default: () => ({}),
},
registrationType: {
type: [String, Boolean, Number], // 根据实际类型调整
default: null, // 或者 false、'' 等
@@ -201,25 +181,11 @@ const props = defineProps({
type: Boolean,
default: false,
},
//待入院,已入院区分
isRegistered: {
type: Boolean,
default: false,
},
inHospitalInfo: {
type: Object,
default: () => ({}),
required: false,
},
});
const emits = defineEmits(['onChangFeeType', 'carReading']);
const emits = defineEmits(['onChangFeeType']);
const registerRef = ref();
const typeCode = ref('01');
const organization = ref([]);
const { nationality_code } = proxy.useDict('nationality_code');
const readCardLoading = ref(false);
const loadingText = ref('正在读取...');
onMounted(() => {
getInitOptions();
@@ -276,185 +242,136 @@ const submitForm = async (callback) => {
}
});
};
const getDictLabel = (dictList, value) => {
if (!dictList || !value) return '';
const item = dictList.find((item) => item.value === value);
return item ? item.label : value;
};
async function handleReadCard(value) {
try {
// await CefSharp.BindObjectAsync('boundAsync');
// string url,
// string fixmedins_code,
// string businessType,
// string operatorCode,
// string operatorName,
// string officeId,
// string officeName
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 = null;
let jsonResult;
let cardInfo;
let userMessage = undefined;
// 调试日志检查patientInfo中的值
console.log('patientInfo:', props.patientInfo);
console.log('patientInfo中的id:', props.patientInfo?.id);
console.log('patientInfo中的encounterId:', props.patientInfo?.encounterId);
switch (value) {
case '01': // 电子凭证
// readCardLoading.value = true;
// await boundAsync
// .getInfoByQrCodeAsync(
// )
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: '财务科',
})
// 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) => {
readCardLoading.value = true;
loadingText.value = '正在读取...';
console.log(res);
jsonResult = res.data;
cardInfo = JSON.parse(JSON.stringify(jsonResult));
let message = JSON.parse(cardInfo.message);
console.log('patientInfo中的encounterId:', props.patientInfo);
const encounterId = props.inHospitalInfo.encounterId || '1993854019030441985';
console.log('1111111111111111111准备使用的encounterId:', encounterId);
userMessage = {
certType: '02', // 证件类型
certNo: message.data.idNo, // 身份证号
psnCertType: '02', // 居民身份证
encounterId: encounterId || '1993854019030441985',
};
userCardInfo = {
certType: '01', // 证件类型
certNo: message.data.idNo, // 身份证号
psnCertType: '01', // 居民身份证
busiCardInfo: message.data.ecToken, // 令牌
encounterId: encounterId || '1993854019030441985',
};
BusiCardInfo.value = message.data.ecToken;
console.log(BusiCardInfo.value);
emits('carReading', jsonResult);
})
.catch(() => {
readCardLoading.value = false;
});
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);
let message1 = JSON.parse(jsonResult);
// 从patientInfo中获取encounterId如果没有则尝试从住院号中获取
// const encounterId =
// props.patientInfo?.encounterId || props.patientInfo?.visitNo || props.patientInfo?.busNo;
// console.log('准备使用的encounterId:', encounterId);
userMessage = {
certType: '02', // 证件类型
certNo: message1.SocialSecurityNumber, // 身份证号
psnCertType: '02', // 居民身份证
encounterId: encounterId || '1993854019030441985',
};
userCardInfo = {
certType: '02', // 证件类型
certNo: message1.SocialSecurityNumber, // 身份证号
psnCertType: '02', // 居民身份证
busiCardInfo: message1.BusiCardInfo, //卡号
encounterId: encounterId || '1993854019030441985',
};
BusiCardInfo.value = message1.BusiCardInfo;
console.log(message1.BusiCardInfo);
emits('carReading', res.data);
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;
});
break;
case '99':
break;
}
} catch (error) {
console.error('调用失败:', error);
readCardLoading.value = false;
}
readCardLoading.value = true;
// 调试日志检查发送给gerPreInfo的参数
console.log('发送给gerPreInfo的参数:', userMessage);
if (userMessage && userMessage.certNo) {
gerPreInfo(userMessage)
.then((res) => {
console.log('gerPreInfo返回结果:', res);
if (res && res.code == 200 && res.data) {
form.patientId = res.data.id;
form.name = res.data.name;
form.age = res.data.age;
form.idCard = res.data.idCard;
form.card = res.data.id;
form.contractNo = res.data.contractBusNo;
form.genderEnum = res.data.genderEnum;
form.ybAreaNo = res.data.contractName;
form.encounterId = res.data.encounterId;
// 成功获取数据后跳转到 registerEdit 页面,并传递数据
// router.push({
// name: '/ybmanagement/inhospital/register/edit', // 需要根据实际路由名称调整
// params: {
// cardData: JSON.stringify(res.data), // 将完整数据作为参数传递
// cardType: value, // 卡类型
// },
// });
} else {
// 处理无有效数据的情况
ElMessage.error('未获取到有效的患者信息');
}
})
.catch((error) => {
console.error('gerPreInfo调用失败:', error);
})
.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');
};
// 无档登记收集信息
const getPatientForm = () => {
return patientInfoFormRef?.value?.form;
};
defineExpose({ submitForm, form, isEditing, getPatientForm });
</script>
@@ -487,4 +404,4 @@ defineExpose({ submitForm, form, isEditing, getPatientForm });
font-weight: 700 !important;
margin-bottom: 10px;
}
</style>
</style>

View File

@@ -210,9 +210,9 @@
v-model="form.deceasedDate"
type="datetime"
placeholder="请选择时间"
format="YYYY-MM-DD HH:mm:ss"
format="YYYY/MM/DD HH:mm:ss"
:disabled="isViewMode"
value-format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY/MM/DD HH:mm:ss"
/>
</el-form-item>
</el-col>
@@ -266,7 +266,6 @@ const data = reactive({
isViewMode: false,
form: {
typeCode: '01',
genderEnum: 0,
},
rules: {
name: [{ required: true, message: '姓名不能为空', trigger: 'change' }],

View File

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

View File

@@ -10,7 +10,6 @@
ref="registerRef"
label-width="80px"
:rules="rules"
:disabled="props.isRegistered"
>
<el-row :gutter="8">
<el-col :span="6">
@@ -29,7 +28,6 @@
clearable
style="width: 100%"
v-model="submitForm.inHospitalOrgId"
:disabled="props.isRegistered"
filterable
:data="organization"
:props="{
@@ -49,11 +47,7 @@
</el-col>
<el-col :span="6">
<el-form-item label="入院病区" prop="wardLocationId">
<el-select
:disabled="props.isRegistered || !submitForm.inHospitalOrgId"
v-model="submitForm.wardLocationId"
placeholder="请先选择入院科室"
>
<el-select :disabled="props.alreadyEdit" v-model="submitForm.wardLocationId">
<el-option
v-for="item in wardListOptions"
:key="item.id"
@@ -80,7 +74,6 @@
<el-form-item label="诊断类别" prop="medTypeCode">
<el-select
v-model="submitForm.medTypeCode"
:disabled="props.isRegistered"
placeholder="诊断类别"
clearable
filterable
@@ -108,7 +101,6 @@
<el-form-item label="入院诊断" prop="diagnosisDefinitionId">
<el-select
v-model="submitForm.diagnosisDefinitionId"
:disabled="props.isRegistered"
placeholder="入院诊断"
clearable
filterable
@@ -132,11 +124,11 @@
</el-col>
<el-col :span="6">
<el-form-item label="患者病情">
<el-select v-model="submitForm.priorityEnum" :disabled="props.isRegistered">
<el-select v-model="submitForm.priorityEnum">
<el-option
v-for="item in props.initOptions.priorityLevelOptionOptions"
v-for="item in props.initOptions.priorityEnumList"
:key="item.value"
:label="item.label"
:label="item.info"
:value="item.value"
/>
</el-select>
@@ -144,7 +136,7 @@
</el-col>
<el-col :span="6">
<el-form-item label="入院类型" prop="admitSourceCode">
<el-select v-model="submitForm.admitSourceCode" :disabled="props.isRegistered">
<el-select v-model="submitForm.admitSourceCode">
<el-option
v-for="item in admit_source_code"
:key="item.value"
@@ -156,7 +148,7 @@
</el-col>
<el-col :span="6">
<el-form-item label="入院方式" prop="inWayCode">
<el-select v-model="submitForm.inWayCode" :disabled="props.isRegistered">
<el-select v-model="submitForm.inWayCode">
<el-option
v-for="item in in_way_code"
:key="item.value"
@@ -172,7 +164,6 @@
v-model="submitForm.contractNo"
placeholder="费用性质"
clearable
:disabled="props.isRegistered"
@change="getValue"
>
<el-option
@@ -188,7 +179,6 @@
<el-form-item label="入院日期" prop="startTime">
<el-date-picker
v-model="submitForm.startTime"
:disabled="props.isRegistered"
value-format="YYYY-MM-DD HH:mm:ss"
type="date"
placeholder="请选择日期"
@@ -208,7 +198,6 @@ import {
getBedInfo,
getContractList,
getDiagnosisDefinitionList,
getProvincesAndCities,
} from './api';
const { proxy } = getCurrentInstance();
const { in_way_code, admit_source_code, med_type } = proxy.useDict(
@@ -235,7 +224,7 @@ const props = defineProps({
require: true,
default: () => ({}),
},
isRegistered: {
alreadyEdit: {
type: Boolean,
default: false,
},
@@ -250,7 +239,6 @@ const wardListOptions = ref([]);
const contractList = ref([]);
const verificationStatusOptions = ref([]);
const diagnosisDefinitionList = ref([]);
const wardLoading = ref(false);
const rules = reactive({
inHospitalOrgId: [
{
@@ -280,52 +268,15 @@ const rules = reactive({
trigger: ['blur', 'change'],
},
],
// diagnosisDesc: [
// {
// required: true,
// message: '诊断描述未填写',
// trigger: ['blur', 'change'],
// },
// ],
diagnosisDesc: [
{
required: true,
message: '诊断描述未填写',
trigger: ['blur', 'change'],
},
],
});
//获取省市医保字符串
const medicalInsuranceTitle = ref('');
// 暴露给父组件使用
// defineExpose({
// medicalInsuranceTitle,
// });
const getProvincesAndCitiesInfo = async () => {
try {
if (inHospitalInfo.encounterId) {
const res = await getProvincesAndCities(props.inHospitalInfo.encounterId);
// console.log('获取省市医保字符串', res);
if (res && res.code == 200) {
// 确保有数据时才更新
medicalInsuranceTitle.value = res.data?.insutype || res.data || '';
}
}
} catch (error) {
// 静默处理错误,确保页面不会显示错误信息
console.error('获取医保省市信息失败:', error);
}
};
onMounted(() => {
getProvincesAndCitiesInfo();
});
// 监听inHospitalInfo.encounterId的变化在弹窗打开时重新调用接口
watch(
() => props.inHospitalInfo.encounterId,
(newEncounterId) => {
if (newEncounterId) {
getProvincesAndCitiesInfo();
}
},
{ immediate: true }
);
/* 提交表单 */
const submitForm = reactive({
inHospitalOrgId: props.inHospitalInfo.inHospitalOrgId,
@@ -338,50 +289,25 @@ const submitForm = reactive({
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);
// }
// }
// );
/* 科室 病区 */
watch(
() => submitForm.wardLocationId,
(newWardId) => {
if (newWardId && wardListOptions.value.length > 0) {
const selectedWard = wardListOptions.value.find((item) => item.id === newWardId);
if (selectedWard) {
handleWardClick(selectedWard);
() => submitForm.inDocterWorkGroupCode,
(newValue) => {
if (newValue) {
if (newValue == '') {
submitForm.wardLocationId = '';
}
} else {
submitForm.totalBedsNum = undefined;
submitForm.idleBedsNum = undefined;
submitForm.wardLocationId = '';
}
},
{ immediate: true }
}
);
watch(
() => props.isRegistered,
(newVal) => {
if (newVal) {
// 已登记状态可以做一些数据锁定操作
} else {
init();
() => submitForm.inNurseDeptCode,
(newValue) => {
if (newValue) {
getBedInfo(newValue);
}
}
);
@@ -389,51 +315,25 @@ watch(
onMounted(() => {
getInitOptions();
setValue();
setDefaultAdmitSource();
if (submitForm.inHospitalOrgId) {
handleNodeClick({ id: submitForm.inHospitalOrgId });
}
});
const setDefaultAdmitSource = () => {
if (props.noFile) return;
const defaultItem = admit_source_code.value.find((item) => item.value === '1');
if (defaultItem) {
submitForm.admitSourceCode = props.inHospitalInfo?.admitSourceCode || defaultItem.value;
}
};
function handleWardClick(item) {
submitForm.wardBusNo = item.busNo;
submitForm.totalBedsNum = undefined;
submitForm.idleBedsNum = undefined;
getBedInfo(submitForm.wardBusNo)
.then((res) => {
if (res.data) {
submitForm.totalBedsNum = res.data.totalBedsNum;
submitForm.idleBedsNum = res.data.idleBedsNum;
} else {
submitForm.totalBedsNum = 0;
submitForm.idleBedsNum = 0;
}
})
.catch((err) => {
console.error('查询病床失败:', err);
submitForm.totalBedsNum = undefined;
submitForm.idleBedsNum = undefined;
});
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
organization.value = res.data.records[0].children.filter(
(record) => record.typeEnum === 2 && record.classEnum === 2
);
organization.value = res.data.records;
});
// if (!props.noFile) {
// wardList().then((res) => {
// wardListOptions.value = res.data;
// });
// }
if (!props.noFile) {
wardList().then((res) => {
wardListOptions.value = res.data;
});
}
diagnosisInit().then((res) => {
verificationStatusOptions.value = res.data.verificationStatusOptions;
});
@@ -450,40 +350,15 @@ function getDiagnosisInfo(value) {
}
function handleNodeClick(orgInfo) {
submitForm.wardLocationId = undefined; // 切换科室时,先清空原有病区
submitForm.totalBedsNum = undefined;
submitForm.idleBedsNum = undefined;
wardListOptions.value = []; // 先清空列表,避免旧数据残留
wardLoading.value = true;
wardList({ orgId: orgInfo.id })
.then((res) => {
wardListOptions.value = res.data || [];
if (wardListOptions.value.length > 0 && !props.inHospitalInfo.wardLocationId) {
submitForm.wardLocationId = wardListOptions.value[0].id;
const defaultWard = wardListOptions.value.find(
(item) => item.id === submitForm.wardLocationId
);
if (defaultWard) {
handleWardClick(defaultWard);
}
}
})
.catch((err) => {
console.error('加载病区失败:', err);
wardListOptions.value = [];
})
.finally(() => {
wardLoading.value = false;
});
wardList({ orgId: orgInfo.id }).then((res) => {
wardListOptions.value = res.data;
});
}
function handleChange(value) {
if (!value) {
wardListOptions.value = [];
submitForm.wardLocationId = undefined;
submitForm.totalBedsNum = undefined;
submitForm.idleBedsNum = undefined;
wardLoading.value = false; // 同步停止加载
}
}
@@ -510,7 +385,7 @@ function setValue() {
submitForm.ambDiagnosisName = props.inHospitalInfo?.ambDiagnosisName;
submitForm.priorityEnum = props.inHospitalInfo?.priorityEnum;
submitForm.priorityEnum_enumText = props.inHospitalInfo?.priorityEnum_enumText;
// submitForm.admitSourceCode = props.inHospitalInfo?.admitSourceCode;
submitForm.admitSourceCode = props.inHospitalInfo?.admitSourceCode;
submitForm.admitSourceCode_dictText = props.inHospitalInfo?.admitSourceCode_dictText;
submitForm.inWayCode = props.inHospitalInfo?.inWayCode;
submitForm.inWayCode_dictText = props.inHospitalInfo?.inWayCode_dictText;
@@ -531,13 +406,10 @@ const validateData = async (callback) => {
};
const init = () => {
if (!props.isRegistered) {
// 只有待登记状态才重置
submitForm.inDocterWorkGroupCode = '';
submitForm.wardLocationId = '';
}
submitForm.inDocterWorkGroupCode = '';
submitForm.wardLocationId = '';
};
defineExpose({ validateData, submitForm, init, medicalInsuranceTitle });
defineExpose({ validateData, submitForm, init });
</script>
<style lang="scss" scoped>
.registerForm-container {

View File

@@ -22,6 +22,7 @@ const props = defineProps({});
const state = reactive({});
defineExpose({ state });
const activeName = ref('first');
</script>
<style lang="scss" scoped>
.sds {

View File

@@ -2,7 +2,7 @@
<div class="container">
<el-form :model="state.form">
<div class="record-container">
<div class="title">长春市朝阳区中医院</div>
<div class="title">演示医院</div>
<div class="subtitle">入院记录</div>
<div class="header">
<span>姓名: [<el-input v-model="state.form.name" class="inline-input" />]</span>

View File

@@ -1,89 +1,72 @@
<template>
<div @keyup="handleKeyDown" tabindex="0" ref="tableWrapper" class="advice-base-list-wrapper">
<Table
<div @keyup="handleKeyDown" tabindex="0" ref="tableWrapper">
<el-table
ref="adviceBaseRef"
:table-data="adviceBaseList"
:table-columns="tableColumns"
:highlight-current-row="true"
:table-height="400"
:max-height="400"
:loading="loading"
height="400"
:data="adviceBaseList"
highlight-current-row
@current-change="handleCurrentChange"
row-key="patientId"
@row-click="handleRowClick"
@cell-click="clickRow"
>
<template #quantity="{ row }">
{{ handleQuantity(row) }}
</template>
<template #useScope="{ row }">
<span v-if="row.useLimitFlag === 1">{{ row.useScope }}</span>
<span v-else>{{ '-' }}</span>
</template>
</Table>
<el-table-column label="名称" align="center" prop="adviceName" />
<el-table-column label="类型" align="center" prop="activityType_enumText" />
<el-table-column label="包装单位" align="center" prop="unitCode_dictText" />
<el-table-column label="最小单位" align="center" prop="minUnitCode_dictText" />
<el-table-column label="规格" align="center" prop="volume" />
<el-table-column label="用法" align="center" prop="methodCode_dictText" />
<el-table-column label="库存数量" align="center">
<template #default="scope">{{ handleQuantity(scope.row) }}</template>
</el-table-column>
<el-table-column label="频次" align="center" prop="rateCode_dictText" />
<!-- <el-table-column label="单次剂量" align="center" prop="dose" /> -->
<!-- <el-table-column label="剂量单位" align="center" prop="doseUnitCode_dictText" /> -->
<el-table-column label="注射药品" align="center" prop="injectFlag_enumText" />
<el-table-column label="皮试" align="center" prop="skinTestFlag_enumText" />
<el-table-column label="医保码" align="center" prop="ybNo" />
<!-- <el-table-column label="限制使用标志" align="center" prop="useLimitFlag" /> -->
<el-table-column
label="限制使用范围"
align="center"
:show-overflow-tooltip="true"
prop="useScope"
>
<template #default="scope">
<span v-if="scope.row.useLimitFlag === 1">{{ scope.row.useScope }}</span>
<span v-else>{{ '-' }}</span>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script setup lang="ts">
import { ref, nextTick, watch, computed } from 'vue';
import { throttle } from 'lodash-es';
import Table from '@/components/TableLayout/Table.vue';
<script setup>
import { nextTick } from 'vue';
import { getAdviceBaseInfo } from './api';
import type { TableColumn } from '@/components/types/TableLayout.d';
import { throttle } from 'lodash-es';
interface Props {
adviceQueryParams?: {
searchKey?: string;
adviceType?: string;
};
const props = defineProps({
adviceQueryParams: {
type: Object,
default: '',
},
patientInfo: {
inHospitalOrgId?: string;
[key: string]: any;
};
}
const props = withDefaults(defineProps<Props>(), {
adviceQueryParams: () => ({}),
type: Object,
required: true,
},
});
const emit = defineEmits<{
selectAdviceBase: [row: any];
}>();
const total = ref<number>(0);
const loading = ref<boolean>(false);
const adviceBaseRef = ref<InstanceType<typeof Table> | null>(null);
const tableWrapper = ref<HTMLDivElement | null>(null);
const currentIndex = ref<number>(0);
const currentSelectRow = ref<any>({});
const emit = defineEmits(['selectAdviceBase']);
const total = ref(0);
const adviceBaseRef = ref();
const tableWrapper = ref();
const currentIndex = ref(0); // 当前选中行索引
const currentSelectRow = ref({});
const queryParams = ref({
pageSize: 100,
pageNum: 1,
adviceTypes: '1,3',
searchKey: '',
organizationId: '',
adviceTypes: '1,3'
});
const adviceBaseList = ref<any[]>([]);
// 表格列配置
const tableColumns = computed<TableColumn[]>(() => [
{ label: '名称', prop: 'adviceName', align: 'center', width: 200 },
{ label: '类型', prop: 'activityType_enumText', align: 'center' },
{ label: '包装单位', prop: 'unitCode_dictText', align: 'center' },
{ label: '最小单位', prop: 'minUnitCode_dictText', align: 'center' },
{ label: '规格', prop: 'volume', align: 'center' },
{ label: '用法', prop: 'methodCode_dictText', align: 'center' },
{ label: '库存数量', prop: 'quantity', align: 'center', slot: 'quantity' },
{ label: '频次', prop: 'rateCode_dictText', align: 'center' },
{ label: '注射药品', prop: 'injectFlag_enumText', align: 'center' },
{ label: '皮试', prop: 'skinTestFlag_enumText', align: 'center' },
{ label: '医保码', prop: 'ybNo', align: 'center' },
{
label: '限制使用范围',
prop: 'useScope',
align: 'center',
showOverflowTooltip: true,
slot: 'useScope',
},
]);
const adviceBaseList = ref([]);
// 节流函数
const throttledGetList = throttle(
() => {
@@ -105,52 +88,39 @@ watch(
getList();
function getList() {
loading.value = true;
queryParams.value.organizationId = props.patientInfo.inHospitalOrgId;
getAdviceBaseInfo(queryParams.value)
.then((res) => {
console.log(res.data.records);
if (res.data.records.length > 0) {
adviceBaseList.value = res.data.records.filter((item) => {
if (item.adviceType == 1 || item.adviceType == 2) {
return handleQuantity(item) != 0;
} else {
return true;
}
});
total.value = res.data.total;
nextTick(() => {
if (adviceBaseList.value.length > 0) {
currentIndex.value = 0;
setCurrentRow(adviceBaseList.value[0]);
}
});
} else {
adviceBaseList.value = [];
}
})
.catch(() => {
adviceBaseList.value = [];
})
.finally(() => {
loading.value = false;
});
getAdviceBaseInfo(queryParams.value).then((res) => {
if (res.data.records.length > 0) {
adviceBaseList.value = res.data.records.filter((item) => {
if (item.adviceType == 1 || item.adviceType == 2) {
return handleQuantity(item) != 0;
} else {
return true;
}
});
total.value = res.data.total;
nextTick(() => {
currentIndex.value = 0;
adviceBaseRef.value.setCurrentRow(adviceBaseList.value[0]);
});
}
});
}
// 处理键盘事件
const handleKeyDown = (event: KeyboardEvent): void => {
const handleKeyDown = (event) => {
const key = event.key;
const data = adviceBaseList.value;
switch (key) {
case 'ArrowUp': // 上箭头
event.preventDefault();
event.preventDefault(); // 阻止默认滚动行为
if (currentIndex.value > 0) {
currentIndex.value--;
setCurrentRow(data[currentIndex.value]);
}
break;
case 'ArrowDown': // 下箭头
case 'ArrowDown': // 下箭头`
event.preventDefault();
if (currentIndex.value < data.length - 1) {
currentIndex.value++;
@@ -158,84 +128,52 @@ const handleKeyDown = (event: KeyboardEvent): void => {
}
break;
case 'Enter': // 回车键
// const currentRow = adviceBaseRef.value.getSelectionRows();
event.preventDefault();
if (currentSelectRow.value && Object.keys(currentSelectRow.value).length > 0) {
if (currentSelectRow.value) {
// 这里可以触发自定义逻辑,如弹窗、跳转等
emit('selectAdviceBase', currentSelectRow.value);
}
break;
}
};
function handleQuantity(row: any): string {
function handleQuantity(row) {
if (row.inventoryList && row.inventoryList.length > 0) {
const totalQuantity = row.inventoryList.reduce(
(sum: number, item: any) => sum + (item.quantity || 0),
0
);
return totalQuantity.toString() + (row.minUnitCode_dictText || '');
const totalQuantity = row.inventoryList.reduce((sum, item) => sum + (item.quantity || 0), 0);
return totalQuantity.toString() + row.minUnitCode_dictText;
}
return '0';
return 0;
}
// 设置选中行(带滚动)
const setCurrentRow = (row: any) => {
if (adviceBaseRef.value?.tableRef) {
adviceBaseRef.value.tableRef.setCurrentRow(row);
// 滚动到选中行
nextTick(() => {
const tableEl = adviceBaseRef.value?.tableRef?.$el;
if (tableEl) {
const tableBody = tableEl.querySelector('.el-table__body-wrapper');
const currentRowEl = tableEl.querySelector('.current-row');
if (tableBody && currentRowEl) {
currentRowEl.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
}
});
const setCurrentRow = (row) => {
adviceBaseRef.value.setCurrentRow(row);
// 滚动到选中行
const tableBody = adviceBaseRef.value.$el.querySelector('.el-table__body-wrapper');
const currentRowEl = adviceBaseRef.value.$el.querySelector('.current-row');
if (tableBody && currentRowEl) {
currentRowEl.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
};
// 行点击事件
const handleRowClick = (row: any): void => {
currentIndex.value = adviceBaseList.value.findIndex((item) => item === row);
currentSelectRow.value = row;
emit('selectAdviceBase', row);
// 当前行变化时更新索引
const handleCurrentChange = (currentRow) => {
currentIndex.value = adviceBaseList.value.findIndex((item) => item === currentRow);
currentSelectRow.value = currentRow;
};
// 监听表格当前行变化(通过 el-table 的 current-change 事件)
watch(
() => adviceBaseRef.value?.tableRef,
(tableRef) => {
if (tableRef) {
// 通过 $el 访问原生 el-table 并监听 current-change
const elTable = tableRef.$el?.querySelector('.el-table');
if (elTable) {
// 使用 MutationObserver 或直接监听 DOM 变化来检测当前行变化
// 或者通过 watch 监听 currentSelectRow 的变化
}
}
},
{ immediate: true }
);
function clickRow(row) {
emit('selectAdviceBase', row);
}
defineExpose({
handleKeyDown,
});
</script>
<style scoped lang="scss">
.advice-base-list-wrapper {
height: 400px;
overflow: hidden;
display: flex;
flex-direction: column;
&:focus {
outline: 2px solid #409eff;
}
}
<style scoped>
.popover-table-wrapper:focus {
outline: 2px solid #409eff;
outline: 2px solid #409eff; /* 聚焦时的高亮效果 */
}
</style>
</style>

View File

@@ -1,11 +1,11 @@
import request from '@/utils/request';
import request from '@/utils/request'
export function getPatientList(queryParams) {
return request({
url: '/reg-doctorstation/advice-manage/reg-patient-zk',
method: 'get',
params: queryParams,
});
params: queryParams
})
}
// 诊断相关接口
@@ -16,8 +16,8 @@ export function saveDiagnosis(data) {
return request({
url: '/doctor-station/diagnosis/save-doctor-diagnosis',
method: 'post',
data: data,
});
data: data
})
}
/**
@@ -27,8 +27,8 @@ export function saveDiagnosisBind(data) {
return request({
url: '/doctor-station/diagnosis/diagnosis-belong-binding',
method: 'post',
data: data,
});
data: data
})
}
/**
* 删除诊断绑定
@@ -37,7 +37,7 @@ export function deleteDiagnosisBind(id) {
return request({
url: '/doctor-station/diagnosis/diagnosis-belong-binding?id=' + id,
method: 'delete',
});
})
}
/**
@@ -47,8 +47,8 @@ export function getDiagnosisDefinitionList(queryParams) {
return request({
url: '/doctor-station/diagnosis/condition-definition-metadata',
method: 'get',
params: queryParams,
});
params: queryParams
})
}
/**
@@ -58,7 +58,7 @@ export function getConditionDefinitionInfo(patientId) {
return request({
url: '/doctor-station/diagnosis/get-condition-definition-class?patientId=' + patientId,
method: 'get',
});
})
}
/**
@@ -68,29 +68,29 @@ export function diagnosisInit() {
return request({
url: '/doctor-station/diagnosis/init',
method: 'get',
});
})
}
/**
*
*
* 获取诊断回显数据
*/
export function getEncounterDiagnosis(encounterId) {
return request({
url: '/doctor-station/diagnosis/get-encounter-diagnosis?encounterId=' + encounterId,
method: 'get',
});
})
}
/**
*
*
* 删除就诊诊断
*/
export function delEncounterDiagnosis(conditionId) {
return request({
url: '/doctor-station/diagnosis/encounter-diagnosis?conditionId=' + conditionId,
method: 'delete',
});
})
}
/**
@@ -112,8 +112,8 @@ export function getTcmCondition(params) {
return request({
url: '/doctor-station/chinese-medical/condition-info',
method: 'get',
params: params,
});
params: params
})
}
/**
@@ -123,8 +123,8 @@ export function getTcmSyndrome(params) {
return request({
url: '/doctor-station/chinese-medical/syndrome-info',
method: 'get',
params: params,
});
params: params
})
}
/**
@@ -134,8 +134,8 @@ export function getTcmDiagnosis(params) {
return request({
url: '/doctor-station/chinese-medical/get-tcm-encounter-diagnosis',
method: 'get',
params: params,
});
params: params
})
}
/**
@@ -145,8 +145,8 @@ export function saveTcmDiagnosis(data) {
return request({
url: '/doctor-station/chinese-medical/save-tcm-diagnosis',
method: 'post',
data: data,
});
data: data
})
}
/**
* 获取人员慢性病诊断
@@ -155,10 +155,11 @@ export function getChronicDisease(params) {
return request({
url: '/yb-request/getConditionDefinition',
method: 'get',
params: params,
});
params: params
})
}
/**
* 获取药品列表
*/
@@ -166,8 +167,8 @@ export function getAdviceBaseInfo(queryParams) {
return request({
url: '/doctor-station/advice/advice-base-info',
method: 'get',
params: queryParams,
});
params: queryParams
})
}
/**
@@ -177,8 +178,8 @@ export function savePrescription(data) {
return request({
url: '/reg-doctorstation/advice-manage/save-reg-advice',
method: 'post',
data: data,
});
data: data
})
}
/**
* 签发处方
@@ -187,8 +188,8 @@ export function savePrescriptionSign(data) {
return request({
url: '/reg-doctorstation/advice-manage/sign-reg-advice',
method: 'post',
data: data,
});
data: data
})
}
/**
* 处方签退
@@ -197,8 +198,8 @@ export function singOut(data) {
return request({
url: '/reg-doctorstation/advice-manage/sign-off-reg',
method: 'post',
data: data,
});
data: data
})
}
/**
* 停嘱
@@ -207,8 +208,8 @@ export function stopAdvice(data) {
return request({
url: '/reg-doctorstation/advice-manage/stop-reg-advice',
method: 'post',
data: data,
});
data: data
})
}
/**
* 获取患者本次就诊处方
@@ -217,7 +218,7 @@ export function getPrescriptionList(encounterId) {
return request({
url: '/reg-doctorstation/advice-manage/reg-request-base-info?encounterId=' + encounterId,
method: 'get',
});
})
}
/**
@@ -227,8 +228,8 @@ export function getContract(params) {
return request({
url: '/doctor-station/advice/get-encounter-contract',
method: 'get',
params: params,
});
params: params
})
}
/**
@@ -238,7 +239,7 @@ export function getOrgTree() {
return request({
url: '/base-data-manage/organization/organization',
method: 'get',
});
})
}
@@ -257,28 +258,6 @@ export function updateGroupId(data) {
return request({
url: '/doctor-station/advice/update-groupid',
method: 'put',
data: data,
});
}
/**
* 查询项目绑定信息
*/
export function getBindDevice(data) {
return request({
url: '/doctor-station/advice/order-bind-info',
method: 'get',
params: data,
});
}
/**
* 出院
*/
export function leaveHospital(data) {
return request({
url: '/reg-doctorstation/special-advice/leave-hospital-orders',
method: 'post',
data: data,
});
data: data
})
}

View File

@@ -1,318 +1,87 @@
<!--
* @Author: sjjh
* @Date: 2025-09-05 21:16:06
* @Description: 输血申请详情
-->
<template>
<div class="report-container">
<div class="report-section">
<div class="report-title">
<span>输血申请</span>
<el-icon
class="report-refresh-icon"
:class="{ 'is-loading': loading }"
@click="handleRefresh"
>
<Refresh />
</el-icon>
</div>
<div class="report-table-wrapper">
<el-table
v-loading="loading"
:data="tableData"
border
size="small"
height="100%"
style="width: 100%"
>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="patientName" label="患者姓名" width="120" />
<el-table-column prop="name" label="申请单名称" width="140" />
<el-table-column prop="createTime" label="创建时间" width="160" />
<el-table-column prop="prescriptionNo" label="处方号" width="140" />
<el-table-column prop="requesterId_dictText" label="申请者" width="120" />
<el-table-column label="操作" align="center" fixed="right">
<template #default="scope">
<el-button link type="primary" @click="handleViewDetail(scope.row)">详情</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="applicationShow-container">
<div class="applicationShow-container-header">
<el-button @click="getInfo">刷新</el-button>
</div>
<div class="applicationShow-container-content">
<el-descriptions title="输血申请详情" :column="2">
<el-descriptions-item label="Username">kooriookami</el-descriptions-item>
<el-descriptions-item label="患者姓名">{{ patientInfoValue?.patientName || '-' }}</el-descriptions-item>
<el-descriptions-item label="患者性别">{{ patientInfoValue?.patientSex || '-' }}</el-descriptions-item>
<el-descriptions-item label="患者年龄">{{ patientInfoValue?.patientAge || '-' }}</el-descriptions-item>
<el-descriptions-item label="患者手机号">{{ patientInfoValue?.patientPhone || '-' }}</el-descriptions-item>
<el-descriptions-item label="患者身份证号">{{ patientInfoValue?.patientIdCard || '-' }}</el-descriptions-item>
<el-descriptions-item label="患者地址">{{ patientInfoValue?.patientAddress || '-' }}</el-descriptions-item>
</el-descriptions>
</div>
<div class="applicationShow-container-table">
<el-table :data="dataList">
<el-table-column label="医嘱名称" prop="adviceName" />
<el-table-column label="输血数量" prop="adviceDefinitionId" />
</el-table>
</div>
<!-- 详情弹窗 -->
<el-dialog
v-model="detailDialogVisible"
title="输血申请详情"
width="800px"
destroy-on-close
top="5vh"
:close-on-click-modal="false"
>
<div v-if="currentDetail" class="applicationShow-container">
<div class="applicationShow-container-content">
<el-descriptions title="基本信息" :column="2">
<el-descriptions-item label="患者姓名">{{
currentDetail.patientName || '-'
}}</el-descriptions-item>
<el-descriptions-item label="申请单名称">{{
currentDetail.name || '-'
}}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{
currentDetail.createTime || '-'
}}</el-descriptions-item>
<el-descriptions-item label="处方号">{{
currentDetail.prescriptionNo || '-'
}}</el-descriptions-item>
<el-descriptions-item label="申请者">{{
currentDetail.requesterId_dictText || '-'
}}</el-descriptions-item>
<el-descriptions-item label="就诊ID">{{
currentDetail.encounterId || '-'
}}</el-descriptions-item>
<el-descriptions-item label="申请单ID">{{
currentDetail.requestFormId || '-'
}}</el-descriptions-item>
</el-descriptions>
</div>
<div v-if="descJsonData && hasMatchedFields" class="applicationShow-container-content">
<el-descriptions title="申请单描述" :column="2">
<template v-for="(value, key) in descJsonData" :key="key">
<el-descriptions-item v-if="isFieldMatched(key)" :label="getFieldLabel(key)">
{{ value || '-' }}
</el-descriptions-item>
</template>
</el-descriptions>
</div>
<div
v-if="currentDetail.requestFormDetailList && currentDetail.requestFormDetailList.length"
class="applicationShow-container-table"
>
<el-table :data="currentDetail.requestFormDetailList" border>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="adviceName" label="医嘱名称" />
<el-table-column prop="quantity" label="数量" width="80" align="center" />
<el-table-column prop="unitCode_dictText" label="单位" width="100" />
<el-table-column prop="totalPrice" label="总价" width="100" align="right" />
</el-table>
</div>
</div>
<template #footer>
<el-button @click="detailDialogVisible = false">关闭</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { getCurrentInstance, ref, watch, computed } from 'vue';
import { Refresh } from '@element-plus/icons-vue';
import { patientInfo } from '../../store/patient.js';
import { getCurrentInstance, onBeforeMount, onMounted, reactive, ref, computed } from 'vue'
import { getBloodTransfusion } from './api';
import { getOrgList } from '../../../../doctorstation/components/api.js';
import { patientInfo } from '../../store/patient.js';
const { proxy } = getCurrentInstance();
const emits = defineEmits([])
const props = defineProps({
const tableData = ref([]);
const loading = ref(false);
const detailDialogVisible = ref(false);
const currentDetail = ref(null);
const descJsonData = ref(null);
const orgOptions = ref([]);
})
const state = reactive({
const fetchData = async () => {
if (!patientInfo.value?.encounterId) {
tableData.value = [];
loading.value = false;
return;
}
loading.value = true;
try {
const res = await getBloodTransfusion({ encounterId: patientInfo.value.encounterId });
if (res.code === 200 && res.data) {
const raw = res.data?.records || res.data;
const list = Array.isArray(raw) ? raw : [raw];
tableData.value = list.filter(Boolean);
} else {
tableData.value = [];
}
} catch (e) {
proxy.$modal?.msgError?.(e.message || '查询输血申请失败');
tableData.value = [];
} finally {
loading.value = false;
}
};
})
const handleRefresh = async () => {
if (loading.value || !patientInfo.value?.encounterId) return;
await fetchData();
};
const labelMap = {
categoryType: '项目类别',
targetDepartment: '发往科室',
symptom: '症状',
sign: '体征',
clinicalDiagnosis: '临床诊断',
otherDiagnosis: '其他诊断',
relatedResult: '相关结果',
attention: '注意事项',
};
const isFieldMatched = (key) => {
return key in labelMap;
};
const getFieldLabel = (key) => {
return labelMap[key] || key;
};
const hasMatchedFields = computed(() => {
if (!descJsonData.value) return false;
return Object.keys(descJsonData.value).some((key) => isFieldMatched(key));
// 使用计算属性确保安全访问
const patientInfoValue = computed(() => {
return patientInfo.value || {};
});
/** 查询科室 */
const getLocationInfo = () => {
getOrgList().then((res) => {
orgOptions.value = res.data.records;
});
};
const recursionFun = (targetDepartment) => {
let name = '';
for (let index = 0; index < orgOptions.value.length; index++) {
const obj = orgOptions.value[index];
if (obj.id == targetDepartment) {
name = obj.name;
}
const subObjArray = obj['children'];
for (let index = 0; index < subObjArray.length; index++) {
const item = subObjArray[index];
if (item.id == targetDepartment) {
name = item.name;
const dataList = ref([])
const getInfo = () => {
if (patientInfo.value?.inHospitalOrgId) {
getBloodTransfusion({
encounterId: patientInfo.value.encounterId,
}).then((res) => {
if (res.code === 200) {
dataList.value = res.data
} else {
}
}
});
}
return name;
};
onBeforeMount(() => {
const handleViewDetail = (row) => {
currentDetail.value = row;
// 解析 descJson
if (row.descJson) {
try {
// descJsonData.value = JSON.parse(row.descJson);
const obj = JSON.parse(row.descJson);
obj.targetDepartment = recursionFun(obj.targetDepartment);
descJsonData.value = obj;
} catch (e) {
console.error('解析 descJson 失败:', e);
descJsonData.value = null;
}
} else {
descJsonData.value = null;
}
detailDialogVisible.value = true;
};
})
onMounted(() => {
getInfo()
})
defineExpose({ state })
watch(
() => patientInfo.value?.encounterId,
(val) => {
if (val) {
fetchData();
getLocationInfo();
} else {
tableData.value = [];
}
},
{ immediate: true }
);
defineExpose({
refresh: fetchData,
});
</script>
<style scoped lang="scss">
.report-container {
display: flex;
flex-direction: column;
gap: 12px;
padding: 8px 0;
height: 100%;
}
.report-section {
background: #fff;
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
}
.report-title {
font-weight: 600;
margin-bottom: 8px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 8px;
}
.report-table-wrapper {
flex: 1;
min-height: 0;
overflow: auto;
padding: 0 8px;
}
.report-refresh-icon {
cursor: pointer;
color: #909399;
transition: color 0.2s;
font-size: 18px;
}
.report-refresh-icon:hover {
color: #409eff;
}
.report-refresh-icon.is-loading {
animation: rotating 2s linear infinite;
}
@keyframes rotating {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
:deep(.el-dialog__body) {
padding-top: 0 !important;
}
<style lang="scss" scoped>
.applicationShow-container {
display: flex;
flex-direction: column;
max-height: 70vh;
height: 100%;
width: 100%;
overflow-y: auto;
.applicationShow-container-content {
flex-shrink: 0;
margin-bottom: 0px;
.applicationShow-container-header{
height: 44px;
display: flex;
align-items: center;
gap:8px;
padding: 0 16px;
}
.applicationShow-container-table {
flex-shrink: 0;
max-height: 300px;
overflow: auto;
.applicationShow-container-content{
flex: 1;
}
.applicationShow-container-table{
height: 400px;
flex:auto
}
}
</style>
</style>

View File

@@ -4,316 +4,42 @@
* @Description: 检查申请详情
-->
<template>
<div class="report-container">
<div class="report-section">
<div class="report-title">
<span>检查申请</span>
<el-icon
class="report-refresh-icon"
:class="{ 'is-loading': loading }"
@click="handleRefresh"
>
<Refresh />
</el-icon>
</div>
<div class="report-table-wrapper">
<el-table
v-loading="loading"
:data="tableData"
border
size="small"
height="100%"
style="width: 100%"
>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="patientName" label="患者姓名" width="120" />
<el-table-column prop="name" label="申请单名称" width="140" />
<el-table-column prop="createTime" label="创建时间" width="160" />
<el-table-column prop="prescriptionNo" label="处方号" width="140" />
<el-table-column prop="requesterId_dictText" label="申请者" width="120" />
<el-table-column label="操作" align="center" fixed="right">
<template #default="scope">
<el-button link type="primary" @click="handleViewDetail(scope.row)">详情</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
<!-- 详情弹窗 -->
<el-dialog
v-model="detailDialogVisible"
title="检查申请详情"
width="800px"
destroy-on-close
top="5vh"
:close-on-click-modal="false"
>
<div v-if="currentDetail" class="applicationShow-container">
<div class="applicationShow-container-content">
<el-descriptions title="基本信息" :column="2">
<el-descriptions-item label="患者姓名">{{
currentDetail.patientName || '-'
}}</el-descriptions-item>
<el-descriptions-item label="申请单名称">{{
currentDetail.name || '-'
}}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{
currentDetail.createTime || '-'
}}</el-descriptions-item>
<el-descriptions-item label="处方号">{{
currentDetail.prescriptionNo || '-'
}}</el-descriptions-item>
<el-descriptions-item label="申请者">{{
currentDetail.requesterId_dictText || '-'
}}</el-descriptions-item>
<el-descriptions-item label="就诊ID">{{
currentDetail.encounterId || '-'
}}</el-descriptions-item>
<el-descriptions-item label="申请单ID">{{
currentDetail.requestFormId || '-'
}}</el-descriptions-item>
</el-descriptions>
</div>
<div v-if="descJsonData && hasMatchedFields" class="applicationShow-container-content">
<el-descriptions title="申请单描述" :column="2">
<template v-for="(value, key) in descJsonData" :key="key">
<el-descriptions-item v-if="isFieldMatched(key)" :label="getFieldLabel(key)">
{{ value || '-' }}
</el-descriptions-item>
</template>
</el-descriptions>
</div>
<div
v-if="currentDetail.requestFormDetailList && currentDetail.requestFormDetailList.length"
class="applicationShow-container-table"
>
<el-table :data="currentDetail.requestFormDetailList" border>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="adviceName" label="医嘱名称" />
<el-table-column prop="quantity" label="数量" width="80" align="center" />
<el-table-column prop="unitCode_dictText" label="单位" width="100" />
<el-table-column prop="totalPrice" label="总价" width="100" align="right" />
</el-table>
</div>
</div>
<template #footer>
<el-button @click="detailDialogVisible = false">关闭</el-button>
</template>
</el-dialog>
<div class="container">
<el-button @click="getInfo">查询</el-button>
</div>
</template>
<script setup>
import { getCurrentInstance, ref, watch, computed } from 'vue';
import { Refresh } from '@element-plus/icons-vue';
</template>
<script setup >
import { getCurrentInstance, onBeforeMount, onMounted, reactive } from 'vue'
import { getCheck } from './api';
import { patientInfo } from '../../store/patient.js';
import { getCheck } from './api';
import { getOrgList } from '../../../../doctorstation/components/api.js';
const { proxy } = getCurrentInstance();
const tableData = ref([]);
const loading = ref(false);
const detailDialogVisible = ref(false);
const currentDetail = ref(null);
const descJsonData = ref(null);
const orgOptions = ref([]);
const fetchData = async () => {
if (!patientInfo.value?.encounterId) {
tableData.value = [];
loading.value = false;
return;
}
loading.value = true;
try {
const res = await getCheck({ encounterId: patientInfo.value.encounterId });
if (res.code === 200 && res.data) {
const raw = res.data?.records || res.data;
const list = Array.isArray(raw) ? raw : [raw];
tableData.value = list.filter(Boolean);
} else {
tableData.value = [];
}
} catch (e) {
proxy.$modal?.msgError?.(e.message || '查询检查申请失败');
tableData.value = [];
} finally {
loading.value = false;
}
};
const handleRefresh = async () => {
if (loading.value || !patientInfo.value?.encounterId) return;
await fetchData();
};
const labelMap = {
categoryType: '项目类别',
targetDepartment: '发往科室',
symptom: '症状',
sign: '体征',
clinicalDiagnosis: '临床诊断',
otherDiagnosis: '其他诊断',
relatedResult: '相关结果',
attention: '注意事项',
};
const isFieldMatched = (key) => {
return key in labelMap;
};
const getFieldLabel = (key) => {
return labelMap[key] || key;
};
const hasMatchedFields = computed(() => {
if (!descJsonData.value) return false;
return Object.keys(descJsonData.value).some((key) => isFieldMatched(key));
});
/** 查询科室 */
const getLocationInfo = () => {
getOrgList().then((res) => {
orgOptions.value = res.data.records;
});
};
const recursionFun = (targetDepartment) => {
let name = '';
for (let index = 0; index < orgOptions.value.length; index++) {
const obj = orgOptions.value[index];
if (obj.id == targetDepartment) {
name = obj.name;
}
const subObjArray = obj['children'];
for (let index = 0; index < subObjArray.length; index++) {
const item = subObjArray[index];
if (item.id == targetDepartment) {
name = item.name;
const { proxy } = getCurrentInstance();
const emits = defineEmits([])
const props = defineProps({
})
const state = reactive({
})
const getInfo = () => {
if (patientInfo.value?.inHospitalOrgId) {
getCheck({
encounterId: patientInfo.value.encounterId,
}).then((res) => {
if (res.code === 200) {
} else {
}
}
});
}
return name;
};
const handleViewDetail = (row) => {
console.log('targetDepartment========>', JSON.stringify(row));
currentDetail.value = row;
// 解析 descJson
if (row.descJson) {
try {
const obj = JSON.parse(row.descJson);
obj.targetDepartment = recursionFun(obj.targetDepartment);
descJsonData.value = obj;
} catch (e) {
console.error('解析 descJson 失败:', e);
descJsonData.value = null;
}
} else {
descJsonData.value = null;
}
detailDialogVisible.value = true;
};
watch(
() => patientInfo.value?.encounterId,
(val) => {
if (val) {
fetchData();
getLocationInfo();
} else {
tableData.value = [];
}
},
{ immediate: true }
);
defineExpose({
refresh: fetchData,
});
</script>
<style scoped lang="scss">
.report-container {
display: flex;
flex-direction: column;
gap: 12px;
padding: 8px 0;
height: 100%;
}
.report-section {
background: #fff;
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
}
.report-title {
font-weight: 600;
margin-bottom: 8px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 8px;
}
.report-table-wrapper {
flex: 1;
min-height: 0;
overflow: auto;
padding: 0 8px;
}
.report-refresh-icon {
cursor: pointer;
color: #909399;
transition: color 0.2s;
font-size: 18px;
}
.report-refresh-icon:hover {
color: #409eff;
}
.report-refresh-icon.is-loading {
animation: rotating 2s linear infinite;
}
@keyframes rotating {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
:deep(.el-dialog__body) {
padding-top: 0 !important;
}
.applicationShow-container {
display: flex;
flex-direction: column;
max-height: 70vh;
width: 100%;
overflow-y: auto;
.applicationShow-container-content {
flex-shrink: 0;
margin-bottom: 0px;
}
.applicationShow-container-table {
flex-shrink: 0;
max-height: 300px;
overflow: auto;
}
}
</style>
onBeforeMount(() => {
})
onMounted(() => {
getInfo()
})
defineExpose({ state })
</script>
<style lang="scss" scoped>
</style>

View File

@@ -1,238 +0,0 @@
<template>
<div class="report-container">
<div class="report-section">
<div class="report-title">
<span>检查报告</span>
<el-icon
class="report-refresh-icon"
:class="{ 'is-loading': loadingCheck }"
@click="handleRefreshCheck"
>
<Refresh />
</el-icon>
</div>
<div class="report-table-wrapper">
<el-table
v-loading="loadingCheck"
:data="checkReportList"
border
size="small"
height="100%"
style="width: 100%"
>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="adviceName" label="报告名称" width="140" />
<el-table-column prop="reportNo" label="报告号" width="140" />
<el-table-column label="链接" min-width="140">
<template #default="scope">
<a
v-if="scope.row.requestUrl"
class="report-link"
:href="scope.row.requestUrl"
target="_blank"
rel="noopener noreferrer"
>
查看报告
</a>
<span v-else class="report-link-disabled">暂无链接</span>
</template>
</el-table-column>
</el-table>
</div>
</div>
<div class="report-section">
<div class="report-title">
<span>检验报告</span>
<el-icon
class="report-refresh-icon"
:class="{ 'is-loading': loadingInspection }"
@click="handleRefreshInspection"
>
<Refresh />
</el-icon>
</div>
<div class="report-table-wrapper">
<el-table
v-loading="loadingInspection"
:data="inspectionReportList"
border
size="small"
height="100%"
style="width: 100%"
>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="adviceName" label="报告名称" width="140" />
<el-table-column prop="reportNo" label="报告号" width="140" />
<el-table-column label="链接" min-width="140">
<template #default="scope">
<a
v-if="scope.row.requestUrl"
class="report-link"
:href="scope.row.requestUrl"
target="_blank"
rel="noopener noreferrer"
>
查看报告
</a>
<span v-else class="report-link-disabled">暂无链接</span>
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
</template>
<script setup>
import { getCurrentInstance, ref, watch } from 'vue';
import { Refresh } from '@element-plus/icons-vue';
import { patientInfo } from '../../store/patient.js';
import { getProofResult, getTestResult } from './api';
const { proxy } = getCurrentInstance();
const checkReportList = ref([]);
const inspectionReportList = ref([]);
const loadingCheck = ref(false);
const loadingInspection = ref(false);
const fetchCheckReport = async () => {
if (!patientInfo.value?.encounterId) return;
const res = await getTestResult({ encounterId: patientInfo.value.encounterId });
if (res.code === 200 && res.data) {
const raw = res.data?.records || res.data;
const list = Array.isArray(raw) ? raw : [raw];
checkReportList.value = list.filter(Boolean).map((item) => ({
reportNo: item.busNo,
requestUrl: item.requestUrl,
adviceName: item.adviceName,
_raw: item,
}));
} else {
checkReportList.value = [];
}
};
const fetchInspectionReport = async () => {
if (!patientInfo.value?.encounterId) return;
const res = await getProofResult({ encounterId: patientInfo.value.encounterId });
if (res.code === 200 && res.data) {
const raw = res.data?.records || res.data;
const list = Array.isArray(raw) ? raw : [raw];
inspectionReportList.value = list.filter(Boolean).map((item) => ({
reportNo: item.busNo,
requestUrl: item.requestUrl,
adviceName: item.adviceName,
_raw: item,
}));
} else {
inspectionReportList.value = [];
}
};
const fetchAll = async () => {
if (!patientInfo.value?.encounterId) {
checkReportList.value = [];
inspectionReportList.value = [];
loadingCheck.value = false;
loadingInspection.value = false;
return;
}
loadingCheck.value = true;
loadingInspection.value = true;
try {
await Promise.all([fetchCheckReport(), fetchInspectionReport()]);
} catch (e) {
proxy.$modal?.msgError?.(e.message || '查询报告失败');
} finally {
loadingCheck.value = false;
loadingInspection.value = false;
}
};
const handleRefreshCheck = async () => {
if (loadingCheck.value || !patientInfo.value?.encounterId) return;
loadingCheck.value = true;
try {
await fetchCheckReport();
} finally {
loadingCheck.value = false;
}
};
const handleRefreshInspection = async () => {
if (loadingInspection.value || !patientInfo.value?.encounterId) return;
loadingInspection.value = true;
try {
await fetchInspectionReport();
} finally {
loadingInspection.value = false;
}
};
watch(
() => patientInfo.value?.encounterId,
(val) => {
if (val) {
fetchAll();
} else {
checkReportList.value = [];
inspectionReportList.value = [];
}
},
{ immediate: true }
);
</script>
<style scoped lang="scss">
.report-container {
display: flex;
flex-direction: column;
gap: 12px;
padding: 8px 0;
height: 100%;
}
.report-section {
background: #fff;
flex: 1;
max-height: 55%;
min-height: 0;
display: flex;
flex-direction: column;
}
.report-title {
font-weight: 600;
margin-bottom: 8px;
display: flex;
align-items: center;
justify-content: space-between;
}
.report-table-wrapper {
flex: 1;
min-height: 0;
overflow: auto;
}
.report-refresh-icon {
cursor: pointer;
color: #909399;
transition: color 0.2s;
}
.report-refresh-icon:hover {
color: #409eff;
}
.report-link {
color: #409eff;
cursor: pointer;
text-decoration: underline;
}
.report-link-disabled {
color: #c0c4cc;
}
</style>

View File

@@ -4,315 +4,33 @@
* @Description: 手术申请详情
-->
<template>
<div class="report-container">
<div class="report-section">
<div class="report-title">
<span>手术申请</span>
<el-icon
class="report-refresh-icon"
:class="{ 'is-loading': loading }"
@click="handleRefresh"
>
<Refresh />
</el-icon>
</div>
<div class="report-table-wrapper">
<el-table
v-loading="loading"
:data="tableData"
border
size="small"
height="100%"
style="width: 100%"
>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="patientName" label="患者姓名" width="120" />
<el-table-column prop="name" label="申请单名称" width="140" />
<el-table-column prop="createTime" label="创建时间" width="160" />
<el-table-column prop="prescriptionNo" label="处方号" width="140" />
<el-table-column prop="requesterId_dictText" label="申请者" width="120" />
<el-table-column label="操作" align="center" fixed="right">
<template #default="scope">
<el-button link type="primary" @click="handleViewDetail(scope.row)">详情</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
<!-- 详情弹窗 -->
<el-dialog
v-model="detailDialogVisible"
title="手术申请详情"
width="800px"
destroy-on-close
top="5vh"
:close-on-click-modal="false"
>
<div v-if="currentDetail" class="applicationShow-container">
<div class="applicationShow-container-content">
<el-descriptions title="基本信息" :column="2">
<el-descriptions-item label="患者姓名">{{
currentDetail.patientName || '-'
}}</el-descriptions-item>
<el-descriptions-item label="申请单名称">{{
currentDetail.name || '-'
}}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{
currentDetail.createTime || '-'
}}</el-descriptions-item>
<el-descriptions-item label="处方号">{{
currentDetail.prescriptionNo || '-'
}}</el-descriptions-item>
<el-descriptions-item label="申请者">{{
currentDetail.requesterId_dictText || '-'
}}</el-descriptions-item>
<el-descriptions-item label="就诊ID">{{
currentDetail.encounterId || '-'
}}</el-descriptions-item>
<el-descriptions-item label="申请单ID">{{
currentDetail.requestFormId || '-'
}}</el-descriptions-item>
</el-descriptions>
</div>
<div v-if="descJsonData && hasMatchedFields" class="applicationShow-container-content">
<el-descriptions title="申请单描述" :column="2">
<template v-for="(value, key) in descJsonData" :key="key">
<el-descriptions-item v-if="isFieldMatched(key)" :label="getFieldLabel(key)">
{{ value || '-' }}
</el-descriptions-item>
</template>
</el-descriptions>
</div>
<div
v-if="currentDetail.requestFormDetailList && currentDetail.requestFormDetailList.length"
class="applicationShow-container-table"
>
<el-table :data="currentDetail.requestFormDetailList" border>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="adviceName" label="医嘱名称" />
<el-table-column prop="quantity" label="数量" width="80" align="center" />
<el-table-column prop="unitCode_dictText" label="单位" width="100" />
<el-table-column prop="totalPrice" label="总价" width="100" align="right" />
</el-table>
</div>
</div>
<template #footer>
<el-button @click="detailDialogVisible = false">关闭</el-button>
</template>
</el-dialog>
<div class="container">
<el-button @click="getInfo">查询</el-button>
</div>
</template>
<script setup>
import { getCurrentInstance, ref, watch, computed } from 'vue';
import { Refresh } from '@element-plus/icons-vue';
import { patientInfo } from '../../store/patient.js';
import { getCurrentInstance, onBeforeMount, onMounted, reactive } from 'vue';
import { getSurgery } from './api';
import { getOrgList } from '../../../../doctorstation/components/api.js';
import { patientInfo } from '../../store/patient.js';
const { proxy } = getCurrentInstance();
const tableData = ref([]);
const loading = ref(false);
const detailDialogVisible = ref(false);
const currentDetail = ref(null);
const descJsonData = ref(null);
const orgOptions = ref([]);
const fetchData = async () => {
if (!patientInfo.value?.encounterId) {
tableData.value = [];
loading.value = false;
return;
}
loading.value = true;
try {
const res = await getSurgery({ encounterId: patientInfo.value.encounterId });
if (res.code === 200 && res.data) {
const raw = res.data?.records || res.data;
const list = Array.isArray(raw) ? raw : [raw];
tableData.value = list.filter(Boolean);
} else {
tableData.value = [];
}
} catch (e) {
proxy.$modal?.msgError?.(e.message || '查询手术申请失败');
tableData.value = [];
} finally {
loading.value = false;
}
};
const handleRefresh = async () => {
if (loading.value || !patientInfo.value?.encounterId) return;
await fetchData();
};
const labelMap = {
categoryType: '项目类别',
targetDepartment: '发往科室',
symptom: '症状',
sign: '体征',
clinicalDiagnosis: '临床诊断',
otherDiagnosis: '其他诊断',
relatedResult: '相关结果',
attention: '注意事项',
};
const isFieldMatched = (key) => {
return key in labelMap;
};
const getFieldLabel = (key) => {
return labelMap[key] || key;
};
const hasMatchedFields = computed(() => {
if (!descJsonData.value) return false;
return Object.keys(descJsonData.value).some((key) => isFieldMatched(key));
});
/** 查询科室 */
const getLocationInfo = () => {
getOrgList().then((res) => {
orgOptions.value = res.data.records;
});
};
const recursionFun = (targetDepartment) => {
let name = '';
for (let index = 0; index < orgOptions.value.length; index++) {
const obj = orgOptions.value[index];
if (obj.id == targetDepartment) {
name = obj.name;
}
const subObjArray = obj['children'];
for (let index = 0; index < subObjArray.length; index++) {
const item = subObjArray[index];
if (item.id == targetDepartment) {
name = item.name;
const emits = defineEmits([]);
const props = defineProps({});
const state = reactive({});
const getInfo = () => {
if (patientInfo.value?.inHospitalOrgId) {
getSurgery({
encounterId: patientInfo.value.encounterId,
}).then((res) => {
if (res.code === 200) {
} else {
}
}
});
}
return name;
};
const handleViewDetail = (row) => {
currentDetail.value = row;
// 解析 descJson
if (row.descJson) {
try {
// descJsonData.value = JSON.parse(row.descJson);
const obj = JSON.parse(row.descJson);
obj.targetDepartment = recursionFun(obj.targetDepartment);
descJsonData.value = obj;
} catch (e) {
console.error('解析 descJson 失败:', e);
descJsonData.value = null;
}
} else {
descJsonData.value = null;
}
detailDialogVisible.value = true;
};
watch(
() => patientInfo.value?.encounterId,
(val) => {
if (val) {
fetchData();
getLocationInfo();
} else {
tableData.value = [];
}
},
{ immediate: true }
);
defineExpose({
refresh: fetchData,
onBeforeMount(() => {});
onMounted(() => {
getInfo();
});
defineExpose({ state });
</script>
<style scoped lang="scss">
.report-container {
display: flex;
flex-direction: column;
gap: 12px;
padding: 8px 0;
height: 100%;
}
.report-section {
background: #fff;
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
}
.report-title {
font-weight: 600;
margin-bottom: 8px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 8px;
}
.report-table-wrapper {
flex: 1;
min-height: 0;
overflow: auto;
padding: 0 8px;
}
.report-refresh-icon {
cursor: pointer;
color: #909399;
transition: color 0.2s;
font-size: 18px;
}
.report-refresh-icon:hover {
color: #409eff;
}
.report-refresh-icon.is-loading {
animation: rotating 2s linear infinite;
}
@keyframes rotating {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
:deep(.el-dialog__body) {
padding-top: 0 !important;
}
.applicationShow-container {
display: flex;
flex-direction: column;
max-height: 70vh;
width: 100%;
overflow-y: auto;
.applicationShow-container-content {
flex-shrink: 0;
margin-bottom: 0px;
}
.applicationShow-container-table {
flex-shrink: 0;
max-height: 300px;
overflow: auto;
}
}
</style>
<style lang="scss" scoped></style>

View File

@@ -4,315 +4,34 @@
* @Description: 检验申请
-->
<template>
<div class="report-container">
<div class="report-section">
<div class="report-title">
<span>检验申请</span>
<el-icon
class="report-refresh-icon"
:class="{ 'is-loading': loading }"
@click="handleRefresh"
>
<Refresh />
</el-icon>
</div>
<div class="report-table-wrapper">
<el-table
v-loading="loading"
:data="tableData"
border
size="small"
height="100%"
style="width: 100%"
>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="patientName" label="患者姓名" width="120" />
<el-table-column prop="name" label="申请单名称" width="140" />
<el-table-column prop="createTime" label="创建时间" width="160" />
<el-table-column prop="prescriptionNo" label="处方号" width="140" />
<el-table-column prop="requesterId_dictText" label="申请者" width="120" />
<el-table-column label="操作" align="center" fixed="right">
<template #default="scope">
<el-button link type="primary" @click="handleViewDetail(scope.row)">详情</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
<!-- 详情弹窗 -->
<el-dialog
v-model="detailDialogVisible"
title="检验申请详情"
width="800px"
destroy-on-close
top="5vh"
:close-on-click-modal="false"
>
<div v-if="currentDetail" class="applicationShow-container">
<div class="applicationShow-container-content">
<el-descriptions title="基本信息" :column="2">
<el-descriptions-item label="患者姓名">{{
currentDetail.patientName || '-'
}}</el-descriptions-item>
<el-descriptions-item label="申请单名称">{{
currentDetail.name || '-'
}}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{
currentDetail.createTime || '-'
}}</el-descriptions-item>
<el-descriptions-item label="处方号">{{
currentDetail.prescriptionNo || '-'
}}</el-descriptions-item>
<el-descriptions-item label="申请者">{{
currentDetail.requesterId_dictText || '-'
}}</el-descriptions-item>
<el-descriptions-item label="就诊ID">{{
currentDetail.encounterId || '-'
}}</el-descriptions-item>
<el-descriptions-item label="申请单ID">{{
currentDetail.requestFormId || '-'
}}</el-descriptions-item>
</el-descriptions>
</div>
<div v-if="descJsonData && hasMatchedFields" class="applicationShow-container-content">
<el-descriptions title="申请单描述" :column="2">
<template v-for="(value, key) in descJsonData" :key="key">
<el-descriptions-item v-if="isFieldMatched(key)" :label="getFieldLabel(key)">
{{ value || '-' }}
</el-descriptions-item>
</template>
</el-descriptions>
</div>
<div
v-if="currentDetail.requestFormDetailList && currentDetail.requestFormDetailList.length"
class="applicationShow-container-table"
>
<el-table :data="currentDetail.requestFormDetailList" border>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="adviceName" label="医嘱名称" />
<el-table-column prop="quantity" label="数量" width="80" align="center" />
<el-table-column prop="unitCode_dictText" label="单位" width="100" />
<el-table-column prop="totalPrice" label="总价" width="100" align="right" />
</el-table>
</div>
</div>
<template #footer>
<el-button @click="detailDialogVisible = false">关闭</el-button>
</template>
</el-dialog>
<div class="container">
<el-button @click="getInfo">查询</el-button>
</div>
</template>
<script setup>
import { getCurrentInstance, ref, watch, computed } from 'vue';
import { Refresh } from '@element-plus/icons-vue';
import { patientInfo } from '../../store/patient.js';
import { getCurrentInstance, onBeforeMount, onMounted, reactive } from 'vue';
import { getInspection } from './api';
import { getOrgList } from '../../../../doctorstation/components/api.js';
import { patientInfo } from '../../store/patient.js';
const { proxy } = getCurrentInstance();
const tableData = ref([]);
const loading = ref(false);
const detailDialogVisible = ref(false);
const currentDetail = ref(null);
const descJsonData = ref(null);
const orgOptions = ref([]);
const fetchData = async () => {
if (!patientInfo.value?.encounterId) {
tableData.value = [];
loading.value = false;
return;
}
loading.value = true;
try {
const res = await getInspection({ encounterId: patientInfo.value.encounterId });
if (res.code === 200 && res.data) {
const raw = res.data?.records || res.data;
const list = Array.isArray(raw) ? raw : [raw];
tableData.value = list.filter(Boolean);
} else {
tableData.value = [];
}
} catch (e) {
proxy.$modal?.msgError?.(e.message || '查询检验申请失败');
tableData.value = [];
} finally {
loading.value = false;
}
};
const handleRefresh = async () => {
if (loading.value || !patientInfo.value?.encounterId) return;
await fetchData();
};
const labelMap = {
categoryType: '项目类别',
targetDepartment: '发往科室',
symptom: '症状',
sign: '体征',
clinicalDiagnosis: '临床诊断',
otherDiagnosis: '其他诊断',
relatedResult: '相关结果',
attention: '注意事项',
};
const isFieldMatched = (key) => {
return key in labelMap;
};
const getFieldLabel = (key) => {
return labelMap[key] || key;
};
const hasMatchedFields = computed(() => {
if (!descJsonData.value) return false;
return Object.keys(descJsonData.value).some((key) => isFieldMatched(key));
});
/** 查询科室 */
const getLocationInfo = () => {
getOrgList().then((res) => {
orgOptions.value = res.data.records;
});
};
const recursionFun = (targetDepartment) => {
let name = '';
for (let index = 0; index < orgOptions.value.length; index++) {
const obj = orgOptions.value[index];
if (obj.id == targetDepartment) {
name = obj.name;
}
const subObjArray = obj['children'];
for (let index = 0; index < subObjArray.length; index++) {
const item = subObjArray[index];
if (item.id == targetDepartment) {
name = item.name;
const emits = defineEmits([]);
const props = defineProps({});
const state = reactive({});
const getInfo = () => {
if (patientInfo.value?.inHospitalOrgId) {
getInspection({
encounterId: patientInfo.value.encounterId,
}).then((res) => {
if (res.code === 200) {
} else {
}
}
});
}
return name;
};
const handleViewDetail = (row) => {
currentDetail.value = row;
// 解析 descJson
if (row.descJson) {
try {
const obj = JSON.parse(row.descJson);
obj.targetDepartment = recursionFun(obj.targetDepartment);
descJsonData.value = obj;
// descJsonData.value = JSON.parse(row.descJson);
} catch (e) {
console.error('解析 descJson 失败:', e);
descJsonData.value = null;
}
} else {
descJsonData.value = null;
}
detailDialogVisible.value = true;
};
watch(
() => patientInfo.value?.encounterId,
(val) => {
if (val) {
fetchData();
getLocationInfo();
} else {
tableData.value = [];
}
},
{ immediate: true }
);
defineExpose({
refresh: fetchData,
onBeforeMount(() => {});
onMounted(() => {
getInfo();
});
defineExpose({ state });
</script>
<style scoped lang="scss">
.report-container {
display: flex;
flex-direction: column;
gap: 12px;
padding: 8px 0;
height: 100%;
}
.report-section {
background: #fff;
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
}
.report-title {
font-weight: 600;
margin-bottom: 8px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 8px;
}
.report-table-wrapper {
flex: 1;
min-height: 0;
overflow: auto;
padding: 0 8px;
}
.report-refresh-icon {
cursor: pointer;
color: #909399;
transition: color 0.2s;
font-size: 18px;
}
.report-refresh-icon:hover {
color: #409eff;
}
.report-refresh-icon.is-loading {
animation: rotating 2s linear infinite;
}
@keyframes rotating {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
:deep(.el-dialog__body) {
padding-top: 0 !important;
}
.applicationShow-container {
display: flex;
flex-direction: column;
max-height: 70vh;
width: 100%;
overflow-y: auto;
.applicationShow-container-content {
flex-shrink: 0;
margin-bottom: 0px;
}
.applicationShow-container-table {
flex-shrink: 0;
max-height: 300px;
overflow: auto;
}
}
</style>
<style lang="scss" scoped></style>

View File

@@ -20,7 +20,7 @@
</el-input>
</div>
<el-table
:data="conditionDatas"
:data="conditionList"
max-height="460"
@row-click="handleClickRow"
highlight-current-row
@@ -33,7 +33,7 @@
<div class="syndrome-section">
<div class="section-title">证候</div>
<div class="search-box">
<el-input v-model="searchMiddleDisease" placeholder="搜索疾病名称或编码" clearable>
<el-input v-model="searchDisease" placeholder="搜索疾病名称或编码" clearable>
<template #prefix>
<el-icon><search /></el-icon>
</template>
@@ -41,7 +41,7 @@
</div>
<div v-if="selectedDisease">
<el-table
:data="syndromeListDatas"
:data="syndromeList"
max-height="460"
@row-click="clickSyndromeRow"
highlight-current-row
@@ -85,14 +85,13 @@
</template>
</el-dialog>
</template>
<script setup>
import {
getTcmCondition,
getTcmSyndrome,
saveTcmDiagnosis,
} from '@/views/doctorstation/components/api';
import { computed } from 'vue';
const props = defineProps({
openAddDiagnosisDialog: {
@@ -112,8 +111,6 @@ const tcmDiagonsisSaveList = ref([]);
const syndromeSelected = ref(false); // 当前诊断是否选择对应证候
const timestamp = ref('');
const selectedDisease = ref(false);
const searchDisease = ref('');
const searchMiddleDisease = ref('');
const { proxy } = getCurrentInstance();
const emit = defineEmits(['close']);
@@ -123,26 +120,6 @@ function handleOpen() {
});
}
// 搜索诊断
const conditionDatas = computed(() => {
return conditionList.value.filter((item) => {
if (searchDisease.value) {
return searchDisease.value == item.name || searchDisease.value == item.ybNo;
}
return conditionList;
});
});
// 后证
const syndromeListDatas = computed(() => {
return syndromeList.value.filter((item) => {
if (searchMiddleDisease.value) {
return searchMiddleDisease.value == item.name || searchMiddleDisease.value == item.ybNo;
}
return syndromeList;
});
});
// 点击诊断列表处理,点击以后才显示证候列表
function handleClickRow(row) {
if (syndromeSelected.value || tcmDiagonsisList.value == 0) {
@@ -179,7 +156,7 @@ function clickSyndromeRow(row) {
// 删除诊断
function removeDiagnosis(row, index) {
tcmDiagonsisList.value.splice(index, 1);
tcmDiagonsisSaveList.value = tcmDiagonsisSaveList.value.filter((item) => {
tcmDiagonsisSaveList.value = tcmDiagonsisSaveList.filter((item) => {
return item.syndromeGroupNo !== row.syndromeGroupNo;
});
}
@@ -441,4 +418,4 @@ function close() {
padding: 20px 0;
text-align: center;
}
</style>
</style>

View File

@@ -1,633 +0,0 @@
<template>
<el-form :model="row" :rules="rules" :ref="(el) => (formRef = el)" :label-width="100">
<div class="expend_div" style="padding: 16px; background: #f8f9fa; border-radius: 8px">
<template v-if="row.adviceType == 1">
<div style="display: flex; align-items: center; margin-bottom: 16px; gap: 16px">
<span class="medicine-title">
{{
row.adviceName +
' ' +
row.volume +
' [' +
Number(row.unitPrice).toFixed(2) +
' 元' +
'/' +
row.unitCode_dictText +
']'
}}
</span>
<el-form-item prop="lotNumber" label="药房:">
<el-select
v-model="row.inventoryId"
style="width: 330px; margin-right: 20px"
placeholder="药房"
>
<el-option
v-for="item in row.stockList"
:key="item.inventoryId"
:value="item.inventoryId"
:label="`${item.locationName} 批次号: ${item.lotNumber ?? '-'} 库存:${stockFormat(
row.partPercent,
row.unitCodeList,
item.quantity
)}`"
@click="handleNumberClick(item)"
>
<div style="display: flex; gap: 8px; align-items: center">
<span>{{ item.locationName }}</span>
<span>批次号: {{ item.lotNumber ?? '-' }}</span>
<span>
库存{{ stockFormat(row.partPercent, row.unitCodeList, item.quantity) }}
</span>
</div>
</el-option>
</el-select>
</el-form-item>
<el-form-item
label="执行次数:"
prop="executeNum"
class="required-field"
data-prop="executeNum"
v-if="row.injectFlag == 1"
>
<el-input-number
:min="1"
v-model="row.executeNum"
controls-position="right"
:controls="false"
:ref="(el) => setInputRef('executeNum', el)"
@keyup.enter.prevent="handleEnter('executeNum')"
style="width: 70px; margin-right: 20px"
/>
</el-form-item>
<span class="medicine-info"> 诊断{{ config.diagnosisName }} </span>
<span class="medicine-info"> 皮试{{ row.skinTestFlag_enumText }} </span>
<span class="medicine-info"> 注射药品{{ row.injectFlag_enumText }} </span>
<span class="total-amount" v-if="row.therapyEnum == '2'">
总金额{{ row.totalPrice ? Number(row.totalPrice).toFixed(2) + ' ' : '0.00 ' }}
</span>
</div>
<div style="display: flex; align-items: center; gap: 12px; flex-wrap: wrap">
<div class="form-group">
<!-- 单次剂量 -->
<el-form-item
label="单次用量:"
prop="doseQuantity"
class="required-field"
data-prop="doseQuantity"
>
<el-input-number
:min="0"
v-model="row.doseQuantity"
controls-position="right"
:controls="false"
style="width: 70px"
:ref="(el) => setInputRef('doseQuantity', el)"
@input="convertValues"
@keyup.enter.prevent="handleEnter('doseQuantity')"
/>
</el-form-item>
<!-- 剂量单位 -->
<el-select
v-model="row.minUnitCode"
style="width: 70px; margin-right: 32px"
placeholder=" "
>
<template v-for="item in row.unitCodeList" :key="item.value">
<el-option
v-if="item.type == config.unitMap['minUnit']"
:value="item.value"
:label="item.label"
/>
</template>
</el-select>
<span>=</span>
<!-- 单次剂量 -->
<el-form-item prop="dose" class="required-field" data-prop="dose" label-width="0">
<el-input-number
v-model="row.dose"
controls-position="right"
:controls="false"
style="width: 70px; margin-left: 32px"
:ref="(el) => setInputRef('dose', el)"
@input="convertDoseValues"
@keyup.enter.prevent="handleEnter('dose')"
/>
</el-form-item>
<!-- 全部单位 -->
<el-select
v-model="row.doseUnitCode"
style="width: 70px"
placeholder=" "
@change="convertValues"
>
<el-option
v-for="item in row.unitCodeList"
:value="item.value"
:label="item.label"
:key="item.value"
/>
</el-select>
</div>
<div class="form-group">
<el-form-item
label="给药途径:"
prop="methodCode"
class="required-field"
data-prop="methodCode"
>
<el-select
v-model="row.methodCode"
placeholder="给药途径"
clearable
filterable
:ref="(el) => setInputRef('methodCode', el)"
style="width: 120px"
@keyup.enter.prevent="
() => {
if (row.methodCode) {
handleEnter('methodCode');
}
}
"
>
<el-option
v-for="dict in config.methodCode"
@click="() => (row.methodCode_dictText = dict.label)"
@keyup="handleEnter('methodCode')"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item
label="用药频次:"
prop="rateCode"
class="required-field"
data-prop="rateCode"
>
<el-select
v-model="row.rateCode"
placeholder="频次"
style="width: 120px"
filterable
:disabled="row.therapyEnum == '2'"
@keyup.enter.prevent="
() => {
if (row.rateCode) {
handleEnter('rateCode');
}
}
"
:ref="(el) => setInputRef('rateCode', el)"
>
<el-option
v-for="dict in config.rateCode"
@click="() => (row.rateCode_dictText = dict.label)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</div>
</div>
<div
style="display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 10px"
>
<div class="form-group">
<template v-if="row.therapyEnum == '2'">
<el-form-item
label="用药天数:"
prop="dispensePerDuration"
class="required-field"
data-prop="dispensePerDuration"
>
<el-input-number
v-model="row.dispensePerDuration"
style="width: 148px"
:min="1"
controls-position="right"
:controls="false"
:ref="(el) => setInputRef('dispensePerDuration', el)"
@keyup.enter.prevent="handleEnter('dispensePerDuration')"
>
<template #suffix></template>
</el-input-number>
</el-form-item>
<el-form-item
label="总量:"
prop="quantity"
class="required-field"
data-prop="quantity"
label-width="80"
>
<el-input-number
v-model="row.quantity"
style="width: 70px"
controls-position="right"
:controls="false"
:ref="(el) => setInputRef('quantity', el)"
@keyup.enter.prevent="handleEnter('quantity')"
@input="calculateTotalPrice"
/>
</el-form-item>
<el-select
v-model="row.unitCode"
style="width: 70px"
placeholder=" "
@change="calculateTotalAmount"
>
<template v-for="item in row.unitCodeList" :key="item.value">
<el-option
v-if="checkUnit(item)"
:value="item.value"
:label="item.label"
@click="
() => {
if (item.type == config.unitMap['minUnit']) {
row.unitPrice = row.minUnitPrice;
} else {
row.unitPrice = row.unitTempPrice;
}
row.unitCode_dictText = item.label;
}
"
/>
</template>
</el-select>
</template>
<template v-if="row.therapyEnum == '1'">
<el-form-item
label="首次用量:"
prop="firstDose"
class="required-field"
data-prop="firstDose"
>
<el-input-number
v-model="row.firstDose"
style="width: 70px"
controls-position="right"
:controls="false"
:ref="(el) => setInputRef('firstDose', el)"
@keyup.enter.prevent="handleEnter('firstDose')"
/>
</el-form-item>
<el-select v-model="row.unitCode" style="width: 70px" placeholder=" ">
<template v-for="item in row.unitCodeList" :key="item.value">
<el-option v-if="checkUnit(item)" :value="item.value" :label="item.label" />
</template>
</el-select>
</template>
</div>
<div class="form-actions">
<el-button type="primary" @click="handleSave">确定</el-button>
<el-button @click="handleCancel">取消</el-button>
</div>
</div>
</template>
<template v-else-if="row.adviceType == 2">
<div style="display: flex; align-items: center; margin-bottom: 16px; gap: 16px">
<span style="font-size: 16px; font-weight: 600">
{{
row.adviceName +
' ' +
row.volume +
' ' +
row.unitPrice +
' 元/' +
row.unitCode_dictText
}}
</span>
<div class="form-group">
<el-select
v-model="row.lotNumber"
style="width: 180px; margin-right: 20px"
placeholder="药房"
>
<el-option
v-for="item in row.stockList"
:key="item.inventoryId"
:value="item.inventoryId"
:label="`${item.locationName} 批次号: ${item.lotNumber ?? '-'} 库存:${stockFormat(
row.partPercent,
row.unitCodeList,
item.quantity
)}`"
@click="handleNumberClick(item)"
>
<div style="display: flex; gap: 8px; align-items: center">
<span>{{ item.locationName }}</span>
<span>批次号: {{ item.lotNumber ?? '-' }}</span>
<span>
库存{{ stockFormat(row.partPercent, row.unitCodeList, item.quantity) }}
</span>
</div>
</el-option>
</el-select>
<el-form-item
label="数量:"
prop="quantity"
class="required-field"
data-prop="quantity"
>
<el-input-number
placeholder="数量"
v-model="row.quantity"
style="width: 70px"
controls-position="right"
:controls="false"
@keyup.enter.prevent="handleEnter('quantity')"
@input="calculateTotalAmount"
/>
</el-form-item>
<el-select
v-model="row.unitCode"
style="width: 70px; margin-right: 20px"
placeholder=" "
@change="calculateTotalAmount"
>
<template v-for="item in row.unitCodeList" :key="item.value">
<el-option
v-if="item.type != config.unitMap['dose']"
:value="item.value"
:label="item.label"
@click="() => (row.unitCode_dictText = item.label)"
/>
</template>
</el-select>
<span class="total-amount" v-if="row.therapyEnum == '2'">
总金额{{ row.totalPrice ? Number(row.totalPrice).toFixed(2) + ' ' : '0.00 ' }}
</span>
</div>
<div class="form-actions">
<el-button type="primary" @click="handleSave">确定</el-button>
<el-button @click="handleCancel">取消</el-button>
</div>
</div>
</template>
<template v-else>
<div style="display: flex; align-items: center; margin-bottom: 16px; gap: 16px">
<span style="font-size: 16px; font-weight: 600">
{{ row.adviceName }}
{{ row.unitPrice ? Number(row.unitPrice).toFixed(2) + '/次' : '-' + '元' }}
</span>
<div class="form-group">
<el-form-item
label="执行次数:"
prop="quantity"
class="required-field"
data-prop="quantity"
>
<el-input-number
placeholder="执行次数"
style="width: 100px; margin: 0 20px"
v-model="row.quantity"
controls-position="right"
:controls="false"
@keyup.enter.prevent="handleEnter('quantity')"
@input="calculateTotalPrice"
/>
</el-form-item>
<el-form-item label="执行科室:" prop="orgId" class="required-field" data-prop="orgId">
<el-tree-select
clearable
v-model="row.orgId"
style="width: 200px"
:data="config.organization"
:props="{ value: 'id', label: 'name', children: 'children' }"
value-key="id"
check-strictly
default-expand-all
@change="handleOrgChange"
placeholder="请选择执行科室"
/>
</el-form-item>
<span class="total-amount" v-if="row.therapyEnum == '2'">
总金额{{ row.totalPrice ? Number(row.totalPrice).toFixed(2) + ' ' : '0.00 ' }}
</span>
<span style="font-size: 16px; font-weight: 600">
<!-- 金额: {{ row.priceList[0].price }} -->
</span>
</div>
<div class="form-actions">
<el-button type="primary" @click="handleSave">确定</el-button>
<el-button @click="handleCancel">取消</el-button>
</div>
</div>
</template>
</div>
</el-form>
</template>
<script setup lang="ts">
import { ref, computed, nextTick, getCurrentInstance, watch, onMounted } from 'vue';
interface Config {
diagnosisName: string; // 仅用于显示
methodCode: any[];
rateCode: any[];
organization: any[];
unitMap: {
dose: string;
minUnit: string;
unit: string;
};
}
interface Handlers {
handleEnter: (prop: string, row: any, index: number) => void;
handleNumberClick: (item: any, index: number, row: any) => void;
handleOrgChange: (value: any, index: number) => void;
convertValue: (type: 'dose' | 'doseQuantity', row: any, index: number) => void;
calculateTotal: (type: 'price' | 'amount', row: any, index: number) => void;
setInputRef: (prop: string, el: any) => void;
}
interface Props {
row: any;
index: number;
formRefName: string;
rules: any;
config: Config;
handlers: Handlers;
}
interface Emits {
(e: 'save', row: any, index: number): void;
(e: 'cancel', row: any, index: number): void;
}
const props = defineProps<Props>();
const emit = defineEmits<Emits>();
const { proxy } = getCurrentInstance() as any;
// 创建表单 ref
const formRef = ref();
// 将表单 ref 注册到父组件的 $refs 上,以便父组件可以通过 proxy.$refs['formRef' + index] 访问
const registerFormRef = () => {
if (formRef.value && proxy?.$parent?.$refs) {
proxy.$parent.$refs[props.formRefName] = formRef.value;
}
};
// 监听 formRef 变化,确保注册
watch(
() => formRef.value,
() => {
if (formRef.value) {
nextTick(() => {
registerFormRef();
});
}
},
{ immediate: true }
);
onMounted(() => {
nextTick(() => {
registerFormRef();
});
if (props.row.therapyEnum == '2' && !props.row.rateCode) {
setRateCodeToST();
}
});
watch(
() => props.row.therapyEnum,
(newVal) => {
if (newVal == '2') {
setRateCodeToST();
} else if (newVal == '1') {
props.row.rateCode = '';
props.row.rateCode_dictText = '';
}
}
);
const setRateCodeToST = () => {
if (Array.isArray(props.config.rateCode)) {
const stOption = props.config.rateCode.find((item) => item.value === 'ST');
if (stOption) {
props.row.rateCode = 'ST';
props.row.rateCode_dictText = stOption.label;
} else {
props.row.rateCode = 'ST';
props.row.rateCode_dictText = '立即';
}
}
};
// 格式化库存显示
const stockFormat = (partPercent: number, unitList: any[], quantity: number): string => {
const unitCode = unitList.find((item) => item.type == 'unit')?.label;
const minUnitCode = unitList.find((item) => item.type == 'minUnit')?.label;
const a = quantity % partPercent;
const b = Math.floor(quantity / partPercent);
if (a == 0) {
return b + ' ' + unitCode;
}
return b + ' ' + unitCode + ' ' + a + ' ' + minUnitCode;
};
// 检查单位
const checkUnit = (item: any): boolean => {
if (item.type == 'dose') {
return false;
} else if (props.row.partAttributeEnum == '2' && item.type == 'minUnit') {
return false;
} else {
return true;
}
};
const handleEnter = (prop: string) => props.handlers.handleEnter(prop, props.row, props.index);
const handleSave = () => {
nextTick(() => {
if (!formRef.value) {
console.error('Form ref not found');
return;
}
formRef.value.validate((valid: boolean) => {
if (valid) {
emit('save', props.row, props.index);
} else {
if (proxy?.$modal?.msgWarning) {
proxy.$modal.msgWarning('请完善必填信息');
}
}
});
});
};
const handleCancel = () => {
emit('cancel', props.row, props.index);
};
const handleNumberClick = (item: any) =>
props.handlers.handleNumberClick(item, props.index, props.row);
const handleOrgChange = (value: any) => props.handlers.handleOrgChange(value, props.index);
const convertValues = () => props.handlers.convertValue('doseQuantity', props.row, props.index);
const convertDoseValues = () => props.handlers.convertValue('dose', props.row, props.index);
const calculateTotalPrice = () => props.handlers.calculateTotal('price', props.row, props.index);
const calculateTotalAmount = () => props.handlers.calculateTotal('amount', props.row, props.index);
const setInputRef = props.handlers.setInputRef;
defineExpose({
stockFormat,
checkUnit,
formRef,
});
</script>
<style scoped lang="scss">
.medicine-title {
font-size: 16px;
font-weight: 600;
min-width: 280px;
display: inline-block;
}
.total-amount {
font-size: 16px;
font-weight: 600;
color: #409eff;
white-space: nowrap;
}
.medicine-info {
font-size: 15px;
font-weight: 600;
color: #606266;
white-space: nowrap;
}
.form-group {
display: flex;
align-items: center;
gap: 8px;
background: #fff;
padding: 6px 10px;
border-radius: 4px;
border: 1px solid #ebeef5;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);
}
.form-actions {
display: inline-flex;
align-items: center;
gap: 0px;
}
.expend_div {
:deep(.el-form-item--default) {
margin-bottom: 0px;
}
:deep(.el-input-number .el-input__inner) {
text-align: center;
}
}
</style>

View File

@@ -5,71 +5,49 @@
-->
<template>
<div class="bloodTransfusion-container">
<div v-loading="loading" class="transfer-wrapper">
<el-transfer
v-model="transferValue"
:data="applicationList"
filter-placeholder="项目代码/名称"
filterable
:titles="['未选择', '已选择']"
/>
</div>
<el-transfer v-model="transferValue" :data="applicationList" filter-placeholder="项目代码/名称" filterable
:titles="['未选择', '已选择']" />
<div class="bloodTransfusion-form">
<el-form :model="form" :rules="rules" ref="formRef" label-width="120px" class="demo-ruleForm">
<el-row :gutter="20">
<!-- <el-col :span="12">
<el-form-item label="项目类别" prop="categoryType" style="width: 100%">
<el-input v-model="form.categoryType" autocomplete="off" />
</el-form-item>
</el-col> -->
<el-col :span="12">
<el-form-item label="发往科室" prop="targetDepartment" style="width: 100%">
<!-- <el-input v-model="form.targetDepartment" autocomplete="off" /> -->
<el-tree-select
clearable
style="width: 100%"
v-model="form.targetDepartment"
filterable
:data="orgOptions"
:props="{
value: 'id',
label: 'name',
children: 'children',
}"
value-key="id"
check-strictly
placeholder="请选择科室"
/>
<el-form-item label="项目类别" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="症状" prop="symptom" style="width: 100%">
<el-input v-model="form.symptom" autocomplete="off" type="textarea" />
<el-form-item label="发往科室" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="体征" prop="sign" style="width: 100%">
<el-input v-model="form.sign" autocomplete="off" type="textarea" />
<el-form-item label="症状" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="临床诊断" prop="clinicalDiagnosis" style="width: 100%">
<el-input disabled v-model="form.clinicalDiagnosis" autocomplete="off" />
<el-form-item label="体征" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="其他诊断" prop="otherDiagnosis" style="width: 100%">
<el-input disabled v-model="form.otherDiagnosis" autocomplete="off" />
<el-form-item label="临床诊断" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="相关结果" prop="relatedResult" style="width: 100%">
<el-input v-model="form.relatedResult" autocomplete="off" type="textarea" />
<el-form-item label="其他诊断" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="注意事项" prop="attention" style="width: 100%">
<el-input v-model="form.attention" autocomplete="off" type="textarea" />
<el-form-item label="相关结果" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="注意事项" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
</el-row>
@@ -78,10 +56,9 @@
</div>
</template>
<script setup name="BloodTransfusion">
import { getCurrentInstance, onBeforeMount, onMounted, reactive, ref } from 'vue';
import { patientInfo } from '../../../store/patient.js';
import { getOrgList } from '../../../../../basicmanage/ward/components/api.js';
import { getEncounterDiagnosis } from '../../api.js';
const { proxy } = getCurrentInstance();
const emits = defineEmits(['submitOk']);
const props = defineProps({});
@@ -89,28 +66,20 @@ import { getApplicationList, saveBloodTransfusio } from './api';
const state = reactive({});
const applicationListAll = ref();
const applicationList = ref();
const loading = ref(false);
const orgOptions = ref([]); // 科室选项
const getList = () => {
if (!patientInfo.value?.inHospitalOrgId) {
applicationList.value = [];
return;
}
loading.value = true;
getApplicationList({
pageSize: 10000,
pageNum: 1,
categoryCode: '28',
organizationId: patientInfo.value.inHospitalOrgId,
adviceTypes: '3', //1 药品 2耗材 3诊疗
})
.then((res) => {
if (patientInfo.value?.inHospitalOrgId) {
getApplicationList({
pageSize: 10000,
pageNum: 1,
categoryCode: '28',
organizationId: patientInfo.value.inHospitalOrgId,
adviceTypes: '3', //1 药品 2耗材 3诊疗
}).then((res) => {
if (res.code === 200) {
applicationListAll.value = res.data.records;
applicationList.value = res.data.records.map((item) => {
applicationList.value = res.data.records.map((item) => {
return {
adviceDefinitionId: item.adviceDefinitionId,
orgId: item.orgId,
label: item.adviceName + item.adviceDefinitionId,
key: item.adviceDefinitionId,
};
@@ -119,112 +88,45 @@ const getList = () => {
proxy.$message.error(res.message);
applicationList.value = [];
}
})
.finally(() => {
loading.value = false;
});
}
};
const transferValue = ref([]);
const form = reactive({
// categoryType: '', // 项目类别
targetDepartment: '', // 发往科室
symptom: '', // 症状
sign: '', // 体征
clinicalDiagnosis: '', // 临床诊断
otherDiagnosis: '', // 其他诊断
relatedResult: '', // 相关结果
attention: '', // 注意事项
primaryDiagnosisList: [], //主诊断目录
otherDiagnosisList: [], //其他断目录
patientName: '',
patientSex: '',
patientAge: '',
patientPhone: '',
patientAddress: '',
});
const rules = reactive({});
onBeforeMount(() => {});
onBeforeMount(() => { });
onMounted(() => {
getList();
});
/**
* type(1watch监听类型 2:点击保存类型)
* selectProjectIds(选中项目的id数组)
* */
const projectWithDepartment = (selectProjectIds, type) => {
//1.获取选中的项目 2.判断项目的执行科室是否相同 3.判断执行科室是否配置 4.将项目的执行科室复值到执行科室下拉选位置
let isRelease = true;
// 选中项目的数组
const arr = [];
// 根据选中的项目id查找对应的项目
selectProjectIds.forEach((element) => {
const searchData = applicationList.value.find((item) => {
return element == item.adviceDefinitionId;
});
arr.push(searchData);
});
// 清空科室
form.targetDepartment = '';
if (arr.length > 0) {
const obj = arr[0];
// 判断科室是否相同
const isCompare = arr.every((item) => {
return item.orgId == obj.orgId;
});
if (!isCompare) {
ElMessage({
type: 'error',
message: '执行科室不同',
});
isRelease = false;
}
// 选中项目中的执行科室id与全部科室数据做匹配
const findItem = orgOptions.value.find((item) => {
return item.id == obj.orgId;
});
if (!findItem) {
isRelease = false;
ElMessage({
type: 'error',
message: '未找到项目执行的科室',
});
}
if (type == 1) {
if (isRelease) {
form.targetDepartment = findItem.id;
}
}
}
return isRelease;
};
// 监听选择项目变化
watch(
() => transferValue.value,
(newValue) => {
projectWithDepartment(newValue, 1);
}
);
const submit = () => {
if (transferValue.value.length == 0) {
return proxy.$message.error('请选择申请单');
}
if (!projectWithDepartment(transferValue.value, 2)) {
return;
}
let applicationListAllFilter = applicationListAll.value.filter((item) => {
return transferValue.value.includes(item.adviceDefinitionId);
});
applicationListAllFilter = applicationListAllFilter.map((item) => {
return {
adviceDefinitionId: item.adviceDefinitionId /** 诊疗定义id */,
quantity: 1, // /** 请求数量 */
unitCode: item.priceList[0].unitCode /** 请求单位编码 */,
unitPrice: item.priceList[0].price /** 单价 */,
totalPrice: item.priceList[0].price /** 总价 */,
positionId: item.positionId, //执行科室id
ybClassEnum: item.ybClassEnum, //类别医保编码
conditionId: item.conditionId, //诊断ID
encounterDiagnosisId: item.encounterDiagnosisId, //就诊诊断id
adviceType: item.adviceType, ///** 医嘱类型 */
definitionId: item.priceList[0].definitionId, //费用定价主表ID */
definitionDetailId: item.definitionDetailId, //费用定价子表ID */
accountId: patientInfo.value.accountId, // // 账户id
adviceDefinitionId: item.adviceDefinitionId, /** 诊疗定义id */
quantity: 1,// /** 请求数量 */
unitCode: item.priceList[0].unitCode, /** 请求单位编码 */
unitPrice: item.priceList[0].price, /** 单价 */
totalPrice: item.priceList[0].price, /** 总价 */
positionId: item.positionId,//执行科室id
ybClassEnum: item.ybClassEnum,//类别医保编码
conditionId: item.conditionId,//诊断ID
encounterDiagnosisId: item.encounterDiagnosisId,//就诊诊断id
adviceType: item.adviceType,///** 医嘱类型 */
definitionId: item.priceList[0].definitionId,//费用定价主表ID */
definitionDetailId: item.definitionDetailId,//费用定价子表ID */
accountId: patientInfo.value.accountId,// // 账户id
};
});
saveBloodTransfusio({
@@ -235,7 +137,7 @@ const submit = () => {
requestFormId: '', // 申请单ID
name: '输血申请单',
descJson: JSON.stringify(form),
categoryEnum: '3', // 1 检验 2 检查 3 输血 4 手术
categoryEnum: '1', // 1 检验 2 检查 3 输血 4 手术
}).then((res) => {
if (res.code === 200) {
proxy.$message.success(res.msg);
@@ -245,63 +147,19 @@ const submit = () => {
proxy.$message.error(res.message);
}
});
};
/** 查询科室 */
const getLocationInfo = () => {
getOrgList().then((res) => {
orgOptions.value = res.data?.records[0]?.children;
});
};
// 获取诊断目录
function getDiagnosisList() {
getEncounterDiagnosis(patientInfo.value.encounterId).then((res) => {
console.log('诊断目录========>', JSON.stringify(res.data));
if (res.code == 200) {
const datas = (res.data || []).map((item) => {
let obj = {
...item,
};
if (obj.diagSrtNo == null) {
obj.diagSrtNo = '1';
}
return obj;
});
// 主诊断
form.primaryDiagnosisList = datas.filter((item) => {
return item?.maindiseFlag == 1;
});
console.log('@@@@@@========>', form.primaryDiagnosisList);
if (form.primaryDiagnosisList.length == 1) {
const obj = form.primaryDiagnosisList[0];
form.clinicalDiagnosis = obj.name;
}
//其他诊断
form.otherDiagnosisList = datas.filter((item) => {
return item?.maindiseFlag !== 1;
});
const otherDiagnosisNameList = form.otherDiagnosisList.map((item) => {
return item.name;
});
form.otherDiagnosis = otherDiagnosisNameList.join(',');
}
});
}
defineExpose({ state, submit, getLocationInfo, getDiagnosisList });
defineExpose({ state, submit });
</script>
<style lang="scss" scoped>
.bloodTransfusion-container {
height: 100%;
width: 100%;
.transfer-wrapper {
position: relative;
min-height: 300px;
}
.el-transfer {
--el-transfer-panel-width: 400px !important;
}
height: 100%;
width: 100%;
.bloodTransfusion-form {
padding: 8px 8px 0 8px;
height: 100%;

View File

@@ -5,71 +5,54 @@
-->
<template>
<div class="LaboratoryTests-container">
<div v-loading="loading" class="transfer-wrapper">
<el-transfer
v-model="transferValue"
:data="applicationList"
filter-placeholder="项目代码/名称"
filterable
:titles="['未选择', '已选择']"
/>
</div>
<el-transfer
v-model="transferValue"
:data="applicationList"
filter-placeholder="项目代码/名称"
filterable
:titles="['未选择', '已选择']"
/>
<div class="bloodTransfusion-form">
<el-form :model="form" :rules="rules" ref="formRef" label-width="120px" class="demo-ruleForm">
<el-row :gutter="20">
<!-- <el-col :span="12">
<el-form-item label="项目类别" prop="categoryType" style="width: 100%">
<el-input v-model="form.categoryType" autocomplete="off" />
</el-form-item>
</el-col> -->
<el-col :span="12">
<el-form-item label="发往科室" prop="targetDepartment" style="width: 100%">
<!-- <el-input v-model="form.targetDepartment" autocomplete="off" /> -->
<el-tree-select
clearable
style="width: 100%"
v-model="form.targetDepartment"
filterable
:data="orgOptions"
:props="{
value: 'id',
label: 'name',
children: 'children',
}"
value-key="id"
check-strictly
placeholder="请选择科室"
/>
<el-form-item label="项目类别" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="症状" prop="symptom" style="width: 100%">
<el-input v-model="form.symptom" autocomplete="off" type="textarea" />
<el-form-item label="发往科室" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="体征" prop="sign" style="width: 100%">
<el-input v-model="form.sign" autocomplete="off" type="textarea" />
<el-form-item label="症状" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="临床诊断" prop="clinicalDiagnosis" style="width: 100%">
<el-input disabled v-model="form.clinicalDiagnosis" autocomplete="off" />
<el-form-item label="体征" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="其他诊断" prop="otherDiagnosis" style="width: 100%">
<el-input disabled v-model="form.otherDiagnosis" autocomplete="off" />
<el-form-item label="临床诊断" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="相关结果" prop="relatedResult" style="width: 100%">
<el-input v-model="form.relatedResult" autocomplete="off" type="textarea" />
<el-form-item label="其他诊断" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="注意事项" prop="attention" style="width: 100%">
<el-input v-model="form.attention" autocomplete="off" type="textarea" />
<el-form-item label="相关结果" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="注意事项" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
</el-row>
@@ -78,232 +61,104 @@
</div>
</template>
<script setup name="LaboratoryTests">
import { getCurrentInstance, onBeforeMount, onMounted, reactive, watch } from 'vue';
import { getCurrentInstance, onBeforeMount, onMounted, reactive } from 'vue';
import { patientInfo } from '../../../store/patient.js';
const { proxy } = getCurrentInstance();
const emits = defineEmits(['submitOk']);
const props = defineProps({});
import { getApplicationList, saveInspection } from './api';
import { getOrgList } from '../../../../../basicmanage/ward/components/api.js';
import { getEncounterDiagnosis } from '../../api.js';
import { ElMessage } from 'element-plus';
import { getApplicationList, saveCheckd } from './api';
const state = reactive({});
const applicationListAll = ref();
const applicationList = ref();
const loading = ref(false);
const orgOptions = ref([]); // 科室选项
const getList = () => {
if (!patientInfo.value?.inHospitalOrgId) {
applicationList.value = [];
return;
}
loading.value = true;
getApplicationList({
pageSize: 10000,
pageNum: 1,
categoryCode: '22',
organizationId: patientInfo.value.inHospitalOrgId,
adviceTypes: '3', //1 药品 2耗材 3诊疗
})
.then((res) => {
if (patientInfo.value?.inHospitalOrgId) {
getApplicationList({
pageSize: 10000,
pageNum: 1,
categoryCode: '23',
organizationId: patientInfo.value.inHospitalOrgId,
adviceTypes: '3', //1 药品 2耗材 3诊疗
}).then((res) => {
if (res.code === 200) {
applicationListAll.value = res.data.records;
applicationList.value = res.data.records.map((item) => {
return {
adviceDefinitionId: item.adviceDefinitionId,
orgId: item.orgId,
label: item.adviceName + item.adviceDefinitionId,
key: item.adviceDefinitionId,
};
});
console.log('applicationList========>', JSON.stringify(res.data.records));
} else {
proxy.$message.error(res.message);
applicationList.value = [];
}
})
.finally(() => {
loading.value = false;
});
}
};
const transferValue = ref([]);
const form = reactive({
// categoryType: '', // 项目类别
targetDepartment: '', // 发往科室
symptom: '', // 症状
sign: '', // 体征
clinicalDiagnosis: '', // 临床诊断
otherDiagnosis: '', // 其他诊断
relatedResult: '', // 相关结果
attention: '', // 注意事项
primaryDiagnosisList: [], //主诊断目录
otherDiagnosisList: [], //其他断目录
patientName: '',
patientSex: '',
patientAge: '',
patientPhone: '',
patientAddress: '',
});
const rules = reactive({});
onBeforeMount(() => {});
onMounted(() => {
getList();
});
/**
* type(1watch监听类型 2:点击保存类型)
* selectProjectIds(选中项目的id数组)
* */
const projectWithDepartment = (selectProjectIds, type) => {
//1.获取选中的项目 2.判断项目的执行科室是否相同 3.判断执行科室是否配置 4.将项目的执行科室复值到执行科室下拉选位置
let isRelease = true;
// 选中项目的数组
const arr = [];
// 根据选中的项目id查找对应的项目
selectProjectIds.forEach((element) => {
const searchData = applicationList.value.find((item) => {
return element == item.adviceDefinitionId;
});
arr.push(searchData);
});
// 清空科室
form.targetDepartment = '';
if (arr.length > 0) {
const obj = arr[0];
// 判断科室是否相同
const isCompare = arr.every((item) => {
return item.orgId == obj.orgId;
});
if (!isCompare) {
ElMessage({
type: 'error',
message: '执行科室不同',
});
isRelease = false;
}
// 选中项目中的执行科室id与全部科室数据做匹配
const findItem = orgOptions.value.find((item) => {
return item.id == obj.orgId;
});
if (!findItem) {
isRelease = false;
ElMessage({
type: 'error',
message: '未找到项目执行的科室',
});
}
if (type == 1) {
if (isRelease) {
form.targetDepartment = findItem.id;
}
}
}
return isRelease;
};
// 监听选择项目变化
watch(
() => transferValue.value,
(newValue) => {
projectWithDepartment(newValue, 1);
}
);
const submit = () => {
if (transferValue.value.length == 0) {
return proxy.$message.error('请选择申请单');
}
if (!projectWithDepartment(transferValue.value, 2)) {
return;
}
let applicationListAllFilter = applicationListAll.value.filter((item) => {
return transferValue.value.includes(item.adviceDefinitionId);
});
applicationListAllFilter = applicationListAllFilter.map((item) => {
return {
adviceDefinitionId: item.adviceDefinitionId /** 诊疗定义id */,
quantity: 1, // /** 请求数量 */
unitCode: item.priceList[0].unitCode /** 请求单位编码 */,
unitPrice: item.priceList[0].price /** 单价 */,
totalPrice: item.priceList[0].price /** 总价 */,
positionId: item.positionId, //执行科室id
ybClassEnum: item.ybClassEnum, //类别医保编码
conditionId: item.conditionId, //诊断ID
encounterDiagnosisId: item.encounterDiagnosisId, //就诊诊断id
adviceType: item.adviceType, ///** 医嘱类型 */
definitionId: item.priceList[0].definitionId, //费用定价主表ID */
definitionDetailId: item.definitionDetailId, //费用定价子表ID */
accountId: patientInfo.value.accountId, // // 账户id
adviceDefinitionId: item.adviceDefinitionId, /** 诊疗定义id */
quantity: 1,// /** 请求数量 */
unitCode: item.priceList[0].unitCode, /** 请求单位编码 */
unitPrice: item.priceList[0].price, /** 单价 */
totalPrice: item.priceList[0].price, /** 总价 */
positionId: item.positionId,//执行科室id
ybClassEnum: item.ybClassEnum,//类别医保编码
conditionId: item.conditionId,//诊断ID
encounterDiagnosisId: item.encounterDiagnosisId,//就诊诊断id
adviceType: item.adviceType,///** 医嘱类型 */
definitionId: item.priceList[0].definitionId,//费用定价主表ID */
definitionDetailId: item.definitionDetailId,//费用定价子表ID */
accountId: patientInfo.value.accountId,// // 账户id
};
});
const params = {
saveCheckd({
activityList: applicationListAllFilter,
patientId: patientInfo.value.patientId, //患者ID
encounterId: patientInfo.value.encounterId, // 就诊ID
organizationId: patientInfo.value.inHospitalOrgId, // 医疗机构ID
requestFormId: '', // 申请单ID
name: '检申请单',
name: '检申请单',
descJson: JSON.stringify(form),
categoryEnum: '1', // 1 检验 2 检查 3 输血 4 手术
};
saveInspection(params).then((res) => {
}).then((res) => {
if (res.code === 200) {
proxy.$message.success(res.msg);
applicationList.value = [];
emits('submitOk');
proxy.$message.success(res.msg);
applicationList.value = [];
emits('submitOk');
} else {
proxy.$message.error(res.message);
}
});
};
/** 查询科室 */
const getLocationInfo = () => {
getOrgList().then((res) => {
orgOptions.value = res.data?.records[0]?.children;
console.log('科室========>', JSON.stringify(orgOptions.value));
});
};
// 获取诊断目录
function getDiagnosisList() {
getEncounterDiagnosis(patientInfo.value.encounterId).then((res) => {
if (res.code == 200) {
const datas = (res.data || []).map((item) => {
let obj = {
...item,
};
if (obj.diagSrtNo == null) {
obj.diagSrtNo = '1';
}
return obj;
});
// 主诊断
form.primaryDiagnosisList = datas.filter((item) => {
return item?.maindiseFlag == 1;
});
console.log('@@@@@@========>', form.primaryDiagnosisList);
if (form.primaryDiagnosisList.length == 1) {
const obj = form.primaryDiagnosisList[0];
form.clinicalDiagnosis = obj.name;
}
//其他诊断
form.otherDiagnosisList = datas.filter((item) => {
return item?.maindiseFlag !== 1;
});
const otherDiagnosisNameList = form.otherDiagnosisList.map((item) => {
return item.name;
});
form.otherDiagnosis = otherDiagnosisNameList.join(',');
}
});
}
defineExpose({ state, submit, getLocationInfo, getDiagnosisList });
defineExpose({ state, submit });
</script>
<style lang="scss" scoped>
.LaboratoryTests-container {
height: 100%;
width: 100%;
.transfer-wrapper {
position: relative;
min-height: 300px;
}
.el-transfer {
--el-transfer-panel-width: 400px !important;
}
height: 100%;
width: 100%;
.bloodTransfusion-form {
padding: 8px 8px 0 8px;
height: 100%;

View File

@@ -5,71 +5,62 @@
-->
<template>
<div class="medicalExaminations-container">
<div v-loading="loading" class="transfer-wrapper">
<el-transfer
v-model="transferValue"
:data="applicationList"
filter-placeholder="项目代码/名称"
filterable
:titles="['未选择', '已选择']"
/>
</div>
<el-transfer
v-model="transferValue"
:data="applicationList"
style="width: 100%"
filter-placeholder="项目代码/名称"
filterable
:titles="['未选择', '已选择']"
/>
<div class="bloodTransfusion-form">
<el-form :model="form" :rules="rules" ref="formRef" label-width="120px" class="demo-ruleForm">
<el-form
:model="form"
:rules="rules"
ref="formRef"
label-width="120px"
class="demo-ruleForm"
inline
>
<el-row :gutter="20">
<!-- <el-col :span="12">
<el-form-item label="项目类别" prop="categoryType" style="width: 100%">
<el-input v-model="form.categoryType" autocomplete="off" />
</el-form-item>
</el-col> -->
<el-col :span="12">
<el-form-item label="发往科室" prop="targetDepartment" style="width: 100%">
<!-- <el-input v-model="form.targetDepartment" autocomplete="off" /> -->
<el-tree-select
clearable
style="width: 100%"
v-model="form.targetDepartment"
filterable
:data="orgOptions"
:props="{
value: 'id',
label: 'name',
children: 'children',
}"
value-key="id"
check-strictly
placeholder="请选择科室"
/>
<el-form-item label="项目类别" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="症状" prop="symptom" style="width: 100%">
<el-input v-model="form.symptom" autocomplete="off" type="textarea" />
<el-form-item label="发往科室" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="体征" prop="sign" style="width: 100%">
<el-input v-model="form.sign" autocomplete="off" type="textarea" />
<el-form-item label="症状" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="临床诊断" prop="clinicalDiagnosis" style="width: 100%">
<el-input disabled v-model="form.clinicalDiagnosis" autocomplete="off" />
<el-form-item label="体征" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="其他诊断" prop="otherDiagnosis" style="width: 100%">
<el-input disabled v-model="form.otherDiagnosis" autocomplete="off" />
<el-form-item label="临床诊断" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="相关结果" prop="relatedResult" style="width: 100%">
<el-input v-model="form.relatedResult" autocomplete="off" type="textarea" />
<el-form-item label="其他诊断" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="注意事项" prop="attention" style="width: 100%">
<el-input v-model="form.attention" autocomplete="off" type="textarea" />
<el-form-item label="相关结果" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="注意事项" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
</el-row>
@@ -78,40 +69,30 @@
</div>
</template>
<script setup name="MedicalExaminations">
import { getCurrentInstance, onBeforeMount, onMounted, reactive, watch } from 'vue';
import { getCurrentInstance, onBeforeMount, onMounted, reactive } from 'vue';
import { patientInfo } from '../../../store/patient.js';
import { getOrgList } from '../../../../../basicmanage/ward/components/api.js';
import { getEncounterDiagnosis } from '../../api.js';
const { proxy } = getCurrentInstance();
const emits = defineEmits(['submitOk']);
const props = defineProps({});
const orgOptions = ref([]); // 科室选项
import { getApplicationList, saveCheckd } from './api';
import { ElMessage } from 'element-plus';
import { getApplicationList, saveInspection } from './api';
const state = reactive({});
const applicationListAll = ref();
const applicationList = ref();
const loading = ref(false);
const getList = () => {
if (!patientInfo.value?.inHospitalOrgId) {
applicationList.value = [];
return;
}
loading.value = true;
getApplicationList({
pageSize: 10000,
pageNum: 1,
categoryCode: '23',
organizationId: patientInfo.value.inHospitalOrgId,
adviceTypes: '3', //1 药品 2耗材 3诊疗
})
.then((res) => {
// console.log(patientInfo.value);
if (patientInfo.value?.inHospitalOrgId) {
getApplicationList({
pageSize: 10000,
pageNum: 1,
categoryCode: '23',
organizationId: patientInfo.value.inHospitalOrgId,
adviceTypes: '3', //1 药品 2耗材 3诊疗
}).then((res) => {
if (res.code === 200) {
applicationListAll.value = res.data.records;
applicationList.value = res.data.records.map((item) => {
return {
adviceDefinitionId: item.adviceDefinitionId,
orgId: item.orgId,
label: item.adviceName + item.adviceDefinitionId,
key: item.adviceDefinitionId,
};
@@ -120,189 +101,75 @@ const getList = () => {
proxy.$message.error(res.message);
applicationList.value = [];
}
})
.finally(() => {
loading.value = false;
});
}
};
const transferValue = ref([]);
const form = reactive({
// categoryType: '', // 项目类别
targetDepartment: '', // 发往科室
symptom: '', // 症状
sign: '', // 体征
clinicalDiagnosis: '', // 临床诊断
otherDiagnosis: '', // 其他诊断
relatedResult: '', // 相关结果
attention: '', // 注意事项
primaryDiagnosisList: [], //主诊断目录
otherDiagnosisList: [], //其他断目录
patientName: '',
patientSex: '',
patientAge: '',
patientPhone: '',
patientAddress: '',
});
const rules = reactive({});
onBeforeMount(() => {});
onMounted(() => {
getList();
});
/**
* type(1watch监听类型 2:点击保存类型)
* selectProjectIds(选中项目的id数组)
* */
const projectWithDepartment = (selectProjectIds, type) => {
//1.获取选中的项目 2.判断项目的执行科室是否相同 3.判断执行科室是否配置 4.将项目的执行科室复值到执行科室下拉选位置
let isRelease = true;
// 选中项目的数组
const arr = [];
// 根据选中的项目id查找对应的项目
selectProjectIds.forEach((element) => {
const searchData = applicationList.value.find((item) => {
return element == item.adviceDefinitionId;
});
arr.push(searchData);
});
// 清空科室
form.targetDepartment = '';
if (arr.length > 0) {
const obj = arr[0];
// 判断科室是否相同
const isCompare = arr.every((item) => {
return item.orgId == obj.orgId;
});
if (!isCompare) {
ElMessage({
type: 'error',
message: '执行科室不同',
});
isRelease = false;
}
// 选中项目中的执行科室id与全部科室数据做匹配
const findItem = orgOptions.value.find((item) => {
return item.id == obj.orgId;
});
if (!findItem) {
isRelease = false;
ElMessage({
type: 'error',
message: '未找到项目执行的科室',
});
}
if (type == 1) {
if (isRelease) {
form.targetDepartment = findItem.id;
}
}
}
return isRelease;
};
// 监听选择项目变化
watch(
() => transferValue.value,
(newValue) => {
projectWithDepartment(newValue, 1);
}
);
const submit = () => {
if (transferValue.value.length == 0) {
return proxy.$message.error('请选择申请单');
}
if (!projectWithDepartment(transferValue.value, 2)) {
return;
}
let applicationListAllFilter = applicationListAll.value.filter((item) => {
return transferValue.value.includes(item.adviceDefinitionId);
});
applicationListAllFilter = applicationListAllFilter.map((item) => {
return {
adviceDefinitionId: item.adviceDefinitionId /** 诊疗定义id */,
quantity: 1, // /** 请求数量 */
unitCode: item.priceList[0].unitCode /** 请求单位编码 */,
unitPrice: item.priceList[0].price /** 单价 */,
totalPrice: item.priceList[0].price /** 总价 */,
positionId: item.positionId, //执行科室id
ybClassEnum: item.ybClassEnum, //类别医保编码
conditionId: item.conditionId, //诊断ID
encounterDiagnosisId: item.encounterDiagnosisId, //就诊诊断id
adviceType: item.adviceType, ///** 医嘱类型 */
definitionId: item.priceList[0].definitionId, //费用定价主表ID */
definitionDetailId: item.definitionDetailId, //费用定价子表ID */
accountId: patientInfo.value.accountId, // // 账户id
adviceDefinitionId: item.adviceDefinitionId, /** 诊疗定义id */
quantity: 1,// /** 请求数量 */
unitCode: item.priceList[0].unitCode, /** 请求单位编码 */
unitPrice: item.priceList[0].price, /** 单价 */
totalPrice: item.priceList[0].price, /** 总价 */
positionId: item.positionId,//执行科室id
ybClassEnum: item.ybClassEnum,//类别医保编码
conditionId: item.conditionId,//诊断ID
encounterDiagnosisId: item.encounterDiagnosisId,//就诊诊断id
adviceType: item.adviceType,///** 医嘱类型 */
definitionId: item.priceList[0].definitionId,//费用定价主表ID */
definitionDetailId: item.definitionDetailId,//费用定价子表ID */
accountId: patientInfo.value.accountId,// // 账户id
};
});
saveCheckd({
saveInspection({
activityList: applicationListAllFilter,
patientId: patientInfo.value.patientId, //患者ID
encounterId: patientInfo.value.encounterId, // 就诊ID
organizationId: patientInfo.value.inHospitalOrgId, // 医疗机构ID
requestFormId: '', // 申请单ID
name: '检申请单',
name: '检申请单',
descJson: JSON.stringify(form),
categoryEnum: '2', // 1 检验 2 检查 3 输血 4 手术
categoryEnum: '1', // 1 检验 2 检查 3 输血 4 手术
}).then((res) => {
if (res.code === 200) {
proxy.$message.success(res.msg);
applicationList.value = [];
emits('submitOk');
proxy.$message.success(res.msg);
applicationList.value = [];
emits('submitOk');
} else {
proxy.$message.error(res.message);
}
});
};
/** 查询科室 */
const getLocationInfo = () => {
getOrgList().then((res) => {
orgOptions.value = res.data?.records[0]?.children;
});
};
// 获取诊断目录
function getDiagnosisList() {
getEncounterDiagnosis(patientInfo.value.encounterId).then((res) => {
console.log('诊断目录========>', JSON.stringify(res.data));
if (res.code == 200) {
const datas = (res.data || []).map((item) => {
let obj = {
...item,
};
if (obj.diagSrtNo == null) {
obj.diagSrtNo = '1';
}
return obj;
});
// 主诊断
form.primaryDiagnosisList = datas.filter((item) => {
return item?.maindiseFlag == 1;
});
console.log('@@@@@@========>', form.primaryDiagnosisList);
if (form.primaryDiagnosisList.length == 1) {
const obj = form.primaryDiagnosisList[0];
form.clinicalDiagnosis = obj.name;
}
//其他诊断
form.otherDiagnosisList = datas.filter((item) => {
return item?.maindiseFlag !== 1;
});
const otherDiagnosisNameList = form.otherDiagnosisList.map((item) => {
return item.name;
});
form.otherDiagnosis = otherDiagnosisNameList.join(',');
}
});
}
defineExpose({ state, submit, getLocationInfo, getDiagnosisList });
defineExpose({ state, submit });
</script>
<style lang="scss" scoped>
.medicalExaminations-container {
height: 100%;
width: 100%;
.transfer-wrapper {
position: relative;
min-height: 300px;
}
.el-transfer {
--el-transfer-panel-width: 400px !important;
}
height: 100%;
width: 100%;
.bloodTransfusion-form {
padding: 8px 8px 0 8px;
height: 100%;

View File

@@ -4,228 +4,133 @@
* @Description: 手术
-->
<template>
<div class="surgery-container">
<div v-loading="loading" class="transfer-wrapper">
<el-transfer
v-model="transferValue"
:data="applicationList"
filter-placeholder="项目代码/名称"
filterable
:titles="['未选择', '已选择']"
/>
</div>
<div class="surgery-container">
<el-transfer v-model="value" :data="applicationList" filter-placeholder="项目代码/名称" filterable :titles="['未选择', '已选择']" />
<div class="bloodTransfusion-form">
<el-form :model="form" :rules="rules" ref="formRef" label-width="120px" class="demo-ruleForm">
<el-row :gutter="20">
<!-- <el-col :span="12">
<el-form-item label="项目类别" prop="categoryType" style="width: 100%">
<el-input v-model="form.categoryType" autocomplete="off" />
</el-form-item>
</el-col> -->
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="发往科室" prop="targetDepartment" style="width: 100%">
<!-- <el-input v-model="form.targetDepartment" autocomplete="off" /> -->
<el-tree-select
clearable
style="width: 100%"
v-model="form.targetDepartment"
filterable
:data="orgOptions"
:props="{
value: 'id',
label: 'name',
children: 'children',
}"
value-key="id"
check-strictly
placeholder="请选择科室"
/>
<el-form-item label="项目类别" prop="patientName" style="width:100%">
<el-input v-model="form.patientName" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="症状" prop="symptom" style="width: 100%">
<el-input v-model="form.symptom" autocomplete="off" type="textarea" />
<el-form-item label="发往科室" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="体征" prop="sign" style="width: 100%">
<el-input v-model="form.sign" autocomplete="off" type="textarea" />
<el-form-item label="症状" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="临床诊断" prop="clinicalDiagnosis" style="width: 100%">
<el-input disabled v-model="form.clinicalDiagnosis" autocomplete="off" />
<el-col :span="12">
<el-form-item label="体征" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="其他诊断" prop="otherDiagnosis" style="width: 100%">
<el-input disabled v-model="form.otherDiagnosis" autocomplete="off" />
<el-col :span="12">
<el-form-item label="临床诊断" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="相关结果" prop="relatedResult" style="width: 100%">
<el-input v-model="form.relatedResult" autocomplete="off" type="textarea" />
<el-col :span="12">
<el-form-item label="其他诊断" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="注意事项" prop="attention" style="width: 100%">
<el-input v-model="form.attention" autocomplete="off" type="textarea" />
<el-col :span="12">
<el-form-item label="相关结果" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="注意事项" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</div>
</div>
</template>
<script setup name="Surgery">
import { getCurrentInstance, onBeforeMount, onMounted, reactive } from 'vue';
import { getCurrentInstance, onBeforeMount, onMounted, reactive } from 'vue'
import { patientInfo } from '../../../store/patient.js';
import { getOrgList } from '../../../../../basicmanage/ward/components/api.js';
import { getEncounterDiagnosis } from '../../api.js';
const { proxy } = getCurrentInstance();
const emits = defineEmits(['submitOk']);
const props = defineProps({});
import { getApplicationList, saveSurgery } from './api';
import { ElMessage } from 'element-plus';
const state = reactive({});
const emits = defineEmits(['submitOk'])
const props = defineProps({
})
import { getApplicationList,saveSurgery } from './api'
const state = reactive({
})
const applicationListAll = ref();
const applicationList = ref();
const loading = ref(false);
const orgOptions = ref([]); // 科室选项
const getList = () => {
if (!patientInfo.value?.inHospitalOrgId) {
applicationList.value = [];
return;
}
loading.value = true;
getApplicationList({
const applicationList=ref()
const getList= ()=> {
if (patientInfo.value?.inHospitalOrgId) {
getApplicationList({
pageSize: 10000,
pageNum: 1,
categoryCode: '24',
organizationId: patientInfo.value.inHospitalOrgId,
adviceTypes: '3', //1 药品 2耗材 3诊疗
})
.then((res) => {
if (res.code === 200) {
applicationListAll.value = res.data.records;
applicationList.value = res.data.records.map((item) => {
adviceTypes:'3'//1 药品 2耗材 3诊疗
}
).then((res) => {
if (res.code === 200) {
applicationListAll.value = res.data.records;
applicationList.value = res.data.records.map((item) => {
return {
adviceDefinitionId: item.adviceDefinitionId,
orgId: item.orgId,
label: item.adviceName + item.adviceDefinitionId,
key: item.adviceDefinitionId,
};
});
} else {
proxy.$message.error(res.message);
applicationList.value = [];
}
})
.finally(() => {
loading.value = false;
});
};
} else {
proxy.$message.error(res.message);
applicationList.value = []
}
})
}
}
const transferValue = ref([]);
const form = reactive({
// categoryType: '', // 项目类别
targetDepartment: '', // 发往科室
symptom: '', // 症状
sign: '', // 体征
clinicalDiagnosis: '', // 临床诊断
otherDiagnosis: '', // 其他诊断
relatedResult: '', // 相关结果
attention: '', // 注意事项
primaryDiagnosisList: [], //主诊断目录
otherDiagnosisList: [], //其他断目录
});
const rules = reactive({});
onBeforeMount(() => {});
patientName: '',
patientSex: '',
patientAge: '',
patientPhone: '',
patientAddress: '',
})
const rules = reactive({
})
onBeforeMount(() => {
})
onMounted(() => {
getList();
});
/**
* type(1watch监听类型 2:点击保存类型)
* selectProjectIds(选中项目的id数组)
* */
const projectWithDepartment = (selectProjectIds, type) => {
//1.获取选中的项目 2.判断项目的执行科室是否相同 3.判断执行科室是否配置 4.将项目的执行科室复值到执行科室下拉选位置
let isRelease = true;
// 选中项目的数组
const arr = [];
// 根据选中的项目id查找对应的项目
selectProjectIds.forEach((element) => {
const searchData = applicationList.value.find((item) => {
return element == item.adviceDefinitionId;
});
arr.push(searchData);
});
// 清空科室
form.targetDepartment = '';
if (arr.length > 0) {
const obj = arr[0];
// 判断科室是否相同
const isCompare = arr.every((item) => {
return item.orgId == obj.orgId;
});
if (!isCompare) {
ElMessage({
type: 'error',
message: '执行科室不同',
});
isRelease = false;
}
// 选中项目中的执行科室id与全部科室数据做匹配
const findItem = orgOptions.value.find((item) => {
return item.id == obj.orgId;
});
if (!findItem) {
isRelease = false;
ElMessage({
type: 'error',
message: '未找到项目执行的科室',
});
}
if (type == 1) {
if (isRelease) {
form.targetDepartment = findItem.id;
}
}
}
return isRelease;
};
// 监听选择项目变化
watch(
() => transferValue.value,
(newValue) => {
projectWithDepartment(newValue, 1);
}
);
getList()
})
const submit = () => {
if (transferValue.value.length == 0) {
return proxy.$message.error('请选择申请单');
}
if (!projectWithDepartment(transferValue.value, 2)) {
return;
}
let applicationListAllFilter = applicationListAll.value.filter((item) => {
return transferValue.value.includes(item.adviceDefinitionId);
});
applicationListAllFilter = applicationListAllFilter.map((item) => {
return {
adviceDefinitionId: item.adviceDefinitionId /** 诊疗定义id */,
quantity: 1, // /** 请求数量 */
unitCode: item.priceList[0].unitCode /** 请求单位编码 */,
unitPrice: item.priceList[0].price /** 单价 */,
totalPrice: item.priceList[0].price /** 总价 */,
positionId: item.positionId, //执行科室id
ybClassEnum: item.ybClassEnum, //类别医保编码
conditionId: item.conditionId, //诊断ID
encounterDiagnosisId: item.encounterDiagnosisId, //就诊诊断id
adviceType: item.adviceType, ///** 医嘱类型 */
definitionId: item.priceList[0].definitionId, //费用定价主表ID */
definitionDetailId: item.definitionDetailId, //费用定价子表ID */
accountId: patientInfo.value.accountId, // // 账户id
adviceDefinitionId: item.adviceDefinitionId, /** 诊疗定义id */
quantity: 1,// /** 请求数量 */
unitCode: item.priceList[0].unitCode, /** 请求单位编码 */
unitPrice: item.priceList[0].price, /** 单价 */
totalPrice: item.priceList[0].price, /** 总价 */
positionId: item.positionId,//执行科室id
ybClassEnum: item.ybClassEnum,//类别医保编码
conditionId: item.conditionId,//诊断ID
encounterDiagnosisId: item.encounterDiagnosisId,//就诊诊断id
adviceType: item.adviceType,///** 医嘱类型 */
definitionId: item.priceList[0].definitionId,//费用定价主表ID */
definitionDetailId: item.definitionDetailId,//费用定价子表ID */
accountId: patientInfo.value.accountId,// // 账户id
};
});
saveSurgery({
@@ -234,80 +139,37 @@ const submit = () => {
encounterId: patientInfo.value.encounterId, // 就诊ID
organizationId: patientInfo.value.inHospitalOrgId, // 医疗机构ID
requestFormId: '', // 申请单ID
name: '手术申请单',
name: '检验申请单',
descJson: JSON.stringify(form),
categoryEnum: '4', // 1 检验 2 检查 3 输血 4 手术
}).then((res) => {
if (res.code === 200) {
proxy.$message.success(res.msg);
applicationList.value = [];
emits('submitOk');
categoryEnum: '1', // 1 检验 2 检查 3 输血 4 手术
}).then((res) => {
if (res.code === 200) {
proxy.$message.success(res.msg);
applicationList.value = [];
emits('submitOk');
} else {
proxy.$message.error(res.message);
}
});
});
};
/** 查询科室 */
const getLocationInfo = () => {
getOrgList().then((res) => {
orgOptions.value = res.data?.records[0]?.children;
});
};
// 获取诊断目录
function getDiagnosisList() {
getEncounterDiagnosis(patientInfo.value.encounterId).then((res) => {
console.log('诊断目录========>', JSON.stringify(res.data));
if (res.code == 200) {
const datas = (res.data || []).map((item) => {
let obj = {
...item,
};
if (obj.diagSrtNo == null) {
obj.diagSrtNo = '1';
}
return obj;
});
// 主诊断
form.primaryDiagnosisList = datas.filter((item) => {
return item?.maindiseFlag == 1;
});
console.log('@@@@@@========>', form.primaryDiagnosisList);
if (form.primaryDiagnosisList.length == 1) {
const obj = form.primaryDiagnosisList[0];
form.clinicalDiagnosis = obj.name;
}
//其他诊断
form.otherDiagnosisList = datas.filter((item) => {
return item?.maindiseFlag !== 1;
});
const otherDiagnosisNameList = form.otherDiagnosisList.map((item) => {
return item.name;
});
form.otherDiagnosis = otherDiagnosisNameList.join(',');
}
});
}
defineExpose({ state, submit, getLocationInfo, getDiagnosisList });
</script>
defineExpose({ state, submit });
</script>
<style lang="scss" scoped>
.surgery-container {
.surgery-container {
height: 100%;
width: 100%;
.transfer-wrapper {
position: relative;
min-height: 300px;
}
.el-transfer {
padding: 8px;
.el-transfer {
--el-transfer-panel-width: 400px !important;
}
.bloodTransfusion-form {
height: 100%;
width: 100%;
.bloodTransfusion-form {
padding: 8px 8px 0 8px;
height: 100%;
width: 100%;
display: flex;
}
}
</style>
</style>

View File

@@ -0,0 +1,108 @@
<!--
* @Author: sjjh
* @Date: 2025-04-09 17:55:05
* @Description:
-->
<template>
<div class="patient-card" v-for="item in data" :key="item.encounterId" :id="item.encounterId">
<patient-parent-card :activeId="modelValue" :type="type" :data="item" @click="parentClick">
</patient-parent-card>
<!-- // TODO 是否考虑孩子 -->
<!-- <div v-if="item.children">
<div
style="margin-top: 8px"
v-for="citem in item.children"
:key="citem.id"
:id="citem.id"
>
<patient-child-card
:active-id="modelValue"
:data="citem"
:parentData="item"
@click="childClick"
>
</patient-child-card>
</div>
</div> -->
</div>
</template>
<script setup>
import { ref, watch } from 'vue';
import PatientParentCard from './patientParentCard.vue';
// import PatientChildCard from './PatientChildCard.vue'
defineOptions({
name: 'PatientCard',
});
const props = defineProps({
modelValue: '',
data: [],
type: 0,
keyChild: '',
auto: true,
});
const value = ref(props.modelValue);
// const childClick = (node: any, parentVal: any) => {
// if (props.auto) {
// value.value = node.id
// }
// emits('click', value.value, node, parentVal)
// }
const diagnosisInit = inject('diagnosisInit')
const getAdviceList = inject('getAdviceList')
const adviceDiagnoInit = inject('adviceDiagnoInit')
// 调用方法
const parentClick = (node) => {
value.value = node.encounterId;
emits('click', value.value, node, null);
setTimeout(() => {
diagnosisInit()
getAdviceList()
adviceDiagnoInit()
}, 0);
};
const parentNode = ref();
const getItem = (val) => {
parentNode.value = null;
const re = props.data.find((item) => {
return item.encounterId === val;
});
if (re) return re;
else {
let rec;
props.data.forEach((item) => {
if (item.children) {
item.children.find((citem) => {
if (citem.encounterId === val) {
parentNode.value = item;
rec = citem;
}
});
}
});
return rec;
}
};
const emits = defineEmits(['click', 'change', 'update:modelValue']);
watch(props, (newValue) => {
value.value = newValue.modelValue;
});
watch(value, (val) => {
emits('update:modelValue', val);
emits('change', val, getItem(val), parentNode.value);
});
</script>
<style lang="scss" scoped>
.patient-card {
user-select: none;
& + .patient-card {
margin-top: 8px;
}
}
</style>

View File

@@ -0,0 +1,107 @@
<!--
* @Author: yangbo@bjgoodwill.com
* @Date: 2024-10-23 09:37:17
* @Description: 患者卡片-孩子节点
-->
<template>
<div @click="clickAct" style="display: flex">
<div class="patient-child_broken"></div>
<div
class="child-card"
:style="{
backgroundColor:
activeId === data.id ? 'rgba(19,192,179,0.05)' : '#ffffff',
borderColor: activeId === data.id ? '#13C0B3' : '#eeeeee',
}"
>
<div class="child-bed">
{{ data.bedName }}
</div>
<div class="child-line"></div>
<div class="child-name">
{{ data.name }}
<div class="child-age">{{ data.sexName }}/{{ data.age }}</div>
</div>
</div>
</div>
</template>
<script setup>
defineOptions({
name: 'PatientChildCard',
});
const props = defineProps({
data: {},
activeId: '',
parentData: {}
});
const emits = defineEmits(['click']);
const clickAct = () => {
emits('click', props.data, props.parentData);
};
</script>
<style lang="scss" scoped>
// 孩子节点
.child-card {
position: relative;
width: 214px;
height: 80px;
margin-left: 4px;
border: 1px solid;
border-radius: 4px;
box-shadow: 0 2px 2px 0 rgba(57.55, 69.04, 86.28, 20%);
cursor: pointer;
.child-bed {
position: absolute;
top: 8px;
left: 16px;
display: flex;
color: #333;
font-weight: 600;
font-size: 16px;
}
.child-line {
position: absolute;
top: 38px;
left: 16px;
width: 182px;
border-bottom: 1px dashed #ddd;
}
.child-num {
position: absolute;
top: 9px;
right: 16px;
color: #666;
font-size: 14px;
}
.child-name {
position: absolute;
top: 48px;
left: 16px;
display: flex;
color: #333;
font-size: 16px;
.child-age {
margin-top: 2.5px;
margin-left: 16px;
color: #666;
font-size: 14px;
}
}
}
// 折线
.patient-child_broken {
width: 17px;
height: 21px;
margin-top: 18px;
border-bottom: 1px solid #ddd;
border-left: 1px solid #ddd;
}
</style>

View File

@@ -0,0 +1,243 @@
<!--
* @Author: yangbo@bjgoodwill.com
* @Date: 2024-10-23 09:39:24
* @Description: 患者卡片-父节点
-->
<template>
<div
@click="clickAct"
class="patient-card"
:class="{
actived: activeId === data.encounterId,
}"
>
<!-- //跨科 考虑不考虑 -->
<div class="main-info-container">
<div class="bed-container">
<!-- 患者床号 -->
<div class="bed">
<el-text truncated :tclass="bedfont" width="auto">{{ data.bedName }}</el-text>
</div>
<!-- 新入院患者标志 -->
<!-- <div class="bed_new" /> -->
</div>
<div class="indepatient-code-container">
<!-- 患者重/危标识符 -->
<!-- <div
class="sign"
:style="{
backgroundColor: data?.criticalCarePatientName === '危' ? '#BA7BC8' : '#E95657',
}"
>
{{ data.criticalCarePatientName }}
</div> -->
<!-- 住院号 -->
<span style="margin-left: 4px"> {{ data.busNo }} </span>
</div>
</div>
<div class="doctor-parent-line" />
<div class="personal-info-container">
<div class="name-container">
<!-- 患者姓名 -->
<div class="name" style="max-width: 70px">
<el-text :text="data.patientName" tclass="name" width="auto">
{{ data.patientName }}
</el-text>
</div>
<!-- 患者性别/年龄 -->
<div class="age">{{ data.genderEnum_enumText }}/{{ data.age }}</div>
</div>
</div>
<div class="dept">
<div class="doctor">
<el-icon size="20px">
<UserFilled />
</el-icon>
<!-- // TODO 医生图标 -->
<div class="doctor_name">{{ data.admittedDoctorName }}</div>
</div>
<div class="deptNurseName">
<el-icon size="20px">
<Avatar />
</el-icon>
<!-- // TODO 护士图标 -->
{{ data.deptNurseName }}
</div>
</div>
</div>
</template>
<script setup>
defineOptions({
name: 'PatientParentCard',
})
const bedfont = 'bed-font'
const props = defineProps({
data: {},
// type0:在科、1:出院、2:转科、3:会诊、
type: 0,
activeId: ''
})
const emits = defineEmits(['click'])
const clickAct = () => {
emits('click', props.data)
}
</script>
<style lang="scss" scoped>
.patient-card {
width: 100%;
overflow: hidden;
background-color: #fff;
border: 1px solid;
border-color: #eee;
border-radius: 4px;
box-shadow: 0 2px 2px 0 rgba(57.55, 69.04, 86.28, 20%);
cursor: pointer;
&.actived {
background-color: rgb(7, 155, 140, 5%);
border-color: var(--el-color-primary);
}
.cross-dept {
height: 24px;
padding: 0 16px;
color: #fff;
font-size: 14px;
line-height: 24px;
background-color: #256d95;
}
.main-info-container {
display: flex;
align-items: center;
justify-content: space-between;
height: 24px;
margin: 7px 0;
padding: 0 16px;
.bed-container {
display: flex;
flex: 1;
align-items: center;
min-width: 0;
.bed {
flex-grow: 0;
flex-shrink: 1;
min-width: 0;
:deep(.bed-font) {
color: #333;
font-weight: 600;
font-size: 16px;
}
}
.bed_new {
flex-shrink: 0;
width: 10px;
height: 10px;
margin-left: 4px;
background: #29af6f;
border-radius: 50%;
}
}
.indepatient-code-container {
display: flex;
flex-shrink: 0;
align-items: center;
padding-left: 6px;
color: #666;
font-size: 14px;
.sign {
width: 24px;
height: 24px;
color: white;
line-height: 24px;
text-align: center;
border-radius: 50%;
user-select: none;
}
}
}
.doctor-parent-line {
margin: 0 16px;
border-bottom: 1px dashed #ddd;
}
.personal-info-container {
display: flex;
align-items: center;
justify-content: space-between;
margin: 10px 0;
padding: 0 16px;
.name-container {
display: flex;
align-items: center;
height: 24px;
.name {
color: #333;
font-size: 16px;
}
.age {
margin-left: 10px;
color: #666;
font-size: 14px;
}
}
.change-department {
width: 58px;
height: 24px;
color: #5585e3;
font-size: 14px;
line-height: 24px;
text-align: center;
background: #e6edfb;
border-radius: 4px;
}
}
.dept {
margin-bottom: 4px;
padding: 0 16px;
display: flex;
justify-content: space-between;
align-items: center;
.doctor {
display: flex;
align-items: center;
height: 32px;
line-height: 32px;
.doctor_name {
display: flex;
align-items: center;
margin-left: 4px;
color: #333;
}
}
.deptNurseName {
display: flex;
align-items: center;
height: 32px;
color: #256d95;
line-height: 32px;
}
}
}
</style>

View File

@@ -0,0 +1,385 @@
<!--
* @Author:
* @Description: 患者列表
-->
<template>
<div class="patientList-container">
<div class="patientList-operate" :class="{ 'patientList-operate-unexpand': !expand }">
<el-space>
<el-icon icon-class="Refresh" size="24" @click="getList">
<Refresh />
</el-icon>
<el-icon class="svg-sty-menu" size="24" @click="updateExpand">
<Expand v-if="!expand" />
<Fold v-if="expand" />
</el-icon>
</el-space>
</div>
<div class="patientList-list" v-if="expand">
<div class="search-operate">
<!-- 在科 -->
<el-input
placeholder="床号/住院号/姓名"
v-model="searchData.keyword"
@keyup.enter="queryPatientData"
:prefix-icon="Search"
>
</el-input>
</div>
<div class="patient-cards" v-loading="queryloading">
<template v-if="filteredCardData.length > 0">
<el-scrollbar ref="expandScrollbarRef" class="patient-cards-scrollbar">
<patient-card
v-model="cardId"
:data="filteredCardData"
:type="active"
@change="cardChange"
>
</patient-card>
</el-scrollbar>
</template>
<el-empty v-else description="暂无数据" />
</div>
</div>
<div class="patientList-list" v-loading="queryloading" v-else>
<el-scrollbar ref="contractScrollbarRef" class="patient-cards-scrollbar">
<el-tooltip
v-for="item in filteredCardData"
:show-after="200"
:key="item.encounterId"
:show-arrow="true"
placement="right"
effect="light"
:offset="4"
>
<template #content>
<div class="card-tooltip">
<span class="f-16">{{ item.bedName }}</span>
<span class="f-14">{{ item.name }}</span>
<el-icon v-if="item.sexName === '女'" :size="24"> <Female /></el-icon>
<el-icon v-else icon-class="headMale" :size="24"><Male /></el-icon>
</div>
</template>
<div>
<div
class="card-small"
:class="{ 'patient-active': cardId === item.encounterId }"
@click="smallCardClick(item)"
:key="item.encounterId"
>
{{ item.bedName }}
</div>
<div class="patient-card-small-border"></div>
</div>
</el-tooltip>
</el-scrollbar>
</div>
</div>
</template>
<script setup>
import { ref, reactive, onMounted, computed } from 'vue'
// import { store } from '@hip/portal'
import { patientInfo, updatePatientInfo } from '../store/patient'
import PatientCard from './patientCard/index.vue'
import { Search } from '@element-plus/icons-vue'
import { getPatientList } from './api'
// const props = defineProps({
// })
const expand = defineModel('expand')
// const emit = defineEmits(['update:expand'])
const active = ref(0)
const searchData = reactive({
keyword: '',
patientType: 1,
type: 1,
timeLimit: 3,
})
// const { userInfo } = store.useGlobalStore()
// 卡片
const cardId = ref('')
// 所有卡片数据
const cardAllData = ref([
// {
// id: '1',
// name: '张三',
// sexName: '女',
// bedName: '1-1床',
// deptNurseName: '护士甲',
// crossDeptFlag: false,
// criticalCarePatientName: '危',
// inpatientCode: '1212121212',
// age: '30',
// admittedDoctorName: '医生乙',
// },
// {
// id: '2',
// name: '李四',
// sexName: '男',
// bedName: '1-2床',
// deptNurseName: '护士甲',
// crossDeptFlag: false,
// criticalCarePatientName: '重',
// inpatientCode: '1212121212',
// age: '30',
// admittedDoctorName: '医生乙',
// },
])
// 过滤后的卡片数据
const filteredCardData = computed(() => {
// switch (active.value) {
// case 0:
// return cardAllData.value.filter((item: IInPatient) => {
// // const staffId = userInfo?.staffId
// // 在科患者-我的患者 住院/主治/主任医生只要有一个对应即可显示
// if (searchData.patientType === 1) {
// if (
// staffId !== item.directorDoctor &&
// staffId !== item.masterDoctor &&
// staffId !== item.admittedDoctor
// ) {
// return false
// }
// }
// // 在科患者-科室患者 全部/婴儿/非婴儿
// if (searchData.type === 2) {
// // 婴儿
// if (!(item.children && item.children.length > 0)) {
// return false
// }
// } else if (searchData.type === 3) {
// // 非婴儿
// if (item.children && item.children.length > 0) {
// return false
// }
// }
// // 关键字
// if (
// searchData.keyword &&
// !(
// item.bedName.includes(searchData.keyword) ||
// item.name.includes(searchData.keyword) ||
// item.inpatientCode.includes(searchData.keyword)
// )
// ) {
// return false
// }
// return true
// })
// default:
// return cardAllData.value
// }
return cardAllData.value
})
// 是否初始化激活状态
const isInitActive = ref(true)
// 展开患者列表Ref
const expandScrollbarRef = ref()
// 收缩患者列表Ref
const contractScrollbarRef = ref()
const queryloading = ref(false)
onMounted(() => {
cardId.value = patientInfo.value?.encounterId || ''
queryPatientData()
})
const getList = () => {
getPatientList({ status: 5 }).then((res) => {
cardAllData.value = res.data.records
})
}
/**
* 滚动到选中位置
* @param {*} value
*/
const scrollToSelected = () => {
// 如果不是第一次定位,则不进行滚动
if (!isInitActive.value) return
const currentRef = props.expand === true ? expandScrollbarRef : contractScrollbarRef
if (!currentRef.value) return
const value = getSelectedOffsetTop(currentRef)
currentRef.value.setScrollTop(value || 0)
isInitActive.value = false
}
/**
* 获取选中元素位置
* @param {*} ref
*/
const getSelectedOffsetTop = (ref) => {
const childrenNodeArray = ref?.value?.wrapRef?.children[0]?.children
if (!childrenNodeArray?.length) return 0
// TODO 当有子元素时候需要优化
const targetNode = Array.from(childrenNodeArray).find((childrenNode) => {
return childrenNode?.__vnode?.key === cardId.value
})
return targetNode?.offsetTop || 0
}
/**
* 更新展开状态
*/
const updateExpand = () => {
// emit('update:expand', !props.expand)
expand.value = !expand.value
}
const cardChange = (val, node, parent) => {
updatePatientInfo(node)
}
const smallCardClick = (val) => {
cardId.value = val.encounterId
updatePatientInfo(val)
}
// TODO 从后端获取数据
const queryPatientData = async () => {
if (queryloading.value) return
try {
// queryloading.value = true
// const res: IInPatient[] = []
// // TODO 获取患者列表
// // 设置patMiCode和patCode实际是同一字段
// res.forEach((item: IInPatient) => {
// item.patMiCode = item.patCode
// })
// cardAllData.value = res
// scrollToSelected()
} catch (error) {
cardAllData.value = []
} finally {
queryloading.value = false
}
}
getList()
</script>
<style lang="scss" scoped>
.patientList-container {
height: 100%;
display: flex;
flex-direction: column;
height: 100%;
border-right: 1px solid #ebeef5;
background-color: #ffffff;
.patientList-operate {
display: flex;
align-items: center;
justify-content: flex-end;
height: 44px;
padding: 0 8px;
border-bottom: 1px solid #ebeef5;
flex: none;
&-unexpand {
justify-content: space-around;
padding: 0 8px;
}
}
.patientList-list {
display: flex;
flex: 1;
flex-direction: column;
height: 0;
.search-operate {
padding: 0 8px;
height: 48px;
display: flex;
align-items: center;
flex: none;
}
.patient-cards {
flex: 1;
padding: 0 8px;
overflow: hidden;
:deep(.patient-cards-scrollbar) {
width: 100%;
height: 100%;
.el-scrollbar__bar {
width: 0;
}
}
}
.patient-active {
background-color: var(--el-color-primary);
}
.card-small {
height: 44px;
padding-right: 4px;
padding-left: 12px;
overflow: hidden;
font-size: 16px;
line-height: 44px;
white-space: nowrap;
text-overflow: ellipsis;
border-right: none;
cursor: pointer;
&-active {
background-color: rgb(243, 252, 251);
}
// &:hover {
// background-color: #f8f8f8;
// }
}
.patient-card-small-border {
display: block;
width: 100%;
height: 2px;
background-color: #f1faff;
}
}
}
.card-tooltip {
display: inline-flex;
align-items: center;
height: 45px;
padding: 0 10px;
}
.svg-gray {
fill: var(--hip-color-text-unit);
}
:deep(.scrollbar) {
width: 100%;
height: 100%;
.el-scrollbar__bar {
width: 0;
}
}
.f-16 {
font-weight: 600;
font-size: 16px;
}
.f-14 {
font-size: 14px;
}
.empty-wrap {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
.empty-text-sty {
margin-top: 0;
}
}
</style>

View File

@@ -1,34 +1,18 @@
/*
* @Author: sjjh
* @Date: 2025-09-20 17:02:37
* @Description:
* @Description:
*/
import request from '@/utils/request';
import request from '@/utils/request'
// ====== 文书记录
// 保存或更新记录
export function saveOrUpdateRecord(data) {
return request({
url: '/document/record/saveOrUpdateRecord',
method: 'post',
data,
});
}
// 新增记录
// 新记录
export function addRecord(data) {
return request({
url: '/document/record/addRecord',
method: 'post',
data,
});
}
// 删除历史记录
export function deleteRecord(ids) {
return request({
url: '/document/record/deleteRecord',
method: 'delete',
data: ids,
});
data
})
}
// 根据患者ID或就诊ID获取文书记录列表,只针对不需返回患者具体信息的列表,体温单除外,单独处理
@@ -36,15 +20,15 @@ export function getRecordByEncounterIdList(params) {
return request({
url: '/document/record/getRecordByEncounterIdList',
method: 'get',
params,
});
params
})
}
// 初始化文书定义
export function init() {
return request({
url: '/document/record/init',
method: 'get',
});
})
}
// ====== 文书模板
@@ -53,22 +37,24 @@ export function addTemplate(data) {
return request({
url: '/document/template/add',
method: 'post',
data,
});
data
})
}
//
export function getListByDefinitionId(definitionId) {
return request({
url: '/document/template/getListByDefinitionId',
method: 'get',
params: { definitionId },
});
params: {definitionId}
})
}
// 更新模板
export function updateTemplate(data) {
return request({
url: '/document/template/update',
method: 'put',
data,
});
data
})
}

View File

@@ -8,25 +8,14 @@
</el-input>
</div>
<el-scrollbar class="emr-history-scrollbar-container" style="width: 100%">
<div
v-for="item in historyData"
:key="item.id"
class="scrollbar-item"
:class="{ 'selected-history-item': item.id === props.selectedRecordId }"
>
<el-tooltip effect="dark" :content="`${item.name}(${item.recordTime})`" placement="bottom">
<div v-for="item in historyData" :key="item.id" class="scrollbar-item">
<el-tooltip
effect="dark"
:content="`${item.name}(${item.recordTime})`"
placement="bottom"
>
<el-text class="w-150px mb-2" truncated @click="handleNodeClick(item)">
{{ item.name }}({{ item.recordTime }})
<el-icon
class="ml-2"
style="margin-left: 26px; cursor: pointer"
:disabled="item.printCount && item.printCount > 0"
:class="{ 'disabled-icon': item.printCount && item.printCount > 0 }"
@click.stop="handleDelete(item)"
>
<Delete />
</el-icon>
</el-text>
</el-tooltip>
</div>
@@ -35,11 +24,10 @@
</template>
<script setup>
import { ref, reactive, defineEmits, unref, nextTick } from 'vue';
import { getRecordByEncounterIdList, deleteRecord } from '../api';
import { ref, reactive, defineEmits, unref } from 'vue';
import { getRecordByEncounterIdList } from '../api';
import { ElTree } from 'element-plus';
import { ElMessageBox, ElMessage, ElLoading } from 'element-plus';
import { Delete } from '@element-plus/icons-vue';
import { patientInfo } from '../../store/patient.js';
const emits = defineEmits(['historyClick']);
const props = defineProps({
@@ -47,10 +35,6 @@ const props = defineProps({
type: String,
default: '',
},
selectedRecordId: {
type: String,
default: '',
},
});
const definitionId = defineModel('definitionId', {
type: String,
@@ -67,7 +51,7 @@ const queryParams = ref({
const historyData = ref([]);
const queryList = async () => {
try {
if (patientInfo.value.encounterId && unref(definitionId) && unref(definitionId) !== '') {
if (patientInfo.value.encounterId && unref(definitionId)&&unref(definitionId) !== '') {
const res = await getRecordByEncounterIdList({
...queryParams.value,
encounterId: patientInfo.value.encounterId,
@@ -75,76 +59,46 @@ const queryList = async () => {
definitionId: unref(definitionId),
});
historyData.value = res.data || [];
} else {
}else{
historyData.value = [];
}
} catch (error) {
// 不显示错误消息,避免干扰用户体验
ElMessage.error('获取模板树失败');
historyData.value = [];
}
};
// 更新选中的历史记录ID
const updateSelectedRecord = (recordId) => {
// 这个函数可以供父组件调用,用于更新选中状态
nextTick(() => {
// 选中状态会通过props.selectedRecordId自动更新
});
};
// 删除历史记录
const handleDelete = async (item) => {
try {
// 检查是否已打印
if (item.printCount && item.printCount > 0) {
ElMessage.warning('已打印的记录不允许删除');
return;
}
await deleteRecord([item.id]);
ElMessage.success('删除成功');
queryList();
} catch (error) {
ElMessage.error('删除失败');
}
};
const handleNodeClick = (data) => {
emits('historyClick', data);
};
defineExpose({ queryList, updateSelectedRecord });
const currentSelectTemplate = ref({});
defineExpose({ queryList });
</script>
<style lang="scss" scoped>
.emr-history-container {
height: 100%;
// padding: 8px;
.search-box {
height: 40px;
line-height: 40px;
}
.emr-history-scrollbar-container {
height: 100%;
// padding: 8px;
.search-box {
height: 40px;
line-height: 40px;
}
.emr-history-scrollbar-container{
padding: 8px;
height: calc(100% - 40px);
.scrollbar-item {
height: 40px;
line-height: 40px;
border-radius: 4px;
cursor: pointer;
background: var(--el-color-primary-light-9);
& + .scrollbar-item {
margin-top: 8px;
}
transition: all 0.3s ease;
}
.selected-history-item {
background-color: rgb(194, 231, 255);
}
.disabled-icon {
color: #d9d9d9;
cursor: not-allowed;
opacity: 0.6;
.scrollbar-item {
height: 40px;
line-height: 40px;
border-radius: 4px;
cursor: pointer;
background: var(--el-color-primary-light-9);
& + .scrollbar-item {
margin-top: 8px;
}
}
}
}
</style>

View File

@@ -9,15 +9,17 @@
</div> -->
<el-scrollbar class="emr-template-scrollbar-container" style="width: 100%">
<div v-for="item in templateData" :key="item.id" class="scrollbar-item">
<el-tooltip effect="dark" :content="`${item.name}`" placement="bottom">
<el-tooltip
effect="dark"
:content="`${item.name}`"
placement="bottom"
>
<el-text class="2" truncated @click="handleNodeClick(item)">
<div class="template-item">
{{ item.name }}
<el-space>
<el-icon><Edit @click="handleEdit(item)" /></el-icon>
<el-icon><Delete @click="handleDelete(item)" /></el-icon>
</el-space>
</div>
<div class="template-item">{{ item.name }}
<el-space>
<el-icon><Edit @click="handleEdit(item)" /></el-icon>
</el-space></div>
</el-text>
</el-tooltip>
</div>
@@ -31,8 +33,7 @@ import { getListByDefinitionId } from '../api';
import { ElTree } from 'element-plus';
import { ElMessageBox, ElMessage, ElLoading } from 'element-plus';
import { patientInfo } from '../../store/patient.js';
import { Edit } from '@element-plus/icons-vue';
const emits = defineEmits(['templateClick', 'edit']);
const emits = defineEmits(['templateClick','edit']);
const props = defineProps({
definitionId: {
type: String,
@@ -54,12 +55,13 @@ const queryParams = ref({
const templateData = ref([]);
const queryList = async () => {
try {
if (unref(definitionId) && unref(definitionId) !== '') {
if ( unref(definitionId)&&unref(definitionId) !== '') {
const res = await getListByDefinitionId(unref(definitionId));
templateData.value = res.data || [];
} else {
}else{
templateData.value = [];
}
} catch (error) {
ElMessage.error('获取模板失败');
templateData.value = [];
@@ -71,60 +73,40 @@ const handleNodeClick = (data) => {
const handleEdit = (data) => {
emits('edit', data);
};
// 删除模板
const handleDelete = async (item) => {
try {
ElMessageBox.confirm('确定要删除该模板吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(async () => {
await deleteTemplate(item.id);
ElMessage.success('删除成功');
queryList();
});
} catch (error) {
if (error !== 'cancel') {
ElMessage.error('删除失败');
}
}
};
const currentSelectTemplate = ref({});
defineExpose({ queryList });
</script>
<style lang="scss" scoped>
.emr-template-container {
height: 100%;
// padding: 8px;
.emr-template-scrollbar-container {
height: 100%;
// padding: 8px;
.emr-template-scrollbar-container{
padding: 8px;
height: 100%;
.scrollbar-item {
height: 40px;
line-height: 40px;
border-radius: 4px;
cursor: pointer;
background: var(--el-color-primary-light-9);
& + .scrollbar-item {
margin-top: 8px;
}
transition: all 0.3s ease;
.el-text {
width: calc(100% - 0px);
display: flex;
justify-content: space-between;
padding: 0 8px;
}
.template-item {
width: 100%;
display: flex;
justify-content: space-between;
}
.scrollbar-item {
height: 40px;
line-height: 40px;
border-radius: 4px;
cursor: pointer;
background: var(--el-color-primary-light-9);
& + .scrollbar-item {
margin-top: 8px;
}
.el-text{
width: calc(100% - 0px);
display: flex;
justify-content: space-between;
padding: 0 8px;
}
.template-item{
width: 100%;
display: flex;
justify-content: space-between;
}
}
}
}
</style>

View File

@@ -7,7 +7,7 @@
destroy-on-close
@open="handleOpen"
>
<!-- 使用el-form包裹表单 -->
<!-- 使用el-form包裹表单 -->
<el-form :model="formData" ref="formRef" :rules="rules" label-width="120px">
<el-row :gutter="24" class="mb8">
<el-col :span="24">

View File

@@ -1,20 +1,23 @@
/*
* @Author: sjjh
* @Date: 2025-04-09 17:55:05
* @Description:
* @Description:
*/
// import { IInPatient } from '@/model/IInPatient'
import { ref } from 'vue';
import { ref } from 'vue'
// 定义护士等级(没接口前mock)
export const nursingLevel = ref('0');
export const nursingLevel = ref('0')
export function updateNursingLevel(level) {
nursingLevel.value = level;
nursingLevel.value = level
}
// 选择患者信息
export const patientInfo = ref();
export const patientInfo = ref()
export function updatePatientInfo(info) {
patientInfo.value = info;
console.log(123111);
patientInfo.value = info
}

View File

@@ -1,874 +0,0 @@
<template>
<div style="height: calc(100vh - 126px)">
<!-- 操作工具栏 -->
<div
style="
height: 51px;
border-bottom: 2px solid #e4e7ed;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 15px;
"
>
<div style="display: flex; align-items: center">
<!-- 日期选择tabs -->
<el-tabs
v-model="dateRange"
type="card"
class="date-tabs"
@tab-click="handleDateTabClick"
style="margin-right: 20px"
>
<el-tab-pane label="今日" name="today"></el-tab-pane>
<el-tab-pane label="昨日" name="yesterday"></el-tab-pane>
<!-- <el-tab-pane label="其他" name="other"></el-tab-pane> -->
</el-tabs>
<!-- 日期选择器 -->
<el-date-picker
v-model="dateRangeValue"
type="daterange"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
@change="handleDatePickerChange"
@clear="onClear"
style="width: 240px; margin-right: 20px"
/>
<!-- 费用类型选择 -->
<el-select
v-model="formParams.chargeItemEnum"
placeholder="请选择费用类型"
clearable
style="width: 150px; margin-right: 20px"
>
<el-option
v-for="type in med_chrgitm_type"
:key="type.value"
:label="type.label"
:value="type.value"
/>
</el-select>
<!-- 执行科室选择 -->
<el-select
v-model="formParams.orgId"
placeholder="请选择执行科室"
clearable
style="width: 150px; margin-right: 20px"
>
<el-option
v-for="dept in orgOptions"
:key="dept.id"
:label="dept.name"
:value="dept.id"
/>
</el-select>
<!-- 查询按钮 -->
<el-button type="primary" @click="onReset">重置</el-button>
<el-button type="primary" @click="handleQuery">查询</el-button>
</div>
<div style="display: flex; align-items: center">
<!-- 导出按钮 -->
<el-button @click="handleExport">导出</el-button>
<!-- 打印按钮 -->
<!-- <el-button @click="handlePrint" style="margin-left: 15px">打印</el-button> -->
</div>
</div>
<!-- 费用明细列表区域 -->
<div
style="padding: 10px; background-color: #eef9fd; height: 100%; overflow-y: auto"
v-loading="loading"
>
<!-- 费用汇总信息 -->
<div style="background-color: white; padding: 15px; margin-bottom: 10px; border-radius: 4px">
<div style="display: flex; justify-content: space-between; align-items: center">
<div>
<h3 style="margin: 0; font-weight: normal; color: #303133">费用汇总</h3>
<p style="margin: 5px 0; color: #606266; font-size: 14px">
费用周期{{ formatDateRange() }}
</p>
</div>
<div style="text-align: right">
<p style="margin: 0; font-size: 18px; font-weight: bold; color: #ff4d4f">
合计金额¥{{ formatNumber(totalAmount, 4) }}
</p>
<p style="margin: 5px 0; color: #606266; font-size: 14px">
明细项数{{ groupedPrescriptionList.length }}
</p>
</div>
</div>
</div>
<!-- 列表内容容器 -->
<div
v-if="groupedPrescriptionList.length > 0"
style="
flex: 1;
overflow-y: auto;
padding: 10px;
background-color: white;
border-radius: 4px;
"
>
<!-- 患者医嘱折叠面板 -->
<div class="prescription-collapse-container">
<el-collapse
v-model="activeCollapseNames"
accordion
border
style="--el-collapse-border-color: #e4e7ed"
@change="onCollapasChange"
>
<!-- 按encounterId分组渲染患者折叠项 -->
<el-collapse-item
v-for="(patientGroup, index) in groupedPrescriptionList"
:key="`patient-${index}-${safeGet(patientGroup[0], 'encounterId', index)}`"
:name="`patient-${index}`"
class="patient-collapse-item"
>
<!-- 折叠面板头部 - 患者信息 -->
<template #title>
<div class="patient-header">
<div class="patient-basic-info">
<el-avatar :icon="User" size="small" style="margin-right: 10px"></el-avatar>
<div>
<span class="patient-name">{{
safeGet(patientGroup[0], 'patientName', '未知患者')
}}</span>
<span class="patient-info-tag"
>{{ safeGet(patientGroup[0], 'genderEnum_enumText', '未知') }} /
{{ safeGet(patientGroup[0], 'age', '未知') }}</span
>
<span class="patient-info-tag"
>{{ safeGet(patientGroup[0], 'bedName', '无床位') }}{{
safeGet(patientGroup[0], 'busNo', '未知编号')
}}</span
>
</div>
</div>
<div class="patient-ext-info">
<div class="ext-item">
<span class="label">住院医生</span>
<span class="value">{{
safeGet(patientGroup[0], 'admittingDoctorName', '未知')
}}</span>
</div>
<div class="ext-item">
<span class="label">预交金余额</span>
<span class="value amount">{{
formatNumber(safeGet(patientGroup[0], 'balanceAmount', 0), 4)
}}</span>
</div>
<div class="ext-item">
<span class="label">诊断</span>
<span class="value" :title="safeGet(patientGroup[0], 'conditionNames', '无')">
{{ truncateText(safeGet(patientGroup[0], 'conditionNames', '无'), 20) }}
</span>
</div>
<div class="ext-item">
<el-tag size="small">{{
safeGet(patientGroup[0], 'contractName', '未知')
}}</el-tag>
</div>
<div class="patient-amount-preview">
小计<span class="amount">{{ calculatePatientTotal(patientGroup) }}</span>
</div>
</div>
</div>
</template>
<!-- 折叠面板内容 - 医嘱表格 -->
<div class="prescription-table-container">
<el-table
:data="safeArray(patientGroup)"
border
size="small"
style="width: 100%; margin-top: 10px"
@sort-change="handleSortChange"
>
<el-table-column label="项目名称" prop="chargeName" min-width="200" />
<el-table-column
label="费用类型"
prop="chargeItemEnum_enumText"
width="120"
align="center"
/>
<el-table-column
label="单价"
prop="unitPrice"
width="100"
align="center"
sortable
>
<template #default="scope">
{{ formatNumber(scope.row.unitPrice, 4) }}
</template>
</el-table-column>
<el-table-column
label="数量"
prop="quantityValue"
width="100"
align="center"
sortable
/>
<el-table-column
label="金额"
prop="totalPrice"
width="100"
align="center"
sortable
>
<template #default="scope">
<span style="color: #ff4d4f">{{
formatNumber(scope.row.totalPrice, 4)
}}</span>
</template>
</el-table-column>
<el-table-column :prop="orgId" label="执行科室" width="120" align="center">
<template #default="scope">
{{ selectOrg(scope.row.orgId) }}
</template>
</el-table-column>
<el-table-column label="执行人" prop="practitioner" width="100" align="center" />
<el-table-column label="执行日期" prop="recordedTime" width="120" align="center">
<template #default="scope">
{{ moment(scope.row?.recordedTime).format('YYYY-MM-DD HH:mm:ss') }}
</template>
</el-table-column>
<el-table-column
label="医保类型"
prop="chrgitmLv_enumText"
width="100"
align="center"
>
</el-table-column>
<el-table-column label="备注" prop="remark" min-width="150" />
</el-table>
</div>
</el-collapse-item>
</el-collapse>
</div>
</div>
<!-- 无数据提示 -->
<el-empty
v-if="!loading && groupedPrescriptionList.length === 0"
description="暂无费用明细数据"
/>
</div>
<!-- 打印预览弹窗 -->
<el-dialog
v-model="printDialogVisible"
title="打印预览"
width="80%"
:close-on-click-modal="false"
>
<div id="print-content">
<div style="text-align: center; margin-bottom: 20px">
<h2 style="margin: 0">费用明细清单</h2>
<p style="margin: 5px 0">患者姓名{{ patientInfo || '未选择患者' }}</p>
<p style="margin: 5px 0">费用周期{{ formatDateRange() }}</p>
</div>
<table style="width: 100%; border-collapse: collapse">
<thead>
<tr style="background-color: #eef9fd">
<th style="border: 1px solid #e4e7ed; padding: 8px">项目名称</th>
<th style="border: 1px solid #e4e7ed; padding: 8px">费用类型</th>
<th style="border: 1px solid #e4e7ed; padding: 8px">单价</th>
<th style="border: 1px solid #e4e7ed; padding: 8px">数量</th>
<th style="border: 1px solid #e4e7ed; padding: 8px">金额</th>
<th style="border: 1px solid #e4e7ed; padding: 8px">执行科室</th>
<th style="border: 1px solid #e4e7ed; padding: 8px">执行日期</th>
</tr>
</thead>
<tbody>
<tr v-for="item in feeDetailList" :key="item.id">
<td style="border: 1px solid #e4e7ed; padding: 8px">{{ item.itemName }}</td>
<td style="border: 1px solid #e4e7ed; padding: 8px">{{ item.feeTypeName }}</td>
<td style="border: 1px solid #e4e7ed; padding: 8px">
{{ item.unitPrice.toFixed(2) }}
</td>
<td style="border: 1px solid #e4e7ed; padding: 8px">{{ item.quantity }}</td>
<td style="border: 1px solid #e4e7ed; padding: 8px">{{ item.amount.toFixed(2) }}</td>
<td style="border: 1px solid #e4e7ed; padding: 8px">{{ item.execDept }}</td>
<td style="border: 1px solid #e4e7ed; padding: 8px">{{ item.executeDate }}</td>
</tr>
</tbody>
<tfoot>
<tr style="background-color: #f5f7fa">
<td
colspan="4"
style="
border: 1px solid #e4e7ed;
padding: 8px;
text-align: right;
font-weight: bold;
"
>
合计
</td>
<td
colspan="3"
style="border: 1px solid #e4e7ed; padding: 8px; color: #ff4d4f; font-weight: bold"
>
¥{{ totalAmount.toFixed(2) }}
</td>
</tr>
</tfoot>
</table>
</div>
<template #footer>
<el-button @click="printDialogVisible = false">关闭</el-button>
<el-button type="primary" @click="doPrint">打印</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref, computed, onMounted, watch, reactive } from 'vue';
import moment from 'moment';
import { ElMessage } from 'element-plus';
import { patientInfoList } from '../../components/store/patient.js';
import { formatDateStr } from '@/utils/index';
import { getCostDetail } from './api.js';
import { getOrgList } from '../../../basicmanage/ward/components/api.js';
import { User } from '@element-plus/icons-vue';
const { proxy } = getCurrentInstance();
const { med_chrgitm_type } = proxy.useDict('med_chrgitm_type');
const groupedPrescriptionList = ref([]); // 按encounterId分组后的数据
const activeCollapseNames = ref(['patient-0']); // Collapse激活状态
// 响应式数据
const loading = ref(false);
const feeDetailList = ref([]);
const dateRange = ref('today'); // today, yesterday, other
const dateRangeValue = ref([]);
const execDepartment = ref('');
const feeTypeOptions = ref([]);
const patientInfo = ref('');
const orgOptions = ref([]);
const selectIndex = ref(0);
const formParams = reactive({
chargeItemEnum: undefined,
orgId: undefined,
recordedTimeSTime: undefined,
recordedTimeETime: undefined,
pageSize: 10,
encounterIds: '',
pageNo: 1,
});
const props = defineProps({
activeTab: {
type: String,
},
});
// 分页相关
const total = ref(0);
// 打印相关
const printDialogVisible = ref(false);
// 计算总金额
const totalAmount = computed(() => {
console.log('feeDetailList========>', feeDetailList.value);
return feeDetailList?.value?.reduce((sum, item) => {
return sum + (item.totalPrice || 0);
}, 0);
});
// 初始化
onMounted(() => {
// 设置默认日期
const today = new Date();
dateRangeValue.value = [formatDateStr(today, 'YYYY-MM-DD'), formatDateStr(today, 'YYYY-MM-DD')];
});
watch(
() => patientInfoList,
(newValue) => {
if (newValue.value.length > 0) {
if (!(dateRangeValue.value == null || dateRangeValue.value == undefined)) {
formParams.recordedTimeSTime = dateRangeValue.value[0] + ' ' + '00:00:00';
formParams.recordedTimeETime = dateRangeValue.value[1] + ' ' + '23:59:59';
}
const encounterIds = newValue.value
.map((item) => {
return item.encounterId;
})
.join(',');
formParams.encounterIds = encounterIds;
if (props.activeTab === 'expenseDetail') {
getTableList();
}
}
if (newValue.value.length <= 0) {
feeDetailList.value = [];
groupedPrescriptionList.value = [];
}
},
{ deep: true }
);
// 获取列表信息
const getTableList = async () => {
const params = formParams;
try {
const res = await getCostDetail(params);
feeDetailList.value = res.data;
total.value = res.data?.total;
// 核心按encounterId分组数据
groupedPrescriptionList.value = groupByEncounterId(res.data);
// 默认展开第一个患者面板
if (groupedPrescriptionList.value.length > 0 && activeCollapseNames.value.length === 0) {
activeCollapseNames.value = ['patient-0'];
}
} catch (error) {}
};
// 监听患者选择变化
function watchPatientSelection() {
// 定期检查患者选择状态变化
setInterval(() => {
if (patientInfoList.value && patientInfoList.value.length > 0) {
const selectedPatient = patientInfoList.value.find((patient) => patient.selected === true);
if (selectedPatient) {
patientInfo.value = selectedPatient.patientName || '';
} else {
patientInfo.value = '未选择患者';
}
} else {
patientInfo.value = '未选择患者';
}
}, 300);
}
/** 查询科室 */
const getLocationInfo = () => {
getOrgList().then((res) => {
orgOptions.value = res.data?.records[0]?.children;
});
};
getLocationInfo();
// 映射
const selectOrg = (itemid) => {
const item = orgOptions.value.find((item) => {
return item.id == itemid;
});
return item?.name;
};
// 重置
const onReset = () => {
const today = new Date();
dateRangeValue.value = [formatDateStr(today, 'YYYY-MM-DD'), formatDateStr(today, 'YYYY-MM-DD')];
formParams.orgId = undefined;
formParams.chargeItemEnum = undefined;
formParams.recordedTimeSTime = dateRangeValue.value[0] + ' ' + '00:00:00';
formParams.recordedTimeETime = dateRangeValue.value[1] + ' ' + '23:59:59';
dateRange.value = 'today';
getTableList();
};
// 加载费用类型选项
function loadFeeTypeOptions() {
// 模拟费用类型数据
feeTypeOptions.value = [
{ label: '检查费', value: 'examine' },
{ label: '治疗费', value: 'treatment' },
{ label: '药品费', value: 'medicine' },
{ label: '材料费', value: 'material' },
{ label: '床位费', value: 'bed' },
{ label: '其他费用', value: 'others' },
];
}
// 处理日期tabs点击
function handleDateTabClick(tab) {
const rangeType = tab.paneName;
const today = new Date();
const yesterday = new Date();
yesterday.setDate(today.getDate() - 1);
switch (rangeType) {
case 'today':
dateRangeValue.value = [
formatDateStr(today, 'YYYY-MM-DD'),
formatDateStr(today, 'YYYY-MM-DD'),
];
break;
case 'yesterday':
dateRangeValue.value = [
formatDateStr(yesterday, 'YYYY-MM-DD'),
formatDateStr(yesterday, 'YYYY-MM-DD'),
];
break;
// other 情况保持用户选择的值
}
if (!(dateRangeValue.value == null || dateRangeValue.value == undefined)) {
formParams.recordedTimeSTime = dateRangeValue.value[0] + ' ' + '00:00:00';
formParams.recordedTimeETime = dateRangeValue.value[1] + ' ' + '23:59:59';
}
getTableList();
}
// 处理日期选择器变化
function handleDatePickerChange() {
if (dateRangeValue?.value?.length > 0) {
// dateRange.value = 'other';
formParams.recordedTimeSTime = dateRangeValue.value[0] + ' ' + '00:00:00';
formParams.recordedTimeETime = dateRangeValue.value[1] + ' ' + '23:59:59';
} else {
formParams.recordedTimeSTime = undefined;
formParams.recordedTimeETime = undefined;
}
}
// 清空
const onClear = () => {
console.log('1111111111');
const today = new Date();
dateRangeValue.value = [formatDateStr(today, 'YYYY-MM-DD'), formatDateStr(today, 'YYYY-MM-DD')];
formParams.orgId = undefined;
formParams.chargeItemEnum = undefined;
formParams.recordedTimeSTime = dateRangeValue.value[0] + ' ' + '00:00:00';
formParams.recordedTimeETime = dateRangeValue.value[1] + ' ' + '23:59:59';
dateRange.value = 'today';
getTableList();
};
// 格式化日期范围显示
function formatDateRange() {
if (dateRangeValue.value && dateRangeValue.value.length === 2) {
return `${dateRangeValue.value[0]}${dateRangeValue.value[1]}`;
}
return '';
}
// 查询按钮点击
function handleQuery() {
console.log('params=======>', formParams);
getTableList();
}
// 处理排序变化
function handleSortChange({ prop, order }) {
// const sortedData = [...feeDetailList.value];
const selectData = groupedPrescriptionList.value[selectIndex.value];
const sortedData = [...selectData];
if (order === 'ascending') {
sortedData.sort((a, b) => (a[prop] > b[prop] ? 1 : -1));
} else if (order === 'descending') {
sortedData.sort((a, b) => (a[prop] < b[prop] ? 1 : -1));
}
groupedPrescriptionList.value[selectIndex.value] = sortedData;
// feeDetailList.value = sortedData;
}
// 处理分页大小变化
function handleSizeChange(newSize) {
formParams.pageSize = newSize;
formParams.pageNo = 1;
getTableList();
}
// 处理当前页变化
function handleCurrentChange(newCurrent) {
formParams.pageNo = newCurrent;
getTableList();
}
// 导出
async function handleExport() {
if (groupedPrescriptionList.value.length === 0) {
ElMessage.warning('暂无数据可导出');
return;
}
try {
// 实际项目中这里应该调用导出API或使用Excel库生成文件
await proxy.$download.downloadGet(
'/inhospitalnursestation/nursebilling/excel-out',
{
...formParams,
},
`dict_${new Date().getTime()}.xlsx`
);
} catch (error) {}
}
// 打印预览
function handlePrint() {
if (feeDetailList.value.length === 0) {
ElMessage.warning('暂无数据可打印');
return;
}
printDialogVisible.value = true;
}
// 执行打印
function doPrint() {
try {
// 获取要打印的内容
const printContent = document.getElementById('print-content').innerHTML;
// 创建临时窗口
const printWindow = window.open('', '_blank');
// 写入内容
printWindow.document.write(`
<html>
<head>
<title>费用明细清单</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
table { width: 100%; border-collapse: collapse; }
th, td { border: 1px solid #ccc; padding: 8px; }
th { background-color: #f2f2f2; }
tfoot { font-weight: bold; }
.total-row { background-color: #f5f5f5; }
</style>
</head>
<body>
${printContent}
</body>
</html>
`);
// 打印
printWindow.document.close();
printWindow.focus();
printWindow.print();
} catch (e) {
ElMessage.error('打印失败');
console.error('Print error:', e);
}
}
// 获取当前展开折叠板索引
function onCollapasChange(select) {
if (select) {
const selectArr = select.split('-');
if (selectArr && selectArr.length > 1) {
const idx = selectArr[1];
selectIndex.value = Number(idx);
}
}
}
// ========== 核心工具函数 ==========
/**
* 安全获取对象属性,避免空值报错
* @param {Object} obj - 源对象
* @param {String} path - 属性路径
* @param {Any} defaultValue - 默认值
* @returns {Any}
*/
const safeGet = (obj, path, defaultValue = '') => {
// 1. 前置校验:如果源对象不是对象类型,直接返回默认值
if (!obj || typeof obj !== 'object') return defaultValue;
// 2. 拆分路径:把 "info.basic.name" 拆成 ["info", "basic", "name"]
const paths = path.split('.');
// 3. 初始化结果为源对象
let result = obj;
// 4. 循环遍历路径数组,逐层访问属性
for (const p of paths) {
// 5. 关键如果当前层属性不存在undefined/null直接返回默认值
if (result[p] === undefined || result[p] === null) return defaultValue;
// 6. 存在则继续访问下一层
result = result[p];
}
// 7. 所有层级都存在,返回最终属性值
return result;
};
/**
* 安全转换为数组
* @param {Any} data - 待转换数据
* @returns {Array}
*/
const safeArray = (data) => {
return Array.isArray(data) ? data : [];
};
/**
* 格式化数字保留4位小数金额专用
* @param {Number} num - 数字
* @param {Number} decimal - 小数位数默认4位
* @returns {String}
*/
const formatNumber = (num, decimal = 4) => {
if (isNaN(Number(num))) return '0.0000';
// 保留指定小数位不足补0
return Number(num).toFixed(decimal);
};
/**
* 文本截断(超出长度显示省略号)
* @param {String} text - 待处理文本
* @param {Number} length - 最大长度
* @returns {String}
*/
const truncateText = (text, length = 20) => {
if (!text || text.length <= length) return text;
return `${text.slice(0, length)}...`;
};
/**
* 按encounterId分组数据
* @param {Array} data - 原始数据
* @returns {Array} 分组后的数据(二维数组)
*/
const groupByEncounterId = (data) => {
const grouped = {};
safeArray(data).forEach((item) => {
const encounterId = safeGet(item, 'encounterId', 'unknown');
if (!grouped[encounterId]) {
grouped[encounterId] = [];
}
grouped[encounterId].push({
...item,
});
});
// 转换为数组格式
return Object.values(grouped);
};
/**
* 计算单个患者的总金额保留4位小数
* @param {Array} patientGroup - 患者医嘱列表
* @returns {String} 格式化后的金额字符串
*/
const calculatePatientTotal = (patientGroup) => {
const total = safeArray(patientGroup).reduce((sum, item) => {
return Math.round((sum + Number(safeGet(item, 'totalPrice', 0))) * 10000) / 10000;
}, 0);
return formatNumber(total, 4);
};
// 暴露方法供父组件调用
defineExpose({
handleQuery,
});
</script>
<style scoped>
/* 日期tabs样式 */
.date-tabs .el-tabs__header {
margin-bottom: 0;
}
.date-tabs .el-tabs__content {
display: none;
}
/* :deep(.el-table__header th) {
background-color: #eef9fd !important;
} */
:deep(.el-table__row:hover > td) {
background-color: #eef9fd !important;
}
/* 折叠面板容器 */
.prescription-collapse-container {
--el-collapse-item-border-radius: 8px;
}
/* 患者折叠项 */
.patient-collapse-item {
margin-bottom: 12px;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
}
/* 患者头部 */
.patient-header {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
padding: 4px 0;
padding-left: 10px;
flex-wrap: wrap;
gap: 8px;
}
.patient-basic-info {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 8px;
}
.patient-name {
font-weight: 600;
font-size: 15px;
margin-right: 10px;
}
.patient-info-tag {
color: #666;
font-size: 13px;
margin-right: 8px;
}
.patient-ext-info {
display: flex;
align-items: center;
gap: 15px;
flex-wrap: wrap;
}
.ext-item {
display: flex;
align-items: center;
font-size: 13px;
flex-wrap: wrap;
}
.ext-item .label {
color: #999;
margin-right: 4px;
}
.ext-item .amount {
color: #e6a23c;
font-weight: 600;
}
.patient-amount-preview {
font-size: 13px;
color: #333;
margin-left: 10px;
}
.patient-amount-preview .amount {
color: #e6a23c;
font-weight: 600;
}
.prescription-table-container {
padding: 10px 0;
}
</style>

View File

@@ -1,136 +0,0 @@
<template>
<div class="nurse-nav-bar" :style="{ background: background }">
<div class="nav-scroll">
<div
v-for="nav in navs"
:key="nav.path"
class="nav-tab"
:class="{ 'is-active': currentPath === nav.path, disabled: nav.disabled }"
:style="nav.accent ? { '--accent-color': nav.accent } : null"
@click="() => handleNav(nav)"
>
<div class="nav-icon" v-if="nav.icon">
<component :is="nav.icon" />
</div>
<span class="nav-label">{{ nav.label }}</span>
<span v-if="nav.desc" class="nav-desc">{{ nav.desc }}</span>
</div>
</div>
</div>
</template>
<script setup>
import { computed } from 'vue';
import { useRoute, useRouter } from 'vue-router';
const props = defineProps({
navs: {
type: Array,
default: () => [],
},
activePath: {
type: String,
default: '',
},
background: {
type: String,
default: '#f8f9fb',
},
});
const emit = defineEmits(['navigate']);
const route = useRoute();
const router = useRouter();
const currentPath = computed(() => props.activePath || route.path);
function handleNav(nav) {
if (nav.disabled) return;
emit('navigate', nav);
if (nav.path && nav.path !== currentPath.value) {
router.push(nav.path);
}
}
</script>
<style scoped>
.nurse-nav-bar {
--theme-color: var(--el-color-primary, #409eff);
height: 40px;
border-bottom: 1px solid #e4e7ed;
padding: 0 12px;
display: flex;
align-items: center;
}
.nav-scroll {
display: flex;
gap: 8px;
align-items: center;
flex-wrap: wrap;
width: 100%;
}
.nav-tab {
height: 32px;
padding: 0 14px;
border-radius: 16px;
background: #fff;
border: 1px solid transparent;
display: inline-flex;
align-items: center;
gap: 6px;
cursor: pointer;
transition: all 0.15s ease;
position: relative;
color: #1f2d3d;
font-size: 14px;
}
.nav-tab:hover {
border-color: rgba(64, 158, 255, 0.45);
color: var(--theme-color);
background: rgba(64, 158, 255, 0.08);
}
.nav-tab.is-active {
background: rgba(64, 158, 255, 0.18);
border-color: var(--theme-color);
color: var(--theme-color);
box-shadow: 0 3px 8px rgba(64, 158, 255, 0.12);
}
.nav-tab.disabled {
opacity: 0.5;
cursor: not-allowed;
box-shadow: none;
}
.nav-icon {
width: 18px;
height: 18px;
border-radius: 50%;
background: rgba(64, 158, 255, 0.12);
display: inline-flex;
align-items: center;
justify-content: center;
color: var(--accent-color, var(--theme-color));
font-size: 12px;
}
.nav-tab.is-active .nav-icon {
background: rgba(255, 255, 255, 0.8);
color: var(--theme-color);
}
.nav-label {
font-weight: 600;
}
.nav-desc {
font-size: 12px;
color: #909399;
}
</style>

View File

@@ -1,23 +0,0 @@
import request from '@/utils/request'
/**
* 获取住院患者列表
*/
export function getPatientList(queryParams) {
return request({
url: '/nurse-station/advice-process/inpatient',
method: 'get',
params: queryParams
})
}
/**
* 获取当前登录人管理病区
*/
export function getWardList(queryParams) {
return request({
url: '/app-common/practitioner-ward',
method: 'get',
params: queryParams
})
}

View File

@@ -1,305 +0,0 @@
<template>
<div>
<div>
<el-input placeholder="住院号/姓名" v-model="searchKey" @keyup.enter="handleSearch">
<template #append>
<el-button icon="Search" @click="handleSearch" />
</template>
</el-input>
</div>
<el-tree
ref="treeRef"
:key="treeKey"
:load="loadNode"
lazy
show-checkbox
node-key="id"
default-expand-all
:props="{ label: 'name', children: 'children' }"
@node-click="handleNodeClick"
@check="handleCheckChange"
>
<template #default="{ node, data }">
<div class="custom-tree-node" v-if="node.level === 2">
<span>{{ data.bedName + ' / ' + node.label }}</span>
<span class="tree-node-actions">
{{ data.genderEnum_enumText + ' / ' + data.age }}
</span>
</div>
</template>
</el-tree>
</div>
</template>
<script setup>
import { getPatientList, getWardList } from './api';
import { updatePatientInfoList } from './store/patient';
import { ref, nextTick, inject, defineExpose } from 'vue';
const treeRef = ref(null);
const searchKey = ref('');
const treeKey = ref(0); // 用于强制重新渲染树组件
const wardList = ref([]); // 存储病区列表
const patientDataCache = ref(new Map()); // 缓存患者数据key为wardIdvalue为患者列表
const handleGetPrescription = inject('handleGetPrescription');
/**
* 加载树节点数据
* @param {Object} node - 树节点对象
* @param {Function} resolve - 解析函数,用于返回子节点数据
*/
function loadNode(node, resolve) {
// 根节点:加载所有病区
if (node.level === 0) {
loadWardList(resolve);
}
// 病区节点:加载该病区下的患者列表
else if (node.level === 1) {
const wardId = node.data.id;
loadPatientList(wardId, resolve);
}
// 其他层级返回空数组
else {
resolve([]);
}
}
/**
* 加载病区列表
* @param {Function} resolve - 解析函数
*/
function loadWardList(resolve) {
getWardList()
.then((res) => {
// 格式化病区数据
const wards = Array.isArray(res) ? res : res.data || [];
wardList.value = wards;
// 将病区数据转换为树节点格式
const wardNodes = wards.map((ward) => ({
id: ward.id,
name: ward.name || ward.wardName || '',
leaf: false, // 病区节点不是叶子节点
...ward,
}));
resolve(wardNodes);
})
.catch((error) => {
console.error('加载病区列表失败:', error);
resolve([]);
});
}
/**
* 加载指定病区的患者列表
* @param {String|Number} wardId - 病区ID
* @param {Function} resolve - 解析函数
*/
function loadPatientList(wardId, resolve) {
// 构建缓存键(包含搜索条件)
const cacheKey = `${wardId}_${searchKey.value || ''}`;
// 如果缓存中存在且搜索条件为空,直接使用缓存(搜索时需要重新加载)
if (!searchKey.value && patientDataCache.value.has(cacheKey)) {
const cachedPatients = patientDataCache.value.get(cacheKey);
resolve(cachedPatients);
return;
}
// 调用接口获取患者列表
getPatientList({
wardId: wardId,
searchKey: searchKey.value || '',
})
.then((res) => {
// 处理返回的患者数据
const records = res?.data?.records || [];
// 格式化患者数据
const patients = records.map((item) => ({
id: item.id || item.encounterId,
name: item.patientName || '',
leaf: true, // 患者节点是叶子节点
...item,
}));
// 缓存患者数据(仅在没有搜索条件时缓存)
if (!searchKey.value) {
patientDataCache.value.set(cacheKey, patients);
}
resolve(patients);
})
.catch((error) => {
console.error('加载患者列表失败:', error);
resolve([]);
});
}
/**
* 重新加载所有病区的患者列表
*/
function reloadAllPatients() {
if (!treeRef.value) return;
// 清除患者数据缓存
patientDataCache.value.clear();
nextTick(() => {
const rootNode = treeRef.value?.store?.root;
if (!rootNode?.childNodes) return;
// 遍历所有已展开的病区节点,重新加载患者列表
rootNode.childNodes.forEach((wardNode) => {
if (wardNode && wardNode.level === 1 && wardNode.key) {
reloadWardNodePatients(wardNode);
}
});
});
}
/**
* 重新加载指定病区节点的患者列表
* @param {Object} wardNode - 病区节点对象
*/
function reloadWardNodePatients(wardNode) {
if (!wardNode?.key || !treeRef.value) return;
const wardId = wardNode.data.id;
const cacheKey = `${wardId}_${searchKey.value || ''}`;
// 清除该病区的缓存
patientDataCache.value.delete(cacheKey);
// 清除旧的子节点
treeRef.value.updateKeyChildren(wardNode.key, []);
// 重置节点状态
wardNode.loaded = false;
wardNode.childNodes = [];
// 重新加载患者列表
loadPatientList(wardId, (children) => {
treeRef.value.updateKeyChildren(wardNode.key, children);
});
}
/**
* 重新加载指定病区的患者列表
* @param {String|Number} wardId - 病区ID
*/
function reloadWardPatients(wardId) {
if (!treeRef.value) return;
nextTick(() => {
const rootNode = treeRef.value?.store?.root;
if (!rootNode?.childNodes) return;
// 查找对应的病区节点
const wardNode = rootNode.childNodes.find((node) => node.data.id === wardId);
if (wardNode) {
reloadWardNodePatients(wardNode);
}
});
}
/**
* 手动触发加载节点
* @param {Object} node - 节点对象如果为null则重新加载整个树
*/
function manualLoadNode(node = null) {
if (!node) {
// 重新加载整个树
treeKey.value += 1;
patientDataCache.value.clear();
} else if (node.key && treeRef.value) {
// 重新加载指定节点
if (node.level === 1) {
// 病区节点:重新加载患者列表
reloadWardNodePatients(node);
} else if (node.level === 0) {
// 根节点:重新加载病区列表
loadWardList((wards) => {
treeRef.value.updateKeyChildren(node.key, wards);
});
}
}
}
/**
* 获取所有选中的叶子节点(患者节点)
* @returns {Array} 患者节点数组
*/
function getCheckedLeafNodes() {
if (!treeRef.value) return [];
// 获取所有选中的节点数据
const checkedNodes = treeRef.value.getCheckedNodes() || [];
// 只返回叶子节点(患者节点)
return checkedNodes.filter((node) => node.leaf === true);
}
/**
* 处理节点选中状态变化
* @param {Object} data - 节点数据
* @param {Object} checked - 选中状态对象
*/
function handleCheckChange(data, checked) {
const checkedPatients = getCheckedLeafNodes();
updatePatientInfoList(checkedPatients);
// 调用父组件的方法获取处方列表
if (handleGetPrescription && typeof handleGetPrescription === 'function') {
handleGetPrescription();
}
}
/**
* 处理节点点击事件
* @param {Object} data - 节点数据
* @param {Object} node - 节点对象
*/
function handleNodeClick(data, node) {
// 节点点击处理逻辑(可根据需要添加)
}
/**
* 处理搜索
*/
function handleSearch() {
// 清除缓存(搜索时需要重新加载)
patientDataCache.value.clear();
// 重新加载所有已展开病区的患者列表
reloadAllPatients();
}
// 暴露方法供外部调用
defineExpose({
manualLoadNode,
reloadAllPatients,
reloadWardPatients,
handleSearch,
});
</script>
<style scoped lang="scss">
.custom-tree-node {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
}
.tree-node-actions {
display: flex;
align-items: center;
}
:deep(.el-tree-node__content) {
height: 35px;
}
</style>

View File

@@ -1,45 +0,0 @@
export const inpatientNurseNavs = [
{
label: '入出转',
path: '/inHospital/statistics/inOut',
icon: 'Document',
accent: '#5b8ff9',
},
{
label: '护理记录',
path: '/inHospital/statistics/nursingRecord',
icon: 'MedicineBox',
accent: '#13c2c2',
},
{
label: '三测单',
path: '/inHospital/statistics/tprChart',
icon: 'List',
accent: '#ffc53d',
},
{
label: '医嘱执行',
path: '/inHospital/statistics/medicalOrderExecution',
icon: 'Finished',
accent: '#73d13d',
},
{
label: '医嘱校对',
path: '/inHospital/statistics/medicalOrderProofread',
icon: 'EditPen',
accent: '#ff7a45',
},
{
label: '汇总发药申请',
path: '/inHospital/statistics/drugDistribution',
icon: 'Collection',
accent: '#597ef7',
},
{
label: '住院记账',
path: '/inHospital/statistics/InpatientBilling',
icon: 'Tickets',
accent: '#9e60ff',
},
];

View File

@@ -15,19 +15,19 @@
</el-tabs>
</div>
</template>
<script setup>
import { getCurrentInstance, onBeforeMount, onMounted, reactive, ref } from 'vue';
<script setup >
import { getCurrentInstance, onBeforeMount, onMounted, reactive, ref } from 'vue'
import { WaitForDischarge, Discharged } from './components/index.ts';
import { WaitForDischarge, Discharged } from './components/index.ts'
// const { proxy } = getCurrentInstance()
// const emits = defineEmits([])
// const props = defineProps({})
const state = reactive({});
onBeforeMount(() => {});
onMounted(() => {});
defineExpose({ state });
const state = reactive({})
onBeforeMount(() => { })
onMounted(() => { })
defineExpose({ state })
const activeTabName = ref('first');
const activeTabName = ref('first')
</script>
<style lang="scss" scoped>
.inpatientNurseHome-inOut-container {

View File

@@ -0,0 +1,112 @@
<template>
<div class="patientList-container">
<div class="search-container">
<el-space :size="4">
<el-input v-model="searchForm.searchVal" style="width: 100px" placeholder="请输入" />
<el-button>查询</el-button>
</el-space>
</div>
<div class="patientList-table">
<el-table :data="patientListData" row-key="id" style="width: 100%; height: 100%" highlight-current-row
@selection-change="handleSelectionChange" :show-header="false" show-overflow-tooltip>
<el-table-column label="姓名" prop="name" min-width="100">
<template #default="{ row }">
<span class="name" v-if="row.children"> {{ row.department }}({{ row.children?.length || 0 }})</span>
<div class="patient-name" v-else>
<span class="name">{{ row.name }}</span>
</div>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const searchForm = ref({
searchVal: '',
})
const patientListData = ref([
{
id: 1,
department: '儿科',
children: [
{
id: 11,
name: '张三',
bedName: '1201',
gender: '男',
status: '在科',
attention: '医生A'
},
{
id: 12,
name: '张三-2',
age: 3,
gender: '女',
status: '在科',
attention: '医生A'
}
]
},
{
id: 2,
department: '神经内科科',
children: [
{
id: 21,
name: '张三',
bedName: '1201',
gender: '男',
status: '在科',
attention: '医生A'
},
{
id: 22,
name: '张三-2',
age: 3,
gender: '女',
status: '在科',
attention: '医生A'
}
]
}
])
const handleSelectionChange = (selection: any[]) => {
console.log('handleSelectionChange', selection)
}
</script>
<style lang="scss" scoped>
.patientList-container {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
overflow: hidden;
width: 240px;
border-right: 1px solid #e4e7ed;
.search-container {
flex: none;
padding: 0px 8px;
border-bottom: 1px solid #e4e7ed;
height: 40px;
display: flex;
align-items: center;
}
.patientList-table {
flex: 1;
:deep(.el-table__indent) {
display: none !important;
}
:deep(.el-table__placeholder) {
display: none !important;
}
}
}
</style>

View File

@@ -1,4 +1,4 @@
import request from '@/utils/request';
import request from '@/utils/request'
/**
* 获取初始化
@@ -7,8 +7,8 @@ export function getInit(queryParams) {
return request({
url: '/nurse-station/atd-manage/init',
method: 'get',
params: queryParams,
});
params: queryParams
})
}
/**
@@ -18,8 +18,8 @@ export function getPendingInfo(queryParams) {
return request({
url: '/nurse-station/atd-manage/admission-patient',
method: 'get',
params: queryParams,
});
params: queryParams
})
}
/**
@@ -29,8 +29,8 @@ export function getBedInfo(queryParams) {
return request({
url: '/nurse-station/atd-manage/admission-bed',
method: 'get',
params: queryParams,
});
params: queryParams
})
}
/**
@@ -40,8 +40,8 @@ export function getPatientInfo(queryParams) {
return request({
url: '/nurse-station/atd-manage/admission-patient-info',
method: 'get',
params: queryParams,
});
params: queryParams
})
}
/**
@@ -50,8 +50,8 @@ export function getPatientInfo(queryParams) {
export function getDoctorInfo(queryParams) {
return request({
url: '/charge-manage/register/practitioner-metadata?orgId=' + queryParams.organizationId,
method: 'get',
});
method: 'get'
})
}
/**
@@ -60,8 +60,8 @@ export function getDoctorInfo(queryParams) {
export function getNurseInfo(queryParams) {
return request({
url: '/app-common/nurse-list?orgId=' + queryParams.organizationId,
method: 'get',
});
method: 'get'
})
}
/**
@@ -71,8 +71,8 @@ export function bedAssignment(data) {
return request({
url: '/nurse-station/atd-manage/bed-assignment',
method: 'post',
data: data,
});
data: data
})
}
/**
@@ -82,66 +82,14 @@ export function childLocationList(queryParams) {
return request({
url: '/app-common/child-location-list',
method: 'get',
params: queryParams,
});
params: queryParams
})
}
export function getPractitionerWard(queryParams) {
return request({
url: '/app-common/practitioner-ward',
method: 'get',
params: queryParams,
});
}
export function getPrescriptionList(queryParams) {
return request({
url: '/nurse-station/atd-manage/patient-pending',
method: 'get',
params: queryParams,
});
}
//获取个人账户金额
export function getPersonAccount(queryParams) {
return request({
url: '/nurse-station/atd-manage/get-amount?encounterId=' + queryParams.encounterId,
method: 'get',
});
}
//待配药/待发药获取
export function getDRMedication(queryParams) {
return request({
url: '/nurse-station/atd-manage/get-dr-medication?encounterId=' + queryParams.encounterId,
method: 'get',
});
}
//转院
export function updateTransferDepartment(encounterId) {
return request({
url: '/nurse-station/atd-manage/transfer-department',
method: 'put',
params: {
encounterId: encounterId,
},
});
}
//出院
export function updateOutHospital(encounterId) {
return request({
url: '/nurse-station/atd-manage/hospital-discharge',
method: 'put',
params: {
encounterId: encounterId,
},
});
}
//清床
export function terminalCleaning(encounterId) {
return request({
url: '/nurse-station/atd-manage/terminal-cleaning',
method: 'put',
params: {
encounterId: encounterId,
},
});
params: queryParams
})
}

View File

@@ -7,7 +7,5 @@ import BedAllocation from './bedAllocation.vue'
import TransferInDialog from './transferInDialog.vue'
import SignEntryDialog from './signEntryDialog.vue'
import BedCards from './bedcards.vue'
import TransferOut from './transferOut.vue'
export { BedAllocation, TransferInDialog, SignEntryDialog, BedCards ,TransferOut }
export { BedAllocation, TransferInDialog, SignEntryDialog, BedCards }

View File

@@ -15,158 +15,93 @@
<el-row>
<el-col :span="24">
<div class="patient-info">
<div style="display: flex; align-items: center; margin-bottom: 16px">
<div style="margin-right: 36px; font-size: 18px; font-weight: 700">
{{ props.pendingInfo.houseName + '-' + props.pendingInfo.bedName }}
</div>
<div style="border-radius: 50px; border: 2px solid slategray; padding: 4px 12px">
{{ props.pendingInfo.contractName }}
</div>
<div style="display: flex;align-items: center;margin-bottom: 16px;">
<div style="margin-right: 36px;font-size: 18px;font-weight: 700;">{{ props.pendingInfo.houseName + '-' + props.pendingInfo.bedName }}</div>
<div style="border-radius: 50px;border: 2px solid slategray;padding: 4px 12px;">{{ props.pendingInfo.contractName }}</div>
</div>
<div>
<el-row>
<el-col :span="12">
<div style="margin-bottom: 12px">
{{ props.pendingInfo.patientName }}
<span style="color: #9f9f9f"
>{{ props.pendingInfo.genderEnum_enumText }}/</span
>
<span style="color: #9f9f9f">{{ props.pendingInfo.age }}</span>
<div style="margin-bottom: 12px;">
{{ props.pendingInfo.patientName}}
<span style="color: #9f9f9f;">{{ props.pendingInfo.genderEnum_enumText}}/</span>
<span style="color: #9f9f9f;">{{ props.pendingInfo.age}}</span>
</div>
</el-col>
<el-col :span="12">
<div>电话{{ pendingInfo.phone }}</div>
<div>
电话{{ pendingInfo.phone }}
</div>
</el-col>
<el-col :span="12">
<div>住院诊断{{ pendingInfo.conditionNames }}</div>
<div>
住院诊断{{ pendingInfo.conditionNames }}
</div>
</el-col>
<el-col :span="12">{{ props.pendingInfo.patientId }}</el-col>
</el-row>
</div>
</div>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<div class="info-title">入院体征</div>
<div class="info-title">
入院体征
</div>
</el-col>
<el-col :span="8">
<el-form-item label="身高" label-width="50px">
<!-- <el-input-number
:controls="false"
style="width: 160px"
clearable
v-model="interventionForm.height"
placeholder="请输入"
:min="0"
:max="999"
></el-input-number
><span class="unit">cm</span> -->
<el-input
class="right-aligned"
style="width: 160px"
clearable
v-model="interventionForm.height"
placeholder="请输入"
:min="0"
:max="999"
></el-input>
<span class="unit">cm</span>
<el-input-number :controls="false" style="width: 160px" clearable v-model="interventionForm.height" placeholder="请输入" :min="0"
:max="999"></el-input-number><span class="unit">cm</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="体重" label-width="50px">
<!-- <el-input-number
:controls="false"
style="width: 160px"
v-model="interventionForm.weight"
clearable
placeholder="请输入"
:min="0"
:max="999"
></el-input-number>
<span class="unit">kg</span> -->
<el-input
class="right-aligned"
style="width: 160px"
v-model="interventionForm.weight"
clearable
placeholder="请输入"
></el-input>
<el-input-number :controls="false" style="width: 160px" v-model="interventionForm.weight" clearable placeholder="请输入" :min="0"
:max="999"></el-input-number>
<span class="unit">kg</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="体温" label-width="50px">
<el-input-number
:controls="false"
style="width: 160px"
v-model="interventionForm.temperature"
clearable
placeholder="请输入"
:min="0"
:max="99"
></el-input-number>
<el-input-number :controls="false" style="width: 160px" v-model="interventionForm.temperature" clearable placeholder="请输入"
:min="0" :max="99"></el-input-number>
<span class="unit"></span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="心率" label-width="50px">
<el-input-number
:controls="false"
style="width: 160px"
v-model="interventionForm.hertRate"
clearable
placeholder="请输入"
:min="0"
:max="999"
></el-input-number>
<el-input-number :controls="false" style="width: 160px" v-model="interventionForm.hertRate" clearable placeholder="请输入" :min="0"
:max="999"></el-input-number>
<span class="unit">BPM</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="脉搏" label-width="50px">
<el-input-number
:controls="false"
style="width: 160px"
v-model="interventionForm.pulse"
clearable
placeholder="请输入"
:min="0"
:max="999"
></el-input-number
><span class="unit">P</span>
<el-input-number :controls="false" style="width: 160px" v-model="interventionForm.pulse" clearable placeholder="请输入" :min="0"
:max="999"></el-input-number><span class="unit">P</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="血压" label-width="50px">
<el-input-number
:controls="false"
style="width: 72px"
v-model="interventionForm.endBloodPressure"
clearable
placeholder="请输入"
:min="0"
:max="999"
></el-input-number>
<el-input-number :controls="false" style="width: 72px" v-model="interventionForm.endBloodPressure" clearable placeholder="请输入"
:min="0" :max="999"></el-input-number>
<span style="display: inline-block; width: 8px; margin: 0 4px"> ~ </span>
<el-input-number
:controls="false"
style="width: 72px"
v-model="interventionForm.highBloodPressure"
clearable
placeholder="请输入"
:min="0"
:max="999"
></el-input-number>
<el-input-number :controls="false" style="width: 72px" v-model="interventionForm.highBloodPressure" clearable placeholder="请输入"
:min="0" :max="999"></el-input-number>
<span class="unit">mmHg</span>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<div class="info-title">入院信息</div>
<div class="info-title">
入院信息
</div>
</el-col>
<el-col :span="8">
<el-form-item label="入院科室" label-width="100px">
@@ -215,9 +150,7 @@
v-model="interventionForm.admittingDoctorId"
placeholder="请选择住院医生"
style="width: 240px"
:disabled="
props.pendingInfo.encounterStatus == 5 && props.pendingInfo.entranceType == 2
"
:disabled="props.pendingInfo.encounterStatus == 5 && props.pendingInfo.entranceType == 2"
>
<el-option
v-for="item in doctorInfoOptions"
@@ -234,9 +167,7 @@
v-model="interventionForm.attendingDoctorId"
placeholder="请选择主治医生"
style="width: 240px"
:disabled="
props.pendingInfo.encounterStatus == 5 && props.pendingInfo.entranceType == 2
"
:disabled="props.pendingInfo.encounterStatus == 5 && props.pendingInfo.entranceType == 2"
>
<el-option
v-for="item in doctorInfoOptions"
@@ -253,9 +184,7 @@
v-model="interventionForm.chiefDoctorId"
placeholder="请选择主任医生"
style="width: 240px"
:disabled="
props.pendingInfo.encounterStatus == 5 && props.pendingInfo.entranceType == 2
"
:disabled="props.pendingInfo.encounterStatus == 5 && props.pendingInfo.entranceType == 2"
>
<el-option
v-for="item in doctorInfoOptions"
@@ -284,9 +213,7 @@
v-model="interventionForm.primaryNurseId"
placeholder="请选择责任护士"
style="width: 240px"
:disabled="
props.pendingInfo.encounterStatus == 5 && props.pendingInfo.entranceType == 2
"
:disabled="props.pendingInfo.encounterStatus == 5 && props.pendingInfo.entranceType == 2"
>
<el-option
v-for="item in nurseInfoOptions"
@@ -303,9 +230,7 @@
v-model="interventionForm.priorityEnum"
placeholder="请选择患者病情"
style="width: 240px"
:disabled="
props.pendingInfo.encounterStatus == 5 && props.pendingInfo.entranceType == 2
"
:disabled="props.pendingInfo.encounterStatus == 5 && props.pendingInfo.entranceType == 2"
>
<el-option
v-for="item in props.priorityOptions"
@@ -332,57 +257,50 @@
</el-dialog>
</template>
<script lang="ts" setup>
import { reactive, ref, onMounted, inject, type Ref, watch, nextTick } from 'vue';
import type { FormInstance, FormRules } from 'element-plus';
import { dayjs, ElMessage } from 'element-plus';
import { reactive, ref, onMounted, inject, type Ref, watch } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'
import { dayjs, ElMessage } from 'element-plus'
// import type { IInPatient } from '@/model/IInPatient'
import {
getBedInfo,
getDoctorInfo,
getNurseInfo,
getInit,
bedAssignment,
getPatientInfo,
} from './api';
import { getBedInfo, getDoctorInfo, getNurseInfo, getInit, bedAssignment, getPatientInfo } from './api'
const props = defineProps({
pendingInfo: {
type: Object,
require: true,
default: () => ({}),
default: () => ({})
},
priorityOptions: {
type: Object,
require: true,
default: () => ({}),
default: () => ({})
},
});
})
const currentInPatient = ref<Partial<IInPatient>>({});
const bedInfoOptions = ref<{ label: string; value: string }[]>([]);
const doctorInfoOptions = ref<{ name: string; id: string }[]>([]);
const nurseInfoOptions = ref<{ name: string; practitionerId: string }[]>([]);
const InitInfoOptions = ref<any>({});
const priorityListOptions = ref<{ info: string; value: string }[]>([]);
const pendingInfo = ref<any>({});
const currentInPatient = ref<Partial<IInPatient>>({})
const bedInfoOptions = ref<{ label: string; value: string }[]>([])
const doctorInfoOptions = ref<{ name: string; id: string }[]>([])
const nurseInfoOptions = ref<{ name: string; practitionerId: string }[]>([])
const InitInfoOptions = ref<any>({})
const priorityListOptions = ref<{ info: string; value: string }[]>([])
const pendingInfo = ref<any>({})
const initCurrentInPatient = () => {
currentInPatient.value = {
feeType: '08',
sexName: '男',
age: '0',
};
};
}
}
/* 入科 */
const interventionForm = ref({
height: '',
weight: '',
temperature: '',
hertRate: '',
pulse: '',
endBloodPressure: '',
highBloodPressure: '',
height: undefined,
weight: undefined,
temperature: undefined,
hertRate: undefined,
pulse: undefined,
endBloodPressure: undefined,
highBloodPressure: undefined,
bedLocationId: '', // 床号
admittingDoctorId: '', // 住院医师
attendingDoctorId: '', // 主治医师
@@ -394,129 +312,85 @@ const interventionForm = ref({
bedName: '',
attendingDocUpdateId: '',
startTime: '', //入院时间
});
})
watch(
() => props.pendingInfo,
(newVal, oldVal) => {
console.log(newVal);
if (newVal) {
getPatientInfo({ encounterId: newVal.encounterId }).then((res) => {
console.log('res============>', JSON.stringify(res.data));
pendingInfo.value = res.data;
interventionForm.value.admittingDoctorId = res.data.admittingDoctorId;
interventionForm.value.attendingDoctorId = res.data.attendingDoctorId;
if (res.data.chiefDoctorId) {
interventionForm.value.chiefDoctorId = res.data.chiefDoctorId;
}
interventionForm.value.primaryNurseId = res.data.primaryNurseId;
if (res.data.startTime) {
interventionForm.value.startTime = dayjs(res.data.startTime).format(
'YYYY-MM-DD HH:mm:ss'
);
} else {
interventionForm.value.startTime = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss');
}
interventionForm.value.height = res.data.height;
interventionForm.value.weight = res.data.weight;
interventionForm.value.temperature = res.data.temperature;
interventionForm.value.hertRate = res.data.hertRate;
interventionForm.value.pulse = res.data.pulse;
interventionForm.value.endBloodPressure = res.data.endBloodPressure;
interventionForm.value.highBloodPressure = res.data.highBloodPressure;
});
interventionForm.value.priorityEnum = newVal.priorityEnum;
interventionForm.value.organizationName = newVal.organizationName;
interventionForm.value.wardName = newVal.wardName;
interventionForm.value.bedName = newVal.bedName;
}
},
{ deep: true }
);
watch(() => props.pendingInfo, (newVal, oldVal) => {
console.log(newVal)
if(newVal) {
getPatientInfo({encounterId: newVal.encounterId}).then(res => {
pendingInfo.value = res.data
interventionForm.value.admittingDoctorId = res.data.admittingDoctorId
interventionForm.value.attendingDoctorId = res.data.attendingDoctorId
interventionForm.value.chiefDoctorId = res.data.chiefDoctorId
interventionForm.value.primaryNurseId = res.data.primaryNurseId
if(res.data.startTime) {
interventionForm.value.startTime = dayjs(res.data.startTime).format('YYYY-MM-DD HH:mm:ss')
}else {
interventionForm.value.startTime = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss')
}
})
interventionForm.value.priorityEnum = newVal.priorityEnum
interventionForm.value.organizationName = newVal.organizationName
interventionForm.value.wardName = newVal.wardName
interventionForm.value.bedName = newVal.bedName
}
},{ deep: true })
/* 初始化数据 */
const init = () => {
initCurrentInPatient();
getInit()
.then((res) => {
InitInfoOptions.value = res.data;
// 安全地设置priorityListOptions
if (res.data && res.data.priorityListOptions) {
priorityListOptions.value = res.data.priorityListOptions;
}
})
.catch((error) => {
console.error('获取初始化数据失败:', error);
});
initCurrentInPatient()
getInit().then(res => {
InitInfoOptions.value = res.data
// 安全地设置priorityListOptions
if (res.data && res.data.priorityListOptions) {
priorityListOptions.value = res.data.priorityListOptions
}
}).catch(error => {
console.error('获取初始化数据失败:', error)
})
if (props.pendingInfo.wardLocationId) {
getBedInfo({ wardLocationId: props.pendingInfo.wardLocationId })
.then((res) => {
bedInfoOptions.value = res.data || [];
})
.catch((error) => {
console.error('获取床位信息失败:', error);
bedInfoOptions.value = [];
});
getBedInfo({wardLocationId: props.pendingInfo.wardLocationId}).then(res => {
bedInfoOptions.value = res.data || []
}).catch(error => {
console.error('获取床位信息失败:', error)
bedInfoOptions.value = []
})
}
if (props.pendingInfo.organizationId) {
// 主任医生
getDoctorInfo({ organizationId: props.pendingInfo.organizationId })
.then((res) => {
console.log('doctorInfoOptions======>', JSON.stringify(res.data));
doctorInfoOptions.value = res.data.records || [];
nextTick(() => {
// 如果存在主任医师显示主任,如果没有选择第一个展示
if (doctorInfoOptions.value.length > 0) {
let selectId = '';
doctorInfoOptions.value.forEach((item: any) => {
if (item.drProfttlCode == '231') {
selectId = item.id;
}
});
if (selectId.length > 0) {
interventionForm.value.chiefDoctorId = selectId;
} else {
interventionForm.value.chiefDoctorId = doctorInfoOptions.value[0].id;
}
}
});
})
.catch((error) => {
console.error('获取医生信息失败:', error);
doctorInfoOptions.value = [];
});
getNurseInfo({ organizationId: props.pendingInfo.organizationId })
.then((res) => {
nurseInfoOptions.value = res.data || [];
})
.catch((error) => {
console.error('获取护士信息失败:', error);
nurseInfoOptions.value = [];
});
getDoctorInfo({organizationId: props.pendingInfo.organizationId}).then(res => {
doctorInfoOptions.value = res.data.records || []
}).catch(error => {
console.error('获取医生信息失败:', error)
doctorInfoOptions.value = []
})
getNurseInfo({organizationId: props.pendingInfo.organizationId}).then(res => {
nurseInfoOptions.value = res.data || []
}).catch(error => {
console.error('获取护士信息失败:', error)
nurseInfoOptions.value = []
})
}
};
}
const rules = reactive<FormRules>({
admittingDoctorId: [{ required: true, message: '请选择住院医生', trigger: ['blur', 'change'] }],
primaryNurseId: [{ required: true, message: '请选择责任护士', trigger: ['blur', 'change'] }],
bedLocationId: [{ required: true, message: '请选择入住床位', trigger: ['blur', 'change'] }],
});
})
const printWristband = ref(false);
const emits = defineEmits(['okAct']);
const visible = defineModel('visible');
const width = '950px';
const printWristband = ref(false)
const emits = defineEmits(['okAct'])
const visible = defineModel('visible')
const width = '950px'
/* 取消 */
const cancelAct = () => {
resetForm();
visible.value = false;
};
resetForm()
visible.value = false
}
const resetForm = () => {
// interventionForm.value = {
@@ -541,76 +415,74 @@ const resetForm = () => {
// 可选:清空校验状态
if (interventionFormRef.value) {
interventionFormRef.value.resetFields();
interventionFormRef.value.resetFields()
}
};
}
/* 入科 */
const interventionFormRef = ref<FormInstance | null>(null);
const interventionFormRef = ref<FormInstance | null>(null)
const handleSubmit = async () => {
// TODO 登记入科
if (!interventionFormRef.value) {
console.error('表单引用不存在');
return;
console.error('表单引用不存在')
return
}
try {
const valid = await interventionFormRef.value.validate();
const valid = await interventionFormRef.value.validate()
if (valid) {
const params = {
const params = {
...pendingInfo.value,
...interventionForm.value,
targetBedId: props.pendingInfo.bedId,
busNo: props.pendingInfo.busNo,
inHosTime: props.pendingInfo.inHosTime,
targetHouseId: props.pendingInfo.targetHouseId,
targetHouseId : props.pendingInfo.targetHouseId,
targetEncounterId: props.pendingInfo.targetEncounterId,
editFlag: props.pendingInfo.entranceType == 1 ? 1 : 0,
};
bedAssignment(params)
.then((res: any) => {
ElMessage({
message: '登记成功!',
type: 'success',
grouping: true,
showClose: true,
});
resetForm();
emits('okAct');
visible.value = false; // 关闭对话框
editFlag: props.pendingInfo.entranceType == 1 ? 1 : 0
}
bedAssignment(params).then((res: any) => {
ElMessage({
message: '登记成功!',
type: 'success',
grouping: true,
showClose: true,
})
.catch((error: any) => {
console.error('登记失败:', error);
ElMessage({
message: '登记失败!',
type: 'error',
grouping: true,
showClose: true,
});
});
resetForm()
emits('okAct')
visible.value = false // 关闭对话框
}).catch((error: any) => {
console.error('登记失败:', error)
ElMessage({
message: '登记失败!',
type: 'error',
grouping: true,
showClose: true,
})
})
}
} catch (error) {
console.log('表单验证失败:', error);
console.log('表单验证失败:', error)
}
};
}
const openAct = () => {
init();
init()
if (props.pendingInfo) {
interventionForm.value.priorityEnum = props.pendingInfo.priorityEnum || '';
interventionForm.value.admittingDoctorId = props.pendingInfo.practitionerId || '';
interventionForm.value.organizationName = props.pendingInfo.organizationName || '';
interventionForm.value.wardName = props.pendingInfo.wardName || '';
interventionForm.value.attendingDocUpdateId = props.pendingInfo.admittingDoctorId || '';
interventionForm.value.priorityEnum = props.pendingInfo.priorityEnum || ''
interventionForm.value.admittingDoctorId = props.pendingInfo.practitionerId || ''
interventionForm.value.organizationName = props.pendingInfo.organizationName || ''
interventionForm.value.wardName = props.pendingInfo.wardName || ''
interventionForm.value.attendingDocUpdateId = props.pendingInfo.admittingDoctorId || ''
}
};
}
const closedAct = () => {
resetForm();
visible.value = false;
};
resetForm()
visible.value = false
}
onMounted(() => {});
onMounted(() => {})
</script>
<style lang="scss" scoped>
.transferIn-container {
@@ -659,10 +531,4 @@ onMounted(() => {});
padding: 5px 10px;
margin-bottom: 16px;
}
.right-aligned {
:deep(.el-input__inner) {
text-align: center;
}
}
</style>
</style>

View File

@@ -5,69 +5,43 @@
-->
<template>
<div class="inpatientNurseHome-inOut-container">
<el-tabs v-model="activeTabName" class="inOut-tabs" @tab-click="test">
<el-tabs v-model="activeTabName" type="card" class="inOut-tabs">
<el-tab-pane label="入科" name="first">
<BedAllocation v-if="activeTabName === 'first'" ref="firstRef" />
<BedAllocation />
</el-tab-pane>
<el-tab-pane label="转出" name="second">
<TransferOut
v-if="activeTabName === 'second'"
ref="secondRef"
operation-type="transfer"
:visible="activeTabName === 'second'"
/>
</el-tab-pane>
<el-tab-pane label="出院" name="third">
<TransferOut
v-if="activeTabName === 'third'"
ref="thirdRef"
operation-type="discharge"
:visible="activeTabName === 'third'"
/>
</el-tab-pane>
<!-- <el-tab-pane label="出院患者" name="fourth">Config</el-tab-pane> -->
<el-tab-pane label="转出" name="second">Config</el-tab-pane>
<el-tab-pane label="出院" name="second">Config</el-tab-pane>
<el-tab-pane label="出院患者" name="second">Config</el-tab-pane>
</el-tabs>
</div>
</template>
<script setup lang="ts">
import { getCurrentInstance, nextTick, onBeforeMount, onMounted, reactive, ref } from 'vue';
import { getCurrentInstance, onBeforeMount, onMounted, reactive, ref } from 'vue'
import { BedAllocation, TransferInDialog, SignEntryDialog, TransferOut } from './components/index';
import { BedAllocation, TransferInDialog, SignEntryDialog } from './components/index'
// const { proxy } = getCurrentInstance()
// const emits = defineEmits([])
// const props = defineProps({})
const state = reactive({});
const firstRef = ref();
const secondRef = ref();
const thirdRef = ref();
onBeforeMount(() => {});
onMounted(() => {});
defineExpose({ state });
const test = () => {
nextTick(() => {
if (activeTabName.value == 'first') {
firstRef?.value?.refreshTap();
} else if (activeTabName.value == 'second') {
secondRef?.value?.refreshTap();
} else if (activeTabName.value == 'third') {
thirdRef?.value?.refreshTap();
}
});
};
const state = reactive({})
onBeforeMount(() => {})
onMounted(() => {
})
defineExpose({ state })
const activeTabName = ref('first');
const activeTabName = ref('first')
</script>
<style lang="scss" scoped>
.inpatientNurseHome-inOut-container {
width: 100%;
height: 100%;
display: flex;
padding: 0 8px 8px;
:deep(.inOut-tabs) {
height: 100%;
width: 100%;
.el-tabs__header {
margin: 0;
padding: 0 0 0 8px;
}
.el-tab-pane {
height: 100%;

View File

@@ -1,39 +0,0 @@
// 入出转管理
import inOut from '../inOut/index.vue';
// 护理记录
import NursingRecord from '@/views/inpatientNurse/nursingRecord/index.vue';
// 三测单
// import TprChart from '@/views/inpatientNurse/tprChart/index.vue';
import TprChart from '@/views/inpatientNurse/tprsheet/index.vue';
// 科室耗材盘点
import ChkstockPartDeptDevice from '@/views/medicationmanagement/chkstock/chkstockPartDeptDevice/index.vue';
// 医嘱执行
import MedicalOrderExecution from '@/views/inpatientNurse/medicalOrderExecution/index.vue';
// 医嘱校对
import MedicalOrderProofread from '@/views/inpatientNurse/medicalOrderProofread/index.vue';
// 汇总领药
import DrugDistribution from '@/views/inpatientNurse/drugDistribution/index.vue';
// 住院记账
import InpatientBilling from '@/views/inpatientNurse/InpatientBilling/index.vue';
// 出院管理
import DischargedManagement from '@/views/inpatientNurse/dischargedManagement/index.vue';
// 住院病历
import InpatientRecord from '@/views/inpatientDoctor/home/emr/index.vue';
// 滚费配置
import RollFee from '@/views/inpatientNurse/rollFee/index.vue';
// 危重记录
import Criticalrecord from '@/views/inpatientNurse/nursingstatistics/criticalrecord.vue';
export {
inOut,
ChkstockPartDeptDevice,
NursingRecord,
TprChart,
MedicalOrderExecution,
MedicalOrderProofread,
DrugDistribution,
InpatientBilling,
DischargedManagement,
InpatientRecord,
RollFee,
Criticalrecord,
};

View File

@@ -1,135 +0,0 @@
<template>
<div class="inpatientNurse-home-container">
<el-container>
<!-- main -->
<el-container class="inpatientNurse-home-main">
<el-main>
<el-tabs v-model="activeTabName" type="card" class="patient-tabs">
<el-tab-pane label="入出转管理" name="InOut">
<inOut v-if="activeTabName === 'InOut'"></inOut>
</el-tab-pane>
<el-tab-pane label="住院病历" name="InpatientRecord">
<el-container v-if="activeTabName === 'InpatientRecord'">
<PatientList :selected-patient="patientInfo" :on-select="handlePatientSelect" />
<el-container>
<el-header>
<inPatientBarDoctorFold></inPatientBarDoctorFold>
</el-header>
<el-main>
<InpatientRecord :key="recordKey"></InpatientRecord>
</el-main>
</el-container>
</el-container>
</el-tab-pane>
<el-tab-pane label="医嘱校对" name="MedicalOrderProofread">
<MedicalOrderProofread
v-if="activeTabName === 'MedicalOrderProofread'"
></MedicalOrderProofread>
</el-tab-pane>
<el-tab-pane label="医嘱执行" name="MedicalOrderExecution">
<MedicalOrderExecution
v-if="activeTabName === 'MedicalOrderExecution'"
></MedicalOrderExecution>
</el-tab-pane>
<el-tab-pane label="护理记录" name="NursingRecord">
<Criticalrecord v-if="activeTabName === 'NursingRecord'"></Criticalrecord>
</el-tab-pane>
<el-tab-pane label="体温单" name="TprSheet">
<TprChart
v-if="activeTabName === 'TprSheet'"
:selected-patient="patientInfo"
:on-select="handlePatientSelect"
/>
</el-tab-pane>
<el-tab-pane label="住院记账" name="InpatientBilling">
<InpatientBilling v-if="activeTabName === 'InpatientBilling'" />
</el-tab-pane>
<el-tab-pane label="汇总领药" name="DrugDistribution">
<DrugDistribution v-if="activeTabName === 'DrugDistribution'"></DrugDistribution>
</el-tab-pane>
<el-tab-pane label="科室耗材盘点" name="ChkstockPartDeptDevice">
<ChkstockPartDeptDevice
v-if="activeTabName === 'ChkstockPartDeptDevice'"
></ChkstockPartDeptDevice>
</el-tab-pane>
<el-tab-pane label="滚费配置" name="RollFee">
<RollFee v-if="activeTabName === 'RollFee'"></RollFee>
</el-tab-pane>
<!-- <el-tab-pane label="皮试管理" name="I"> 皮试管理 </el-tab-pane>
<el-tab-pane label="出院管理" name="J">
<DischargedManagement></DischargedManagement>
</el-tab-pane>
<el-tab-pane label="退药管理" name="K"> 退药管理 </el-tab-pane>
<el-tab-pane label="手术记录" name="L"> 手术记录 </el-tab-pane> -->
</el-tabs>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script setup>
import { computed, ref, watch } from 'vue';
import inPatientBarDoctorFold from '@/components/patientBar/inPatientBarDoctorFold.vue';
import PatientList from '@/components/PatientList/patient-list.vue';
import { patientInfo, updatePatientInfo } from '@/views/inpatientDoctor/home/store/patient.js';
import {
inOut,
ChkstockPartDeptDevice,
NursingRecord,
TprChart,
MedicalOrderExecution,
MedicalOrderProofread,
DrugDistribution,
InpatientBilling,
DischargedManagement,
InpatientRecord,
RollFee,
Criticalrecord,
} from './index.js';
const activeTabName = ref('InOut');
const recordKey = computed(
() => patientInfo.value?.encounterId || patientInfo.value?.id || 'empty'
);
const handlePatientSelect = (patient) => {
updatePatientInfo(patient);
};
</script>
<style lang="scss" scoped>
.inpatientNurse-home-container {
height: 100%;
height: calc(100vh - 84px);
.el-container {
height: 100%;
}
:deep(.el-aside) {
padding: 0;
}
.inpatientNurse-home-main {
background-color: #ffffff;
:deep(.el-header) {
padding: 0px;
margin-bottom: 0px;
}
.el-main {
padding: 0px 8px;
}
:deep(.patient-tabs) {
height: 100%;
.el-tabs__header {
margin: 0;
}
.el-tabs__content {
height: calc(100% - 40px);
}
.el-tab-pane {
height: 100%;
}
}
}
}
</style>

View File

@@ -0,0 +1,148 @@
<template>
<div>
<div>
<el-input placeholder="住院号/姓名">
<template #append>
<el-button icon="Search" @click="getPatientList" />
</template>
</el-input>
</div>
<el-tree
ref="treeRef"
:load="loadNode"
lazy
show-checkbox
node-key="id"
default-expand-all
:props="{ label: 'name', children: 'children' }"
@node-click="handleNodeClick"
@check="handleCheckChange"
@node-expand="onNodeExpand"
>
<template #default="{ node, data }">
<div class="custom-tree-node" v-if="node.level === 2">
<span>{{ data.bedName + ' / ' + node.label }}</span>
<span class="tree-node-actions">
{{ data.genderEnum_enumText + ' / ' + data.age }}
</span>
</div>
</template>
</el-tree>
</div>
</template>
<script setup>
import { getPatientList, getWardList } from './api';
import { updatePatientInfoList } from '../store/patient';
import { nextTick, onMounted } from 'vue';
const treeRef = ref(null);
const allNodesLoaded = ref(false);
// 树节点加载完成后的回调
function onTreeLoaded() {
if (!allNodesLoaded.value && treeRef.value) {
// 等待DOM更新后设置全选
nextTick(() => {
// 获取所有节点并设置为选中状态
const allNodes = getAllNodes(treeRef.value.store.root.childNodes);
const allKeys = allNodes.map((node) => node.key);
treeRef.value.setCheckedKeys(allKeys, true); // 第二个参数设为true表示级联选中
allNodesLoaded.value = true;
});
}
}
// 递归获取所有节点
function getAllNodes(nodes) {
let result = [];
if (nodes && nodes.length > 0) {
nodes.forEach((node) => {
result.push(node);
if (node.childNodes && node.childNodes.length > 0) {
result = result.concat(getAllNodes(node.childNodes));
}
});
}
return result;
}
function loadNode(node, resolve) {
// 初始加载:获取所有病区(父级节点)
if (node.level === 0) {
getWardList().then((res) => {
// 确保病区节点不是叶子节点
const wards = res.map((ward) => ({
...ward,
leaf: false,
}));
return resolve(wards);
});
}
// 展开病区节点时:获取该病区下的患者列表
else if (node.level === 1) {
const wardId = node.data.id;
getPatientList({ wardId: wardId }).then((res) => {
let children = res.data.records.map((item) => {
return {
leaf: true, // 患者节点为叶子节点
...item,
name: item.patientName,
};
});
return resolve(children);
});
}
// 更深层级直接返回空数组
else {
return resolve([]);
}
}
// 获取所有选中的子节点(叶子节点)
function getCheckedLeafNodes() {
if (!treeRef.value) return [];
// 获取所有选中的节点key
const checkedKeys = treeRef.value.getCheckedKeys();
// 获取所有半选中的节点key父节点
const halfCheckedKeys = treeRef.value.getHalfCheckedKeys();
// 获取所有选中的节点数据
const checkedNodes = treeRef.value.getCheckedNodes();
// 只返回叶子节点(患者节点)
return checkedNodes.filter((node) => node.leaf === true);
}
// 处理节点选中状态变化
function handleCheckChange(data, checked) {
// 可以在这里处理选中状态变化的逻辑
let list = getCheckedLeafNodes();
console.log(list, '2345678');
updatePatientInfoList(list);
handleGetPrescription()
}
const handleGetPrescription = inject('handleGetPrescription')
</script>
<style scoped lang="scss">
.custom-tree-node {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
}
.tree-node-actions {
display: flex;
align-items: center;
}
:deep(.el-tree-node__content) {
height: 35px;
}
</style>

View File

@@ -22,11 +22,9 @@
<el-tab-pane label="在科" name="first" style="padding: 15px 10px">
<PatientList />
</el-tab-pane>
<!-- 隐藏转科tab
<el-tab-pane label="转科" name="second" style="padding: 0 10px">
<PatientList />
</el-tab-pane>
-->
</el-tabs>
</div>
<div style="width: 100%">
@@ -52,7 +50,7 @@
<script setup>
import { getCurrentInstance } from 'vue';
import PatientList from '../components/patientList.vue';
import PatientList from './components/patientList.vue';
import PrescriptionList from './components/prescriptionList.vue';
const activeName = ref('preparation');

View File

@@ -0,0 +1,146 @@
<template>
<div>
<div>
<el-input placeholder="住院号/姓名">
<template #append>
<el-button icon="Search" @click="getPatientList" />
</template>
</el-input>
</div>
<el-tree
ref="treeRef"
:load="loadNode"
lazy
show-checkbox
node-key="id"
default-expand-all
:props="{ label: 'name', children: 'children' }"
@node-click="handleNodeClick"
@check="handleCheckChange"
@node-expand="onNodeExpand"
>
<template #default="{ node, data }">
<div class="custom-tree-node" v-if="node.level === 2">
<span>{{ data.bedName + ' / ' + node.label }}</span>
<span class="tree-node-actions">
{{ data.genderEnum_enumText + ' / ' + data.age }}
</span>
</div>
</template>
</el-tree>
</div>
</template>
<script setup>
import { getPatientList, getWardList } from './api';
import { updatePatientInfoList } from '../store/patient';
import { nextTick, onMounted } from 'vue';
const treeRef = ref(null);
const allNodesLoaded = ref(false);
// 树节点加载完成后的回调
function onTreeLoaded() {
if (!allNodesLoaded.value && treeRef.value) {
// 等待DOM更新后设置全选
nextTick(() => {
// 获取所有节点并设置为选中状态
const allNodes = getAllNodes(treeRef.value.store.root.childNodes);
const allKeys = allNodes.map((node) => node.key);
treeRef.value.setCheckedKeys(allKeys, true); // 第二个参数设为true表示级联选中
allNodesLoaded.value = true;
});
}
}
// 递归获取所有节点
function getAllNodes(nodes) {
let result = [];
if (nodes && nodes.length > 0) {
nodes.forEach((node) => {
result.push(node);
if (node.childNodes && node.childNodes.length > 0) {
result = result.concat(getAllNodes(node.childNodes));
}
});
}
return result;
}
function loadNode(node, resolve) {
// 初始加载:获取所有病区(父级节点)
if (node.level === 0) {
getWardList().then((res) => {
// 确保病区节点不是叶子节点
const wards = res.map((ward) => ({
...ward,
leaf: false,
}));
return resolve(wards);
});
}
// 展开病区节点时:获取该病区下的患者列表
else if (node.level === 1) {
const wardId = node.data.id;
getPatientList({ wardId: wardId }).then((res) => {
let children = res.data.records.map((item) => {
return {
leaf: true, // 患者节点为叶子节点
...item,
name: item.patientName,
};
});
return resolve(children);
});
}
// 更深层级直接返回空数组
else {
return resolve([]);
}
}
// 获取所有选中的子节点(叶子节点)
function getCheckedLeafNodes() {
if (!treeRef.value) return [];
// 获取所有选中的节点key
const checkedKeys = treeRef.value.getCheckedKeys();
// 获取所有半选中的节点key父节点
const halfCheckedKeys = treeRef.value.getHalfCheckedKeys();
// 获取所有选中的节点数据
const checkedNodes = treeRef.value.getCheckedNodes();
// 只返回叶子节点(患者节点)
return checkedNodes.filter((node) => node.leaf === true);
}
// 处理节点选中状态变化
function handleCheckChange(data, checked) {
// 可以在这里处理选中状态变化的逻辑
let list = getCheckedLeafNodes();
console.log(list, '2345678');
updatePatientInfoList(list);
handleGetPrescription();
}
const handleGetPrescription = inject('handleGetPrescription');
</script>
<style scoped lang="scss">
.custom-tree-node {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
}
.tree-node-actions {
display: flex;
align-items: center;
}
:deep(.el-tree-node__content) {
height: 35px;
}
</style>

View File

@@ -21,7 +21,7 @@
</div>
<div>
<span class="descriptions-item-label">全选</span>
<el-switch v-model="chooseAll" @change="handelSwitchChange" />
<el-switch v-model="chooseAll" @change="handelSwicthChange" />
<el-button class="ml20" type="primary" @click="handleCheck"> 核对通过 </el-button>
<el-button class="ml20 mr20" type="danger" @click="handleCancel"> 退回 </el-button>
</div>
@@ -107,10 +107,8 @@
border
:ref="'tableRef' + index"
:header-cell-style="{ background: '#eef9fd !important' }"
@select="handleSelectionChange"
>
<el-table-column type="selection" align="center" width="50" />
<el-table-column label="组" align="center" width="60" prop="groupIcon" />
<el-table-column label="类型" align="center" prop="therapyEnum_enumText" width="80">
<template #default="scope">
<span :style="scope.row.therapyEnum == '1' ? 'color: #a6745c' : 'color: #3787a5'">
@@ -153,7 +151,7 @@
</template>
<script setup>
import { getPrescriptionList, adviceVerify, cancel } from './api';
import { patientInfoList } from '../../components/store/patient.js';
import { patientInfoList } from '../store/patient.js';
import { formatDateStr } from '@/utils/index';
const activeNames = ref([]);
@@ -201,9 +199,7 @@ function handleGetPrescription() {
// 将分组结果转换为数组形式
prescriptionList.value = Object.values(groupedPrescriptions);
console.log(prescriptionList.value, '1111');
console.log('@@@@@=======>', JSON.stringify(prescriptionList.value));
loading.value = false;
getGroupMarkers();
});
chooseAll.value = false;
} else {
@@ -211,58 +207,6 @@ function handleGetPrescription() {
}
}
// 分组标记处理
function getGroupMarkers() {
// 初始化所有行的 groupIcon 为 null
prescriptionList.value.forEach((item) => {
item.forEach((prescription) => {
prescription.groupIcon = null;
});
});
console.log('prescriptionList====>', JSON.stringify(prescriptionList.value));
// 创建一个映射来存储每个 groupId 对应的行索引
const groupMap = {};
// 遍历处方列表,按 groupId 分组(忽略无 groupId 的项)
prescriptionList.value.forEach((item, index) => {
item.forEach((prescription, idnexNum) => {
if (prescription.groupId) {
if (!groupMap[prescription.groupId]) {
groupMap[prescription.groupId] = [];
}
groupMap[prescription.groupId].push(idnexNum);
}
});
});
// 为每个组设置 groupIcon
Object.values(groupMap).forEach((indices) => {
// 只有当组内元素大于1个时才需要显示分组标记
if (indices.length > 1) {
let iconArrayIndex = 0;
indices.forEach((index, i) => {
prescriptionList.value.forEach((itemArray, index1) => {
itemArray.forEach((item, index2) => {
if (index2 === index) {
iconArrayIndex++;
if (iconArrayIndex == 1) {
item.groupIcon = '┏';
} else if (iconArrayIndex == indices.length) {
item.groupIcon = '┗';
} else {
item.groupIcon = '┃';
}
}
});
});
});
}
});
console.log('prescriptionList====>', JSON.stringify(prescriptionList.value));
}
// 选择框改变时的处理
function handleSelectionChange(selection, row) {}
/**
* 核对通过
*/
@@ -313,7 +257,7 @@ function getSelectRows() {
});
}
function handelSwitchChange(value) {
function handelSwicthChange(value) {
prescriptionList.value.forEach((item, index) => {
proxy.$refs['tableRef' + index][0].toggleAllSelection();
});
@@ -374,4 +318,4 @@ defineExpose({
:deep(.el-table__row:hover > td) {
background-color: #eef9fd !important;
}
</style>
</style>

View File

@@ -18,19 +18,17 @@
<Refresh />
</el-icon>
</div>
<el-tabs v-model="active" class="centered-tabs tab-header" @tab-click="handleClick">
<el-tabs v-model="active" class="demo-tabs centered-tabs tab-header" @tab-click="handleClick">
<el-tab-pane label="在科" name="first" style="padding: 15px 10px">
<PatientList />
</el-tab-pane>
<!-- 隐藏tab
<el-tab-pane label="转科" name="second" style="padding: 0 10px">
<PatientList />
</el-tab-pane>
-->
</el-tabs>
</div>
<div style="width: 100%">
<el-tabs v-model="activeName" class="centered-tabs" @tab-change="handleTabClick">
<el-tabs v-model="activeName" class="demo-tabs centered-tabs" @tab-change="handleTabClick">
<el-tab-pane
v-for="tab in prescriptionTabs"
:key="tab.name"
@@ -50,7 +48,7 @@
</template>
<script setup>
import PatientList from '../components/patientList.vue';
import PatientList from './components/patientList.vue';
import PrescriptionList from './components/prescriptionList.vue';
const activeName = ref('unverified');

View File

@@ -0,0 +1,12 @@
// 选择患者信息
export const patientInfo = ref()
export function updatePatientInfo(info) {
patientInfo.value = info
}
// 多选患者
export const patientInfoList = ref([])
export function updatePatientInfoList(info) {
patientInfoList.value = info
}

View File

@@ -1,9 +0,0 @@
import request from '@/utils/request';
// 体温单图表展示
export function getSummaryList(data) {
return request({
url: '/document/record/summary',
method: 'get',
params: data,
});
}

View File

@@ -1,844 +0,0 @@
<template>
<div class="main">
<PatientList :selected-patient="patientInfo" :on-select="handlePatientSelect" />
<el-container style="height: 100%">
<el-main style="padding: 0">
<div style="margin-bottom: 10px">
<el-date-picker
v-model="intervalTime"
type="daterange"
range-separator="~"
start-placeholder="起始时间"
end-placeholder="结束时间"
:size="medium"
value-format="YYYY-MM-DD"
/>
<el-button style="margin-left: 10px" type="primary" size="default" @click="onSearch"
>搜索</el-button
>
<el-button type="primary" size="default" @click="onAddRecord">新增</el-button>
<el-button type="primary" size="default" @click="printNursingRecord">打印</el-button>
</div>
<div class="header">
<div class="header-item" v-for="(item, index) in personInfo1" :key="index">
<div class="header-title">
<el-text>{{ item.title }}</el-text>
</div>
<div class="header-content">
<el-text>{{ item.text }}</el-text>
</div>
</div>
<!-- <div class="header-item">
<div class="header-title"><el-text></el-text></div>
<div class="header-content"><el-text>20</el-text></div>
<div class="header-title"><el-text></el-text></div>
</div> -->
</div>
<div class="table-contanier">
<el-table
:data="tableData"
:span-method="arraySpanMethod"
border
style="width: 100%"
class="custom-header-table"
height="100%"
>
<!-- 日期与时间合并表头 -->
<el-table-column align="center" class-name="date-time-header" width="150px">
<template #header>
<div class="date-time-container">
<div class="date-label">日期</div>
<div class="time-label">时间</div>
</div>
</template>
<template #default="scope">
<div class="date-time-cell">
<div
v-if="
recordsData[scope.$index].id === null ||
recordsData[scope.$index].id === undefined
"
>
<div style="color: red; font-weight: bold">
总入量为:{{ scope.row.input }}、总出量为:{{ scope.row.output }}
</div>
</div>
<div v-else style="display: flex">
<div class="date-cell">{{ scope.row.date }}</div>
/
<div class="time-cell">{{ scope.row.time }}</div>
</div>
</div>
</template>
</el-table-column>
<!-- 一般column -->
<!-- <el-table-column
v-for="column in averageColumn"
:key="column.id"
:label="column.title"
align="center"
>
<template #default="scope">
{{ averageColumn($index).prop == 'temperature' ? scope.temperature : '' }}
</template>
</el-table-column> -->
<!-- 嵌套column -->
<!-- <el-table-column
v-for="column in nestingColumn"
:key="column.id"
:label="column.title"
align="center"
>
<el-table-column
v-for="column in column.child"
:prop="column.prop"
:key="column.id"
:label="column.title"
align="center"
></el-table-column>
</el-table-column> -->
<el-table-column label="意识" align="center" width="200px">
<template #default="scope">
<!-- <el-select
v-model="scope.row.consciousnessCodeList"
placeholder=""
multiple
collapse-tags
collapse-tags-tooltip
:max-collapse-tags="99"
disabled=""
>
<el-option
v-for="item in ysOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> -->
<el-tag
style="margin: 2px"
type=""
v-for="item in filterYs(scope.row.consciousnessCodeList)"
:key="item.value"
>{{ item.label }}</el-tag
>
</template>
</el-table-column>
<el-table-column label="体温(℃)" align="center" width="100px">
<template #default="scope">
<el-text> {{ scope.row.temperature }}</el-text>
</template>
</el-table-column>
<el-table-column label="脉搏(次/分)" align="center" width="100px">
<template #default="scope">
<el-text> {{ scope.row.pulse }}</el-text>
</template>
</el-table-column>
<el-table-column label="呼吸(次/分)" align="center" width="100px">
<template #default="scope">
<el-text> {{ scope.row.breathe }}</el-text>
</template>
</el-table-column>
<el-table-column label="血压(mmHg)" align="center" width="100px">
<template #default="scope">
<el-text> {{ scope.row.bloodPressure }}</el-text>
</template>
</el-table-column>
<el-table-column label="血氧饱和度(%)" align="center" width="110px">
<template #default="scope">
<el-text> {{ scope.row.bloodOxygen }}</el-text>
</template>
</el-table-column>
<el-table-column label="吸氧升/分" align="center" width="110px">
<template #default="scope">
<el-text> {{ scope.row?.oxygen }}</el-text>
</template>
</el-table-column>
<!-- 入量列组 -->
<el-table-column label="入量(ml)" align="center">
<el-table-column label="名称用法" align="center">
<template #default="scope">
<el-text> {{ scope.row.inputName }}</el-text>
</template>
</el-table-column>
<el-table-column label="量" align="center">
<template #default="scope">
<el-text> {{ scope.row.input }}</el-text>
</template>
</el-table-column>
</el-table-column>
<!-- 出量列组 -->
<el-table-column label="出量" align="center">
<el-table-column label="名称" align="center">
<template #default="scope">
<el-text> {{ scope.row.outputName }}</el-text>
</template>
</el-table-column>
<el-table-column label="量" align="center">
<template #default="scope">
<el-text> {{ scope.row.output }}</el-text>
</template>
</el-table-column>
</el-table-column>
<el-table-column prop="skin" label="皮肤" align="center" width="200px">
<template #default="scope">
<!-- <el-select
placeholder=""
v-model="scope.row.skinconditionCodeList"
multiple
collapse-tags
collapse-tags-tooltip
:max-collapse-tags="99"
disabled=""
>
<el-option
v-for="item in skinconditionOption"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> -->
<el-tag
style="margin: 2px"
type=""
v-for="item in filterPf(scope.row.skinconditionCodeList)"
:key="item.value"
>{{ item.label }}</el-tag
>
</template>
</el-table-column>
<el-table-column prop="tube" label="管路" align="center" width="200px">
<template #default="scope">
<!-- <el-select
placeholder=""
v-model="scope.row.pipelinecare"
multiple
collapse-tags
collapse-tags-tooltip
:max-collapse-tags="99"
disabled=""
>
<el-option
v-for="item in pipelinecareOption"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> -->
<el-tag
style="margin: 2px"
type=""
v-for="item in filterGl(scope.row.pipelinecare)"
:key="item.value"
>{{ item.label }}</el-tag
>
</template>
</el-table-column>
<el-table-column prop="observation" label="病情观察及措施" align="center" width="120px">
<template #default="scope">
<el-text> {{ scope.row.condition }}</el-text>
</template>
</el-table-column>
<el-table-column
prop="nurse"
label="护士签名"
align="center"
width="100px"
></el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="150px">
<template #default="scope" style="display: flex">
<el-button
type="primary"
size="small"
plain
@click="onEdit(scope.row, scope.$index)"
>编辑</el-button
>
<el-button
type="danger"
size="small"
plain
@click="onDelete(scope.row, scope.$index)"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
</div>
<div class="tip-text">
<el-text
>备注:以下项目在相应表格中填写序号:一意识(1、意识清 2、嗜睡3、意识模糊 4、昏睡5.浅昏迷
6.深昏迷)二、管路(1.尿管2.鼻饲管3.胃肠减压管4.
外周静脉置管)5.中心静脉置管6.胸腔闭式引流管 7.腹腔引流管 8.头部引流管 9.其他引流管 10
其他置管)三、皮肤(1.完好 2压疮 3.出血点 4.破损 5. 水肿)。</el-text
>
</div>
</el-main>
</el-container>
<!-- 弹出框 -->
<el-dialog v-model="dialogTableVisible" :show-close="false" width="85%" style="height: 700px">
<OperationRecord
@cancleDialog="onCancle"
@refreshData="refreshFn"
ref="redordRef"
></OperationRecord>
</el-dialog>
</div>
</template>
<script setup>
import { ref, reactive, nextTick, watch } from 'vue';
import OperationRecord from './operationrecord.vue';
import { patientInfo, updatePatientInfo } from '../../inpatientDoctor/home/store/patient';
import { getTemperatureType } from '../tprsheet/api/api';
import { getSummaryList } from './api';
import { getRecordByEncounterIdList } from '../../inpatientDoctor/home/emr/api';
import { deleteRecord } from '../../inpatientDoctor/home/emr/api';
import printUtils, { PRINT_TEMPLATE } from '@/utils/printUtils';
import PatientList from '@/components/PatientList/patient-list.vue';
import { ElMessage } from 'element-plus';
// 处理患者选择
const handlePatientSelect = (patient) => {
updatePatientInfo(patient);
};
const dialogTableVisible = ref(false);
const intervalTime = ref([]);
const redordRef = ref();
const isTemplate = ref(false);
const editForm = ref({
definitionId: '',
startTime: '',
endTime: '',
});
const recordsData = ref([]);
watch(patientInfo, (newVal) => {
const dataArr = [
{ title: '科别', text: newVal.inHospitalOrgName ?? '' },
{ title: '姓名', text: newVal.patientName ?? '' },
{ title: '年龄', text: newVal.age ?? '' },
{ title: '性别', text: newVal.genderEnum_enumText ?? '' },
{ title: '床号', text: newVal.bedName ?? '' },
{ title: '住院', text: '人民医院' },
{ title: '入院日期', text: newVal.inHospitalTime ?? '' },
{ title: '诊断', text: newVal.regDiagnosisName ?? '' },
];
Object.assign(personInfo1, dataArr);
getDefinitionIdNet();
});
// 意识
const ysOptions = [
{
value: '1',
label: '清醒',
},
{
value: '2',
label: '嗜睡',
},
{
value: '3',
label: '意识模糊',
},
{
value: '4',
label: '昏睡',
},
{
value: '5',
label: '谵妄',
},
{
value: '6',
label: '浅昏迷',
},
{
value: '7',
label: '中度昏迷',
},
{
value: '8',
label: '深昏迷',
},
{
value: '9',
label: '全麻未醒',
},
{
value: '10',
label: '镇静',
},
];
// 氧疗
const oxygenOptions = [
{
value: '1',
label: '鼻导管吸氧',
},
{
value: '2',
label: '面罩吸氧',
},
{
value: '3',
label: '高流量氧疗',
},
{
value: '4',
label: '机械通气',
},
];
// 皮肤情况
const skinconditionOption = [
{
value: '1',
label: '完好',
},
{
value: '2',
label: '压疮',
},
{
value: '3',
label: '出血点',
},
{
value: '4',
label: '破损',
},
{
value: '5',
label: '水肿',
},
{
value: '6',
label: '瘀斑',
},
{
value: '7',
label: '过敏',
},
{
value: '8',
label: '其他',
},
];
// 管路护理
const pipelinecareOption = [
{
value: '1',
label: '胃管',
},
{
value: '2',
label: '导尿管',
},
{
value: '3',
label: '静脉置管',
},
{
value: '4',
label: '吸氧管',
},
{
value: '5',
label: 'T管',
},
{
value: '6',
label: '胸腔引流管',
},
{
value: '7',
label: '腹腔引流管',
},
{
value: '8',
label: '伤口引流管',
},
{
value: '9',
label: '脑室引流管',
},
{
value: '10',
label: '其他',
},
];
// 过滤意识
const filterYs = (row) => {
let dats = [];
(row || []).forEach((str) => {
ysOptions.forEach((item) => {
if (item.value == str) {
dats.push(item);
}
});
});
return dats;
};
// 过滤皮肤
const filterPf = (row) => {
let dats = [];
(row || []).forEach((str) => {
skinconditionOption.forEach((item) => {
if (item.value == str) {
dats.push(item);
}
});
});
return dats;
};
// 过滤管路
const filterGl = (row) => {
let dats = [];
(row || []).forEach((str) => {
pipelinecareOption.forEach((item) => {
if (item.value == str) {
dats.push(item);
}
});
});
return dats;
};
// 获取护理记录单类型
const getDefinitionIdNet = async () => {
const res = await getTemperatureType({ menuEnum: '3' });
//默认选中第一个
if (res.data?.length > 0) {
isTemplate.value = true;
const obj = res.data[0];
editForm.value.definitionId = obj.id;
getTableList();
} else {
isTemplate.value = false;
}
};
const refreshFn = () => {
getTableList();
};
// 获取列表数据
const getTableList = async () => {
const res = await getSummaryList({
...editForm.value,
encounterId: patientInfo.value.encounterId,
patientId: patientInfo.value.patientId,
});
console.log('getTableList========>', JSON.stringify(res.data));
recordsData.value = res.data || [];
const tables = [];
(res.data || []).forEach((item) => {
const obj = JSON.parse(item.contentJson);
tables.push(obj);
});
tableData.value = tables;
};
// 个人信息
const personInfo1 = reactive([
{ title: '科别', text: '' },
{ title: '姓名', text: '' },
{ title: '年龄', text: '' },
{ title: '性别', text: '' },
{ title: '床号', text: '' },
{ title: '住院', text: '' },
{ title: '入院日期', text: '' },
{ title: '诊断', text: '' },
]);
// 普通表头配置
const averageColumn = [
{
id: '0',
prop: 'consciousness',
title: '意识',
},
{
id: '1',
prop: 'temperature',
title: '体温(℃)',
},
{
id: '2',
prop: 'pulse',
title: '脉搏(次/分)',
},
{
id: '3',
prop: 'respiration',
title: '呼吸(次/分)',
},
{
id: '4',
prop: 'bloodPressure',
title: '血压(mmHg)',
},
{
id: '5',
prop: 'bloodOxygen',
title: '血氧饱和度(%)',
},
{
id: '6',
prop: 'oxygenFlow',
title: '吸氧(升/分)',
},
];
//
const nestingColumn = ref([
{
id: '7',
prop: '',
title: '入量(ml)',
child: [
{
id: '7-1',
prop: 'name',
title: '名称用法',
},
{
id: '7-2',
prop: 'plan',
title: '量',
},
],
},
{
id: '8',
prop: '',
title: '出量',
child: [
{
id: '8-1',
prop: 'name',
title: '名称',
},
{
id: '8-2',
prop: 'plan',
title: '量',
},
],
},
]);
// 表格数据
const tableData = ref([]);
// 合并单元格
const arraySpanMethod = ({ row, column, rowIndex, columnIndex }) => {
const obj = recordsData.value[rowIndex];
if (obj.id === undefined || obj.id === null) {
if (columnIndex == 0) {
return {
rowspan: 1,
colspan: 17,
};
} else {
return {
rowspan: 0,
colspan: 0,
};
}
}
return {
rowspan: 1,
colspan: 1,
};
// if (rowIndex == 1) {
// if (columnIndex == 0) {
// return {
// rowspan: 1,
// colspan: 17,
// };
// } else {
// return {
// rowspan: 0,
// colspan: 0,
// };
// }
// }
// return {
// rowspan: 1,
// colspan: 1,
// };
};
// 编辑
const onEdit = (row, index) => {
const item = recordsData.value[index];
dialogTableVisible.value = true;
nextTick(() => {
if (redordRef) {
redordRef.value.editEmit(item);
}
});
};
// 新增
const onAddRecord = () => {
if (!patientInfo.value) {
ElMessage({
type: 'error',
message: '请选择患者',
});
return;
}
if (!isTemplate.value) {
ElMessage({
type: 'error',
message: '护理记录未配置,请联系管理员',
});
return;
}
dialogTableVisible.value = true;
nextTick(() => {
if (redordRef) {
redordRef.value.reset();
}
});
};
// 搜索
const onSearch = () => {
if (typeof intervalTime === 'object' && intervalTime === null) {
editForm.value.startTime = '';
editForm.value.endTime = '';
getTableList();
} else {
if (intervalTime.value?.length > 0) {
editForm.value.startTime = intervalTime.value[0];
editForm.value.endTime = intervalTime.value[1];
getTableList();
} else {
editForm.value.startTime = '';
editForm.value.endTime = '';
getTableList();
}
}
};
// 删除
const onDelete = async (row, index) => {
const ids = recordsData.value[index].id;
debugger;
// recordsData.value
await deleteRecord([ids]);
getTableList();
};
// 关闭弹出曾次
const onCancle = () => {
dialogTableVisible.value = false;
};
</script>
<style lang="scss" scoped>
.main {
padding-top: 10px;
display: flex;
height: 100%;
.header {
// background: red;
display: flex;
justify-content: space-between;
padding: 0 10px;
.header-item {
display: flex;
align-items: center;
}
}
.table-contanier {
margin-top: 10px;
background: red;
height: calc(100vh - 280px);
.custom-header-table ::v-deep .el-table__header-wrapper th {
background-color: #f5f7fa;
font-weight: normal;
}
/* 日期时间表头样式 */
.date-time-header {
width: 120px;
}
.date-time-container {
position: relative;
width: 100%;
height: 100%;
min-height: 60px;
}
.date-label {
position: absolute;
top: 5px;
left: 5px;
z-index: 1;
}
.time-label {
position: absolute;
bottom: 5px;
right: 5px;
z-index: 1;
}
.date-time-container::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(
154deg,
transparent 49.5%,
#dcdfe6 49.5%,
#dcdfe6 50.5%,
transparent 50.5%
);
pointer-events: none;
}
/* 日期时间单元格样式 */
.date-time-cell {
// position: relative;
display: flex;
// flex-direction: column;
align-items: center;
// height: 100%;
// min-height: 48px;
}
.date-cell {
// position: absolute;
// top: 5px;
// left: 5px;
// background: red;
}
.time-cell {
// position: absolute;
// bottom: 5px;
// right: 5px;
height: 100%;
// width: 100%;
text-align: left;
}
}
.tip-text {
padding: 0 10px;
}
}
</style>

View File

@@ -1,662 +0,0 @@
<template>
<div class="main">
<div class="title">
<h1>患者护理记录单</h1>
</div>
<el-scrollbar height="500px" style="height: 100%">
<div class="content">
<el-form :model="rulesFrom" :rules="rules" ref="formRef">
<el-card>
<div class="commoncss">
<el-form-item prop="date" label="日期:" label-width="100px">
<el-date-picker
v-model="rulesFrom.date"
type="date"
placeholder="请选择"
format="YYYY/MM/DD"
value-format="YYYY-MM-DD"
@change="dateChange"
/>
</el-form-item>
<el-form-item prop="time" label="时间:" label-width="100px">
<el-time-picker
v-model="rulesFrom.time"
placeholder="请选择时间"
format="HH:mm"
value-format="HH:mm"
@change="dateChange"
/>
</el-form-item>
</div>
<!-- 基本信息 -->
<div class="foundation">
<div class="commone-title">基本信息</div>
<div class="foundation-content">
<div class="foundation-content-first">
<el-form-item label="意识:" label-width="100px">
<el-select
v-model="rulesFrom.consciousnessCodeList"
multiple
collapse-tags
collapse-tags-tooltip
:max-collapse-tags="1"
placeholder="请选择"
style="width: 220px"
>
<el-option
v-for="item in ysOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="体温:" label-width="100px">
<div class="commoncss">
<el-input
v-model="rulesFrom.temperature"
placeholder="请输入"
clearable
style="width: 220px"
/>
<div></div>
</div>
</el-form-item>
<el-form-item label="心率:" label-width="100px">
<div class="commoncss">
<el-input
v-model="rulesFrom.heartRate"
placeholder="请选择"
clearable
style="width: 220px"
/>
<div class="unit">/</div>
</div>
</el-form-item>
</div>
<div class="foundation-content-second">
<el-form-item label="脉率:" label-width="100px" class="wait-flex">
<div class="commoncss">
<el-input
v-model="rulesFrom.pulse"
placeholder="请选择"
clearable
class="wait-flex"
style="width: 180px"
/>
<div class="unit">/</div>
</div>
</el-form-item>
<el-form-item label="呼吸:" label-width="100px" class="wait-flex">
<div class="commoncss">
<el-input
v-model="rulesFrom.breathe"
placeholder="请选择"
clearable
class="wait-flex"
style="width: 180px"
/>
<div class="unit">/</div>
</div>
</el-form-item>
<el-form-item label="血压:" label-width="100px" class="wait-flex">
<div class="commoncss">
<el-input
v-model="rulesFrom.bloodPressure"
placeholder="请选择"
clearable
style="width: 180px"
/>
<div class="unit">mmHg</div>
</div>
</el-form-item>
<el-form-item label="血氧饱和度:" label-width="100px" class="wait-flex">
<div class="commoncss">
<el-input
v-model="rulesFrom.bloodOxygen"
placeholder="请选择"
clearable
style="width: 180px"
/>
<div class="unit">%</div>
</div>
</el-form-item>
</div>
<div>
<el-form-item label="吸氧升/分:" label-width="100px" class="wait-flex">
<div class="commoncss">
<el-input
v-model="rulesFrom.oxygen"
placeholder="请选择"
clearable
style="width: 180px"
/>
<div class="unit">/</div>
</div>
</el-form-item>
</div>
</div>
</div>
<!-- 氧疗 -->
<div class="oxygen">
<div class="oxygen-title commone-title">氧疗/min</div>
<div class="oxygen-content">
<el-form-item label="方式:" label-width="100px">
<el-select
v-model="rulesFrom.oxygenCodeList"
multiple
collapse-tags
collapse-tags-tooltip
:max-collapse-tags="1"
placeholder="请选择"
style="width: 220px"
>
<el-option
v-for="item in oxygenOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="流量:" label-width="100px">
<div>
<el-input
v-model="rulesFrom.oxygenflow"
placeholder="请输入"
clearable
style="width: 220px"
/>
</div>
</el-form-item>
</div>
</div>
<!-- 入量 -->
<div class="input">
<div class="input-title commone-title">入量</div>
<div class="input-content">
<el-form-item label="名称:" label-width="100px">
<div>
<el-input
v-model="rulesFrom.inputName"
placeholder="请输入"
clearable
style="width: 220px"
/>
</div>
</el-form-item>
<el-form-item label="ml" label-width="100px">
<div>
<el-input
v-model="rulesFrom.input"
placeholder="请输入"
clearable
style="width: 220px"
/>
</div>
</el-form-item>
<el-form-item label="途径:" label-width="100px">
<div>
<el-input
v-model="rulesFrom.inputvia"
placeholder="请输入"
clearable
style="width: 220px"
/>
</div>
</el-form-item>
</div>
</div>
<!-- 出量 -->
<div class="out">
<div class="out-title commone-title">出量</div>
<div class="out-content">
<el-form-item label="名称:" label-width="100px">
<div>
<el-input
v-model="rulesFrom.outputName"
placeholder="请输入"
clearable
style="width: 220px"
/>
</div>
</el-form-item>
<el-form-item label="ml" label-width="100px">
<div>
<el-input
v-model="rulesFrom.output"
placeholder="请输入"
clearable
style="width: 220px"
/>
</div>
</el-form-item>
</div>
</div>
<!-- 皮肤情况 -->
<div class="skin">
<el-form-item label="皮肤情况:" label-width="100px">
<el-select
v-model="rulesFrom.skinconditionCodeList"
multiple
collapse-tags
collapse-tags-tooltip
:max-collapse-tags="3"
placeholder="请选择"
style="width: 380px"
>
<el-option
v-for="item in skinconditionOption"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</div>
<!-- 管路护理 -->
<div class="nursing">
<el-form-item label="管路护理:" label-width="100px">
<el-select
v-model="rulesFrom.pipelinecare"
multiple
collapse-tags
collapse-tags-tooltip
:max-collapse-tags="3"
placeholder="请选择"
style="width: 380px"
>
<el-option
v-for="item in pipelinecareOption"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</div>
<!-- 病情措施 -->
<div class="nursing">
<el-form-item label="病情措施:" label-width="100px">
<div>
<el-input
type="textarea"
v-model="rulesFrom.condition"
placeholder="请选择"
clearable
style="width: 380px"
:rows="10"
:autosize="{ minRows: 5, maxRows: 10 }"
/>
</div>
</el-form-item>
</div>
<!-- 护士签名 -->
<div class="nurse">
<el-form-item label="护士签名:" label-width="100px">
<div>
<el-input
v-model="rulesFrom.nurse"
placeholder="请选择"
clearable
style="width: 380px"
/>
</div>
</el-form-item>
</div>
</el-card>
</el-form>
</div>
</el-scrollbar>
<div style="display: flex; justify-content: flex-end; margin-top: 10px">
<el-button @click="onCancle">取消</el-button>
<el-button type="primary" @click="saveData">保存</el-button>
</div>
</div>
</template>
<script setup>
import { computed, nextTick, reactive, ref, watch, watchEffect } from 'vue';
import dayjs from 'dayjs';
import { getTemperatureType, addRecord } from '../tprsheet/api/api';
import { patientInfo } from '../../inpatientDoctor/home/store/patient';
import { ElMessage } from 'element-plus';
const formRef = ref();
// 意识
const ysOptions = [
{
value: '1',
label: '清醒',
},
{
value: '2',
label: '嗜睡',
},
{
value: '3',
label: '意识模糊',
},
{
value: '4',
label: '昏睡',
},
{
value: '5',
label: '谵妄',
},
{
value: '6',
label: '浅昏迷',
},
{
value: '7',
label: '中度昏迷',
},
{
value: '8',
label: '深昏迷',
},
{
value: '9',
label: '全麻未醒',
},
{
value: '10',
label: '镇静',
},
];
// 氧疗
const oxygenOptions = [
{
value: '1',
label: '鼻导管吸氧',
},
{
value: '2',
label: '面罩吸氧',
},
{
value: '3',
label: '高流量氧疗',
},
{
value: '4',
label: '机械通气',
},
];
// 皮肤情况
const skinconditionOption = [
{
value: '1',
label: '完好',
},
{
value: '2',
label: '压疮',
},
{
value: '3',
label: '出血点',
},
{
value: '4',
label: '破损',
},
{
value: '5',
label: '水肿',
},
{
value: '6',
label: '瘀斑',
},
{
value: '7',
label: '过敏',
},
{
value: '8',
label: '其他',
},
];
// 管路护理
const pipelinecareOption = [
{
value: '1',
label: '胃管',
},
{
value: '2',
label: '导尿管',
},
{
value: '3',
label: '静脉置管',
},
{
value: '4',
label: '吸氧管',
},
{
value: '5',
label: 'T管',
},
{
value: '6',
label: '胸腔引流管',
},
{
value: '7',
label: '腹腔引流管',
},
{
value: '8',
label: '伤口引流管',
},
{
value: '9',
label: '脑室引流管',
},
{
value: '10',
label: '其他',
},
];
const rulesFrom = ref({
date: '', //日期 年月日
time: '', //时间 十分
recordTime: '', //组合日期时间 年月日时分
consciousnessCodeList: [], //意识code
temperature: '', //体温
heartRate: '', //心率
pulse: '', //脉搏
breathe: '', //呼吸
bloodPressure: '', //血压
bloodOxygen: '', //血氧
oxygenCodeList: [], //氧疗
oxygenflow: '', //氧疗流量
inputName: '', //入量名称
input: '', //入量
inputvia: '', //入量途径
outputName: '', //出量名称
output: '', //出量
skinconditionCodeList: [], //皮肤情况
pipelinecare: [], //管路护理
condition: '', //病情
nurse: '', //护士
oxygen: '',
});
const rules = reactive({
date: [{ required: true, message: '请选择日期', trigger: 'blur' }],
time: [{ required: true, message: '请选择时间', trigger: 'blur' }],
});
const dateChange = () => {
rulesFrom.value.recordTime = rulesFrom.value.date + ' ' + rulesFrom.value.time + ':00';
};
// 计算时间
rulesFrom.value.recordTime = computed(() => {
console.log('11111111111111');
return rulesFrom.value.date + ' ' + rulesFrom.value.time;
});
// 保存form
const editForm = ref({
id: '',
definitionId: '',
definitionBusNo: '',
contentJson: '',
statusEnum: 1, // 0草稿/暂存 1提交 2归档 3修改
organizationId: 0,
encounterId: '',
patientId: '',
recordTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
createBy: '',
source: '3',
});
const emit = defineEmits(['cancleDialog', 'refreshData']);
const onCancle = () => {
emit('cancleDialog');
};
// 保存数据
const saveData = () => {
if (!patientInfo.value) {
ElMessage({
type: 'error',
message: '请选择患者',
});
}
editForm.value.contentJson = JSON.stringify(rulesFrom.value);
editForm.value.encounterId = patientInfo.value.encounterId;
editForm.value.patientId = patientInfo.value.patientId;
editForm.value.recordTime = rulesFrom.value.recordTime;
console.log('editForm=================>', JSON.stringify(rulesFrom.value));
formRef.value.validate(async (res) => {
if (res) {
await addRecord(editForm.value);
if (editForm.value.id && editForm.value.id.length > 0) {
ElMessage.success('护理记录修改成功');
} else {
ElMessage.success('护理记录保存成功');
}
emit('refreshData');
}
});
};
// 获取护理记录单类型
const getDefinitionIdNet = async () => {
const res = await getTemperatureType({ menuEnum: '3' });
//默认选中第一个
if (res.data?.length > 0) {
const obj = res.data[0];
editForm.value.definitionId = obj.id;
editForm.value.definitionBusNo = obj.busNo;
}
};
watch(patientInfo, () => {
getDefinitionIdNet();
});
// 重置
const reset = () => {
rulesFrom.value = {
date: '', //日期 年月日
time: '', //时间 十分
recordTime: '', //组合日期时间 年月日时分
consciousnessCodeList: [], //意识code
temperature: '', //体温
heartRate: '', //心率
pulse: '', //脉搏
breathe: '', //呼吸
bloodPressure: '', //血压
bloodOxygen: '', //血氧
oxygenCodeList: [], //氧疗
oxygenflow: '', //氧疗流量
inputName: '', //入量名称
input: '', //入量
inputvia: '', //入量途径
outputName: '', //出量名称
output: '', //出量
skinconditionCodeList: [], //皮肤情况
pipelinecare: [], //管路护理
condition: '', //病情
nurse: '', //护士
};
editForm.value = {
id: '',
definitionId: '',
definitionBusNo: '',
contentJson: '',
statusEnum: 1, // 0草稿/暂存 1提交 2归档 3修改
organizationId: 0,
encounterId: '',
patientId: '',
recordTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
createBy: '',
source: '3',
};
getDefinitionIdNet();
};
// 编辑
const editEmit = (row) => {
console.log('rowwwww=======>', JSON.stringify(row));
editForm.value.id = row.id;
editForm.value.definitionId = row.definitionId;
editForm.value.definitionBusNo = row.definitionBusNo;
rulesFrom.value = JSON.parse(row.contentJson);
};
defineExpose({ reset, editEmit });
</script>
<style lang="scss" scoped>
.main {
display: flex;
flex-direction: column;
.title {
width: 100%;
text-align: center;
}
.foundation {
.foundation-content {
.foundation-content-first {
display: flex;
}
.foundation-content-second {
display: flex;
}
}
}
.oxygen {
.oxygen-title {
}
.oxygen-content {
display: flex;
}
}
.input {
.input-title {
}
.input-content {
display: flex;
}
}
.out {
.out-title {
}
.out-content {
display: flex;
}
}
}
.commoncss {
display: flex;
}
.unit {
width: 50px;
}
.wait-flex {
flex: 1;
}
.commone-title {
font-weight: bold;
}
</style>

View File

@@ -1,177 +0,0 @@
import request from '@/utils/request';
/**
* 获取初始化
*/
export function getInit(queryParams) {
return request({
url: '/nurse-station/atd-manage/init',
method: 'get',
params: queryParams,
});
}
/**
* 获取患者列表
*/
export function getPendingInfo(queryParams) {
return request({
url: '/nurse-station/atd-manage/admission-patient',
method: 'get',
params: queryParams,
});
}
/**
* 获取床位列表
*/
export function getBedInfo(queryParams) {
return request({
url: '/nurse-station/atd-manage/admission-bed',
method: 'get',
params: queryParams,
});
}
/**
* 获取患者详细信息
*/
export function getPatientInfo(queryParams) {
return request({
url: '/nurse-station/atd-manage/admission-patient-info',
method: 'get',
params: queryParams,
});
}
/**
* 获取医生列表
*/
export function getDoctorInfo(queryParams) {
return request({
url: '/charge-manage/register/practitioner-metadata?orgId=' + queryParams.organizationId,
method: 'get',
});
}
/**
* 获取护士列表
*/
export function getNurseInfo(queryParams) {
return request({
url: '/app-common/nurse-list?orgId=' + queryParams.organizationId,
method: 'get',
});
}
/**
* 入科床位分配
*/
export function bedAssignment(data) {
return request({
url: '/nurse-station/atd-manage/bed-assignment',
method: 'post',
data: data,
});
}
/**
* 获取病区
*/
export function childLocationList(queryParams) {
return request({
url: '/app-common/child-location-list',
method: 'get',
params: queryParams,
});
}
export function getPractitionerWard(queryParams) {
return request({
url: '/app-common/practitioner-ward',
method: 'get',
params: queryParams,
});
}
export function getPrescriptionList(queryParams) {
return request({
url: '/nurse-station/advice-process/inpatient-advice',
method: 'get',
params: queryParams,
});
}
export function getPersonAccount(queryParams) {
return request({
url: '/nurse-station/atd-manage/get-amount?encounterId=' + queryParams.encounterId,
method: 'get',
});
}
export function getDRMedication(queryParams) {
return request({
url: '/nurse-station/atd-manage/get-dr-medication?encounterId=' + queryParams.encounterId,
method: 'get',
});
}
export function updateTransferDepartment(encounterId) {
return request({
url: '/nurse-station/atd-manage/transfer-department',
method: 'put',
params: {
encounterId: encounterId,
},
});
}
export function updateOutHospital(encounterId) {
return request({
url: '/nurse-station/atd-manage/transfer-department',
method: 'put',
params: {
encounterId: encounterId,
},
});
}
// 获取数据源
export function getDataSource() {
return request({
url: '/nurse-station/auto-roll/source-info',
method: 'get',
});
}
// 保存住院就诊的滚方信息
export function saveInpatientRoll(data) {
return request({
url: '/nurse-station/auto-roll/save-binding',
method: 'post',
data: data,
});
}
// 查询住院就诊的滚方信息
export function getRollInfoPage(id) {
return request({
url: `/nurse-station/auto-roll/encounter-info?encounterId=${id}`,
method: 'get',
});
}
// 启用
export function enableRoll(id) {
return request({
url: `/nurse-station/auto-roll/active?id=${id}`,
method: 'put',
});
}
// 停用
export function stopRoll(id) {
return request({
url: `/nurse-station/auto-roll/retired?id=${id}`,
method: 'put',
});
}
// 删除
export function deleteRoll(id) {
return request({
url: `/nurse-station/auto-roll/delete-binding?id=${id}`,
method: 'delete',
});
}

View File

@@ -1,621 +0,0 @@
<template>
<div class="app-container">
<el-row :gutter="10">
<el-form :model="queryParams" ref="queryRef" inline="true">
<el-form-item label="入院病区" prop="wardId" style="width: 240px">
<el-select
v-model="queryParams.wardId"
@change="changeWardLocationId"
filterable
clearable
>
<el-option
v-for="item in initInfoOptions.wardListOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="入院病房" prop="houseId">
<el-select
v-model="queryParams.houseId"
style="width: 240px"
@change="handleQuery"
filterable
clearable
>
<el-option
v-for="item in wardLocationList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="住院状态" prop="encounterStatus">
<el-select
v-model="queryParams.encounterStatus"
style="width: 240px"
@change="handleQuery"
filterable
clearable
>
<el-option label="全部" value="" />
<el-option
v-for="item in initInfoOptions.encounterStatusOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="床位状态" prop="bedStatus" style="width: 240px">
<el-select v-model="bedStatusFilter" filterable clearable @change="handleQuery">
<el-option label="全部" value="" />
<el-option
v-for="item in initInfoOptions.bedStatusOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-row>
<el-row :gutter="10">
<el-col :span="4">
<el-card shadow="never">
<template #header>
<div class="card-header">
<span>新入院患者</span>
</div>
</template>
<el-input
v-model="queryParams.searchKey"
placeholder="请输入住院号"
clearable
style="width: 100%; margin-bottom: 10px"
@keyup.enter="handleQuery"
>
<template #append>
<el-button icon="Search" @click="handleQuery" />
</template>
</el-input>
<el-scrollbar height="700px">
<div
v-for="(item, index) in patientList"
:class="item.active ? 'patient-card actived' : 'patient-card'"
:key="item.id"
@click="handleCardClick(item, index)"
@dblclick="handleCardDblClick(item)"
>
<div class="main-info-container">
<div class="name-container">
<!-- 患者姓名 -->
<div class="name" style="max-width: 90px">
<el-text class="name" width="auto">{{ item.patientName || '未知' }}</el-text>
</div>
</div>
<div class="name-container">
<!-- 患者性别/年龄 -->
<div class="age">
<el-text class="name" width="auto">
{{ item.genderEnum_enumText }}/{{ item.age }}/{{ item.priorityEnum_enumText }}
</el-text>
</div>
</div>
<div class="patient-tag" :class="getPatientTagClass(item)">
{{ item.encounterStatus_enumText }}
</div>
</div>
<div style="margin-left: 15px; color: #333; font-size: 14px">
{{ item.contractName }}
</div>
<div class="doctor-parent-line" />
<div class="personal-info-container">
<div class="name-container">
<div class="name">
<el-text class="name" width="auto">入院时间</el-text>
<el-text class="name" width="auto">
{{ item.startTime ? formatDate(item.startTime) : '-' }}
</el-text>
</div>
</div>
</div>
<div class="personal-info-container">
<div class="name-container">
<el-text class="name" width="auto">入院科室</el-text>
<el-text class="name" width="auto">
{{ item.organizationName ? item.organizationName : '-' }}
</el-text>
</div>
</div>
<div class="personal-info-container">
<div class="name-container">
<el-text class="name" width="auto">住院号</el-text>
<el-text class="name" width="auto">
{{ item.busNo ? item.busNo : '-' }}
</el-text>
</div>
</div>
</div>
</el-scrollbar>
</el-card>
</el-col>
<el-col :span="20">
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Plus"
@click="handleAddFeeItemm"
:disabled="!selectPatient"
>
新增滚费项目
</el-button>
</el-col>
</el-row>
<el-table :data="rollInfoPageList" ref="table" border>
<el-table-column label="滚费项目" prop="definitionName" align="center" />
<el-table-column label="单位" prop="unitCodeName" align="center" />
<el-table-column label="数量" prop="quantity" align="center" />
<el-table-column label="状态" prop="statusEnum_enumText" align="center">
<template #default="scope">
<el-tag v-if="scope.row.statusEnum_enumText === '启用'" type="success">
{{ scope.row.statusEnum_enumText }}
</el-tag>
<el-tag v-else type="warning">
{{ scope.row.statusEnum_enumText }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="success"
icon="Edit"
@click="handleEnable(scope.row)"
v-if="scope.row.statusEnum_enumText === '停用'"
>
启用
</el-button>
<el-button
link
type="warning"
icon="Edit"
@click="handleStop(scope.row)"
v-if="scope.row.statusEnum_enumText === '启用'"
>
停用
</el-button>
<el-button link icon="Edit" type="danger" @click="handleDelete(scope.row)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-col>
</el-row>
<el-dialog
title="新增滚费配置"
v-model="dialogVisible"
width="400px"
:before-close="handleClose"
append-to-body
>
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
<el-form-item label="滚费项目" prop="instanceId">
<el-select
v-model="form.instanceId"
placeholder="请选择"
filterable
clearable
style="width: 100%"
@change="handleChageInstanceId"
>
<el-option
v-for="item in feeItemOptions"
:key="item.instanceId"
:label="item.instanceName"
:value="item.instanceId"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="数量" prop="quantity">
<el-input-number
v-model="form.quantity"
placeholder="请输入数量"
controls-position="right"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="单位" prop="unit">
<el-input v-model="form.unit" placeholder="请输入" disabled style="width: 100%" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="handleClose"> </el-button>
<el-button type="primary" @click="handleSubmit"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { onBeforeMount, onMounted, reactive, ref, getCurrentInstance } from 'vue';
import {
getPendingInfo,
getBedInfo,
getInit,
childLocationList,
getPractitionerWard,
getDataSource,
saveInpatientRoll,
getRollInfoPage,
enableRoll,
stopRoll,
deleteRoll,
} from './components/api.js';
import { formatDate } from '@/utils/index';
import { ElMessage } from 'element-plus';
const { proxy } = getCurrentInstance();
const transferInDialogVisible = ref(false);
const dialogVisible = ref(false);
const state = reactive({});
const loading = ref(false);
const total = ref();
const badList = ref([]);
const patientList = ref([]);
const pendingInfo = ref({});
const wardLocationList = ref([]);
const priorityOptions = ref([]);
const initInfoOptions = ref({
encounterStatusOptions: [],
bedStatusOptions: [],
priorityOptions: [],
wardListOptions: [],
});
// 新增床状态筛选字段
const bedStatusFilter = ref('');
onBeforeMount(() => {});
const queryParams = ref({
pageNo: 1,
pageSize: 50,
searchKey: '',
wardId: '',
houseId: '',
encounterStatus: '',
bedStatus: '', // 这个字段现在只用于床位查询,不再用于患者列表查询
});
const formRef = ref(null);
const form = reactive({
instanceId: undefined,
unit: undefined,
quantity: 1,
});
const rules = {
instanceId: [{ required: true, message: '请选择滚费项目', trigger: 'change' }],
quantity: [
{ required: true, message: '请输入数量', trigger: 'blur' },
{ type: 'number', min: 0, message: '数量必须大于等于0', trigger: 'blur' },
],
};
onMounted(() => {
getInit().then((res) => {
initInfoOptions.value = res.data;
priorityOptions.value = res.data.priorityOptions || [];
getList();
});
getPractitionerWard().then((res) => {
queryParams.value.wardId = res[0].id;
initInfoOptions.value.wardListOptions = res;
changeWardLocationId(res[0].id);
});
});
defineExpose({ state });
const feeItemOptions = ref([]);
async function getInitDataSourceOptions() {
const res = await getDataSource();
feeItemOptions.value = res.data;
}
const getList = () => {
getPatientList();
// 床位查询不使用encounterStatus参数只使用基本的查询参数
const bedQueryParams = {
...queryParams.value,
encounterStatus: undefined, // 移除encounterStatus确保不影响床位列表查询
};
getBedInfo(bedQueryParams).then((res) => {
badList.value = res.data.records;
});
};
function handleEnable(row) {
proxy
.$confirm('确定启用吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
enableRoll([row.id]).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('启用成功');
getRollInfoPageList();
}
});
});
}
function handleStop(row) {
proxy
.$confirm('确定停用吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
stopRoll([row.id]).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('停用成功');
getRollInfoPageList();
}
});
});
}
function handleDelete(row) {
proxy
.$confirm('确定删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
deleteRoll([row.id]).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('删除成功');
getRollInfoPageList();
}
});
});
}
// 重置查询条件
function resetQuery() {
queryParams.value = {
pageNo: 1,
pageSize: 50,
searchKey: '',
wardId: '',
houseId: '',
encounterStatus: '',
bedStatus: '',
};
bedStatusFilter.value = '';
getList();
}
function changeWardLocationId(id) {
let params = {
locationId: id,
locationForm: 10,
};
queryParams.value.houseId = '';
childLocationList(params).then((res) => {
wardLocationList.value = res;
});
handleQuery();
}
// 获新入院患者列表
function getPatientList() {
// 为患者列表查询创建一个新的参数对象不包含bedStatus
const patientQueryParams = {
...queryParams.value,
bedStatus: undefined, // 移除bedStatus确保不影响患者列表查询
};
getPendingInfo(patientQueryParams).then((res) => {
loading.value = false;
// 为每个患者项初始化 active 属性
patientList.value = res.data.records.map((item) => ({
...item,
active: false,
}));
total.value = res.data.total;
});
}
// 选中患者
const selectPatient = ref(null);
function handleCardClick(item, index) {
// 清除所有项的激活状态
patientList.value.forEach((patient) => {
patient.active = false;
});
// 设置当前项为激活状态
item.active = true;
console.log(item);
selectPatient.value = item;
getRollInfoPageList();
}
function handleChageInstanceId(value) {
form.unit = feeItemOptions.value.find(
(item) => item.instanceId === value
).permittedUnitCode_dictText;
}
function handleClose() {
dialogVisible.value = false;
// 重置表单
form.name = '';
form.unit = '';
form.quantity = 1;
formRef.value?.resetFields();
}
// 获取滚费信息列表
const rollInfoPageList = ref([]);
function getRollInfoPageList() {
const encounterId = selectPatient.value.encounterId;
loading.value = true;
getRollInfoPage(encounterId).then((res) => {
rollInfoPageList.value = res.data;
loading.value = false;
});
}
function handleSubmit() {
formRef.value?.validate((valid) => {
if (valid) {
const param = {
encounterId: selectPatient.value.encounterId,
instanceId: form.instanceId,
quantity: form.quantity,
};
proxy
.$confirm('确认保存吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
saveInpatientRoll(param).then((res) => {
ElMessage.success('新增成功');
handleClose();
getRollInfoPageList();
});
})
.catch(() => {});
} else {
ElMessage.warning('请完善表单信息');
}
});
}
// 双击患者卡片事件
function handleCardDblClick(item) {
if (item.encounterStatus == 2) {
ElMessage({
message: '请分配病床!',
type: 'warning',
grouping: true,
showClose: true,
});
} else {
pendingInfo.value = {
...item,
entranceType: 1,
};
transferInDialogVisible.value = true;
}
}
function handleQuery() {
getList();
}
function handleAddFeeItemm() {
dialogVisible.value = true;
getInitDataSourceOptions();
}
function getPatientTagClass(item) {
if (item.encounterStatus == 2) {
return 'blue-tag';
} else if (item.encounterStatus == 5) {
return 'green-tag';
}
return '';
}
</script>
<style lang="scss" scoped>
.patient-card {
width: 100%;
overflow: hidden;
background-color: #fff;
border: 1px solid;
border-color: #eee;
border-radius: 4px;
box-shadow: 0 2px 2px 0 rgba(57.55, 69.04, 86.28, 20%);
margin-bottom: 10px;
cursor: pointer;
transition: all 0.2s ease;
&.actived {
background-color: rgb(7, 155, 140, 5%);
border-color: var(--el-color-primary);
}
&.dragging {
opacity: 0.5;
transform: rotate(5deg);
}
.doctor-parent-line {
margin: 0 16px;
border-bottom: 1px dashed #ddd;
}
.personal-info-container {
display: flex;
align-items: center;
justify-content: space-between;
margin: 8px 0;
padding: 0 16px;
.name-container {
display: flex;
align-items: center;
height: 18px;
.name {
color: #333;
font-size: 14px;
}
.age {
margin-left: 10px;
color: #666;
font-size: 14px;
}
}
}
}
.main-info-container {
display: flex;
align-items: center;
justify-content: space-between;
height: 32px;
margin: 7px 0;
padding: 0 16px;
margin-right: 48px;
position: relative;
.patient-tag {
position: absolute;
top: -7px;
right: -48px;
font-size: 14px;
padding: 2px 8px;
border-radius: 4px;
&.blue-tag {
background-color: #1890ff;
color: white;
}
&.green-tag {
background-color: #52c41a;
color: white;
}
}
}
</style>

View File

@@ -67,7 +67,9 @@
</el-card>
<el-card style="width: 60%">
<div>
<el-button size="default" type="primary" @click="openAddTprDialog">新增</el-button>
<el-button size="default" type="primary" @click="openAddTprDialog"
>新增</el-button
>
</div>
<div class="business-temperature-sheet" style="width: 60%">
<div>
@@ -131,7 +133,7 @@
@close="closePatientDetialDialog"
/>
<!-- </div> -->
<iframe id="printIframe" ref="printIframe" style="display: none"></iframe>
<iframe id="printIframe" ref="printIframe" style="display:none;"></iframe>
</div>
</template>
@@ -171,7 +173,7 @@ const queryParams = ref({
orgId: userStore.orgId,
});
const data1 = reactive({
const data1 = reactive({
patientInfo: {},
grParamBOS: {
age: '',
@@ -190,10 +192,10 @@ const data1 = reactive({
total: '',
hospDate: '',
operaDate: '',
outdate: '',
outdate: ''
},
rows: [],
types: [],
types: []
});
const patientData = ref({});
const integerPoints = [2, 6, 10, 14, 18, 22];
@@ -266,7 +268,7 @@ function init1(data) {
console.log('体温单初始化', data);
const inDate = data.grParamBOS.hospDate;
const outdate = data.grParamBOS.outdate;
week.value = Math.floor(dateDiff(inDate, outdate) / 10);
week.value = Math.floor(dateDiff(inDate, outdate) / 7);
setTemperatureComp(data);
}
@@ -274,8 +276,6 @@ function init1(data) {
* 点击患者列表行 获取患者体温单数据
*/
function viewPatient(row) {
console.log('1232312123221231');
patientInfo.value = row;
console.log('点击患者列表行 获取患者体温单数据', row);
chargeLoading.value = true;
@@ -375,7 +375,7 @@ function getSignsCharts() {
function getPatientList() {}
// 体温单控件数据设置
function setTemperatureComp(data) {
console.log(JSON.stringify(), '体温单控件数据设置');
console.log(data,'体温单控件数据设置');
if (data !== undefined) {
inputData.value = data;
}
@@ -434,12 +434,12 @@ function sliceData(data) {
const datas = cloneDeep(data);
datas.rows = rows;
datas.types = types;
console.log(datas, '666666666666666666');
console.log(datas,"666666666666666666")
return datas;
}
// 计算时间差
function dateDiff(start, end) {
let diffTime = start ? moment(new Date()).diff(moment(start.substring(0, 10))) / 1000 : start;
let diffTime = start ? moment(new Date()).diff(moment(start.substring(0, 10))) / 1000 :start;
if (end) {
diffTime = moment(end.substring(0, 10)).diff(moment(start.substring(0, 10))) / 1000;
}
@@ -475,45 +475,39 @@ function printPage() {
clone.style.transformOrigin = 'top left';
clone.style.width = 'calc(210mm * 1.11)';
clone.style.height = 'calc(297mm * 1.11)';
clone.style.marginLeft = '50px';
clone.style.marginLeft = '50px';
// 插入到 body 中以便 html2pdf 渲染
document.body.appendChild(clone);
// 设置 html2pdf 配置
const opt = {
margin: 0,
filename: '体温单.pdf',
image: { type: 'jpeg', quality: 1 },
html2canvas: { scale: 2, useCORS: true }, // 启用跨域资源支持
jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' },
pagebreak: { mode: ['avoid-all'] },
margin: 0,
filename: '体温单.pdf',
image: { type: 'jpeg', quality: 1 },
html2canvas: { scale: 2, useCORS: true }, // 启用跨域资源支持
jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' },
pagebreak: { mode: ['avoid-all'] },
onclone: (clonedDoc) => {
const chart = clonedDoc.getElementById(clone.id);
if (chart) {
chart.style.width = '210mm'; // 强制 A4 宽度
chart.style.margin = '0 auto';
}
},
}
};
// 导出为 PDF 并打印
html2pdf()
.from(clone)
.set(opt)
.toPdf()
.get('pdf')
.then(function (pdf) {
pdf.autoPrint(); // 自动打印
window.open(pdf.output('bloburl'), '_blank'); // 在新窗口打开 PDF以便用户确认
})
.finally(() => {
document.body.removeChild(clone); // 清理临时元素
});
html2pdf().from(clone).set(opt).toPdf().get('pdf').then(function (pdf) {
pdf.autoPrint(); // 自动打印
window.open(pdf.output('bloburl'), '_blank'); // 在新窗口打开 PDF以便用户确认
}).finally(() => {
document.body.removeChild(clone); // 清理临时元素
});
}
// 转化时间
function formatDateTo(dateStr) {
const [formattedDate, timePartWithSeconds] = dateStr ? dateStr.split('T') : ['', ''];
const [formattedDate, timePartWithSeconds] = dateStr ? dateStr.split('T'): ['', ''];
const [formattedHour, minutePart] = timePartWithSeconds.split(':');
const formattedTime = `${formattedHour}:${minutePart}`;
@@ -586,7 +580,7 @@ function formatHourTimes(dateStr, temperaturePulses) {
* 打开体征录入
*/
function openAddTprDialog() {
patientData.value = patientInfo.value;
patientData.value = patientInfo.value
openAddTpr.value = true;
// patientId.value = row.id;
nextTick(() => {
@@ -639,4 +633,4 @@ function closePatientDetialDialog(str) {
max-height: 270mm;
overflow: hidden;
}
</style>
</style>

View File

@@ -1,42 +0,0 @@
import request from '@/utils/request';
// 查询诊疗项目列表
export function getTemperatureType(data) {
return request({
url: '/document/definition/getDefinitionId',
method: 'get',
params: data,
});
}
// 根据时间查询体温单数据
export function getTemperatureHistory(data) {
return request({
url: '/document/record/getRecordByEncounterIdAndTimeList',
method: 'get',
params: data,
});
}
// 体温单保存
export function addRecord(data) {
return request({
url: '/document/record/saveOrUpdateRecord',
method: 'post',
data,
});
}
// 体温单图表展示
export function temChar(data) {
return request({
url: '/document/record/temperature-chart',
method: 'get',
params: data,
});
}
export function getPatientList(queryParams) {
return request({
url: '/reg-doctorstation/advice-manage/reg-patient-zk',
method: 'get',
params: queryParams,
});
}

View File

@@ -1,755 +0,0 @@
<template>
<div style="display: flex">
<el-button type="primary" style="margin-left: 20px" @click="increaseAdd('0')"
>变更体温单</el-button
>
<!-- <el-button type="primary" style="margin-left: 20px" @click="increaseAdd('1')">修改</el-button> -->
<!-- <el-button type="primary" style="margin-left: 20px" @click="increaseAdd('2')">查询</el-button> -->
</div>
<div class="main">
<template v-if="isEmpty">
<div class="empty">
<el-empty description="暂无数据" />
</div>
</template>
<template v-else>
<div class="business-temperature-sheet">
<div class="custom-tooltip">
<el-tooltip content="首页" placement="right-end">
<el-button
style="margin-left: 12px"
icon="Upload"
size="default"
type="primary"
@click="toFirst"
/>
</el-tooltip>
<el-tooltip content="上一页" placement="right-end">
<el-button
style="margin-left: 12px; margin-top: 15px"
icon="ArrowUpBold"
size="default"
type="primary"
@click="lastWeek"
/>
</el-tooltip>
<el-tooltip content="下一页" placement="right-end">
<el-button
style="margin-left: 12px; margin-top: 15px"
icon="ArrowDown"
size="default"
type="primary"
@click="nextWeek"
/>
</el-tooltip>
<el-tooltip content="尾页" placement="right-end">
<el-button
style="margin-left: 12px; margin-top: 15px"
icon="Download"
size="default"
type="primary"
@click="toEnd"
/>
</el-tooltip>
<el-tooltip content="打印本页" placement="right-end">
<el-button
style="margin-left: 12px; margin-top: 15px"
icon="Printer"
size="default"
type="primary"
@click="printPage"
/>
</el-tooltip>
</div>
</div>
<div class="sheet">
<div id="my_dataviz" ref="printRef" style="width: 100%; background-color: white" />
</div>
</template>
</div>
<el-drawer v-model="isOpenDraw" :direction="direction" size="100%" :with-header="false">
<template #default>
<AddAttr ref="attrRef" @onSearcTem="onSearch"></AddAttr>
</template>
<template #footer>
<div style="flex: auto">
<el-button @click="cancelClick">取消</el-button>
<el-button v-if="actionType == '2'" type="primary" @click="confirmClick">查询</el-button>
<el-button v-if="actionType !== '2'" type="primary" @click="confirmClick">保存</el-button>
</div>
</template>
</el-drawer>
</template>
<script setup>
import { init } from '@/action/nurseStation/temperatureSheet/line.js';
import { patientInfo } from '../../../inpatientDoctor/home/store/patient';
import { getVitalSignsInfo } from '../../tprChart/components/api';
import { nextTick, onMounted, watch } from 'vue';
import { getTemperatureType, temChar } from '../api/api';
import moment from 'moment';
import AddAttr from './addAttr.vue';
import cloneDeep from 'lodash.clonedeep';
import { ElMessage } from 'element-plus';
import html2pdf from 'html2pdf.js';
const attrRef = ref('');
const actionType = ref('');
const printRef = ref(null);
const isTemplate = ref(false);
const data1 = reactive({
patientInfo: {},
grParamBOS: {
age: '',
birth: '',
cwh: '',
hosNum: '',
inDate: '',
inDiagName: '',
name: '',
// 科室
deptName: '',
operaDays: '',
sex: '',
weekNo: '',
beginDate: '',
hospDays: '',
total: '',
hospDate: '',
operaDate: '',
outdate: '',
},
rows: [],
types: [],
});
const isOpenDraw = ref(false);
const week = ref(0);
const patientId = ref('');
const patientData = ref({});
const integerPoints = [2, 6, 10, 14, 18, 22];
const closestPoint = ref(null);
const patientList = ref([]);
const chargeLoading = ref(false);
const addTprDialogRef = ref(null);
const definitionId = ref(''); //体温单类型
const isEmpty = ref(true);
const objTest = {
hospDate: '2025-11-20T08:13:00',
operaDate: null,
outdate: null,
temperaturePulses: [
{
chartsSmalls: [
{
collectionMode: null,
date: '2025-11-20',
times: '10:00:00',
typeCode: '9500',
typeValue: '入科,08:13',
weekNo: 1,
orderByDateTimes: '2025-11-20 08:13:00',
id: 'c3bafb02-4609-4b53-b307-ad6767f9ba9b',
},
],
weekNo: 1,
},
{
chartsSmalls: [
{
collectionMode: 1,
date: '2025-11-20',
times: '10:00:00',
typeCode: '003',
typeValue: '36.3',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
{
collectionMode: 1,
date: '2025-11-20',
times: '10:00:00',
typeCode: '002',
typeValue: '90',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
{
collectionMode: 1,
date: '2025-11-20',
times: '10:00:00',
typeCode: '001',
typeValue: '18',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
],
weekNo: 1,
},
{
chartsSmalls: [
{
collectionMode: 1,
date: '2025-11-20',
times: '14:00:00',
typeCode: '003',
typeValue: '36.6',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
{
collectionMode: 1,
date: '2025-11-20',
times: '14:00:00',
typeCode: '002',
typeValue: '84',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
{
collectionMode: 1,
date: '2025-11-20',
times: '14:00:00',
typeCode: '001',
typeValue: '20',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
],
weekNo: 1,
},
{
chartsSmalls: [
{
collectionMode: 1,
date: '2025-11-20',
times: '18:00:00',
typeCode: '003',
typeValue: '36.5',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
{
collectionMode: 1,
date: '2025-11-20',
times: '18:00:00',
typeCode: '002',
typeValue: '88',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
{
collectionMode: 1,
date: '2025-11-20',
times: '18:00:00',
typeCode: '001',
typeValue: '20',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
],
weekNo: 1,
},
{
chartsSmalls: [
{
collectionMode: 1,
date: '2025-11-21',
times: '06:00:00',
typeCode: '003',
typeValue: '36.5',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
{
collectionMode: 1,
date: '2025-11-21',
times: '06:00:00',
typeCode: '002',
typeValue: '88',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
{
collectionMode: 1,
date: '2025-11-21',
times: '06:00:00',
typeCode: '001',
typeValue: '18',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
{
collectionMode: 1,
date: '2025-11-21',
times: '06:00:00',
typeCode: '016',
typeValue: '2',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
],
weekNo: 1,
},
{
chartsSmalls: [
{
collectionMode: 1,
date: '2025-11-21',
times: '10:00:00',
typeCode: '003',
typeValue: '36.4',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
{
collectionMode: 1,
date: '2025-11-21',
times: '10:00:00',
typeCode: '002',
typeValue: '86',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
{
collectionMode: 1,
date: '2025-11-21',
times: '10:00:00',
typeCode: '001',
typeValue: '18',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
],
weekNo: 1,
},
{
chartsSmalls: [
{
collectionMode: 1,
date: '2025-11-21',
times: '14:00:00',
typeCode: '003',
typeValue: '36.5',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
{
collectionMode: 1,
date: '2025-11-21',
times: '14:00:00',
typeCode: '002',
typeValue: '82',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
{
collectionMode: 1,
date: '2025-11-21',
times: '14:00:00',
typeCode: '001',
typeValue: '18',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
],
weekNo: 1,
},
],
others: [
{
collectionMode: null,
date: '2025-11-20',
times: null,
typeCode: '030',
typeValue: '卧床',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
{
collectionMode: null,
date: '2025-11-20',
times: null,
typeCode: '009',
typeValue: '卧床',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
{
collectionMode: null,
date: '2025-11-20',
times: '14:00:00',
typeCode: '008',
typeValue: '112/54,',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
{
collectionMode: null,
date: '2025-11-20',
times: '6:00:00',
typeCode: '008',
typeValue: '110/54,',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
{
collectionMode: null,
date: '2025-11-20',
times: null,
typeCode: '011',
typeValue: '3000/22h',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
{
collectionMode: null,
date: '2025-11-20',
times: null,
typeCode: '004',
typeValue: 'C',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
{
collectionMode: null,
date: '2025-11-20',
times: null,
typeCode: '005',
typeValue: '0',
weekNo: 1,
orderByDateTimes: null,
id: null,
},
],
};
/**
* 点击患者列表行 获取患者体温单数据
*/
const inputData = ref({});
onMounted(() => {
console.log(
'onMountedonMountedonMountedonMountedonMountedonMounted========>',
JSON.stringify(patientInfo.value)
);
if (patientInfo.value) {
getTemRequset();
} else {
isEmpty.value = true;
}
});
watch(patientInfo, (newValue) => {
console.log('patientInfo========>', JSON.stringify(patientInfo.value));
isEmpty.value = false;
getTemRequset();
});
// 1.获取体温单类型
// 获取体温单类型
const getTemRequset = async () => {
const res = await getTemperatureType({ menuEnum: 4 });
//默认选中第一个
if (res?.data?.length > 0) {
const obj = res.data[0];
definitionId.value = obj.id;
viewPatient(patientInfo.value);
isTemplate.value = true;
} else {
isTemplate.value = false;
}
};
// 2.根据患者id和病历id获取详情绘制图表
function viewPatient(row = {}) {
chargeLoading.value = true;
patientId.value = row.patientId; // 接收子组件传来的数据
data1.patientInfo = row;
data1.grParamBOS.patientId = row.patientId;
data1.grParamBOS.age = row.age;
data1.grParamBOS.birth = row.birthDate;
// data1.grParamBOS.cwh = row.bedLocationId_dictText;
data1.grParamBOS.cwh = row.bedName;
data1.grParamBOS.deptName = row.wardName;
data1.grParamBOS.hosNum = row.encounterId;
data1.grParamBOS.sex = row.genderEnum_enumText;
// 入科时间存在的场合使用入科时间
data1.grParamBOS.inDate = row.admissionDate;
data1.grParamBOS.name = row.patientName;
data1.grParamBOS.operaDays = null;
data1.grParamBOS.weekNo = null;
data1.grParamBOS.beginDate = getCurrentDate();
data1.grParamBOS.hospDays = null;
data1.grParamBOS.total = null;
getSignsCharts();
}
function getSignsCharts() {
// data1.grParamBOS.hospDate =
// objTest.hospDate && objTest.hospDate.length > 10
// ? objTest.hospDate.substring(0, 10)
// : objTest.hospDate;
// data1.grParamBOS.operaDate = objTest.operaDate;
// data1.grParamBOS.outdate = objTest.outdate;
// data1.rows = objTest.temperaturePulses.map((item) => ({
// rowBOS: item.chartsSmalls,
// weekNo: item.weekNo - 1,
// }));
// data1.types = objTest.others.map((item) => ({
// ...item, // 保留其他属性
// weekNo: item.weekNo - 1, // 将 weekNo 减 1
// }));
// console.log('体温单查询this.data1', data1);
// init1(data1);
const params = {
patientId: patientId.value ?? '',
encounterId: patientInfo.value.encounterId ?? '',
definitionId: definitionId.value,
};
temChar(params).then((response) => {
console.log('体温单返回值', JSON.stringify(response));
if (response.code === 200) {
data1.grParamBOS.hospDate =
response.data.hospDate && response.data.hospDate.length > 10
? response.data.hospDate.substring(0, 10)
: response.data.hospDate;
data1.grParamBOS.operaDate = response.data.operaDate;
data1.grParamBOS.outdate = response.data.outdate;
data1.rows = response.data.temperaturePulses.map((item) => ({
rowBOS: item.chartsSmalls,
weekNo: item.weekNo - 1,
}));
data1.types = response.data.others.map((item) => ({
...item, // 保留其他属性
weekNo: item.weekNo - 1, // 将 weekNo 减 1
}));
console.log('体温单查询this.data1', data1);
init1(data1);
}
});
}
function init1(data) {
console.log('体温单初始化', data);
const inDate = data.grParamBOS.hospDate;
const outdate = data.grParamBOS.outdate;
// week.value = Math.floor(dateDiff(inDate, outdate) / 10);
week.value = Math.floor(dateDiff(inDate, outdate) / 7);
setTemperatureComp(data);
}
// 体温单控件数据设置
function setTemperatureComp(data) {
console.log(JSON.stringify(data), '体温单控件数据设置');
if (data !== undefined) {
inputData.value = data;
}
const inDate = inputData.value.grParamBOS.hospDate;
const outdate = inputData.value.grParamBOS.outdate;
const begin = moment(new Date(inDate))
.add(week.value * 7, 'day')
.format('YYYY-MM-DD HH:mm:ss');
inputData.value.grParamBOS.weekNo = week.value;
inputData.value.grParamBOS.beginDate = begin;
inputData.value.grParamBOS.hospDays = week.value * 7;
inputData.value.grParamBOS.total = Math.floor(dateDiff(inDate, outdate) / 7);
console.log('inputData============>', JSON.stringify(inputData));
init(sliceData(inputData.value));
}
function dateDiff(start, end) {
let diffTime = start ? moment(new Date()).diff(moment(start.substring(0, 10))) / 1000 : start;
if (end) {
diffTime = moment(end.substring(0, 10)).diff(moment(start.substring(0, 10))) / 1000;
}
if (diffTime > 24 * 3600) {
return Math.floor(diffTime / (24 * 3600));
} else if (diffTime > 3600) {
return '0';
} else {
return '0';
}
}
function getCurrentDate() {
// 获取当前日期
const today = new Date();
const year = today.getFullYear();
const month = (today.getMonth() + 1).toString().padStart(2, '0'); // 月份从0开始所以需要加1
const day = today.getDate().toString().padStart(2, '0');
return `${year}-${month}-${day}`; // 格式化为 YYYY-MM-DD
}
// 拆分当前周数据
function sliceData(data) {
const rows = data.rows.filter((item) => item.weekNo === week.value);
const types = data.types.filter((item) => item.weekNo === week.value);
// const datas = JSON.parse(JSON.stringify(data));
const datas = cloneDeep(data);
datas.rows = rows;
datas.types = types;
console.log(datas, '666666666666666666');
return datas;
}
function toFirst() {
week.value = 0;
setTemperatureComp();
}
function toEnd() {
week.value = inputData.value.grParamBOS.total;
setTemperatureComp();
}
function lastWeek() {
week.value--;
if (week.value < 0) {
week.value = 0;
}
setTemperatureComp();
}
function nextWeek() {
week.value = Number(week.value) + 1;
if (week.value > inputData.value.grParamBOS.total) {
week.value = inputData.value.grParamBOS.total;
}
setTemperatureComp();
}
// 新增
const increaseAdd = (type) => {
if (!patientInfo.value) {
ElMessage({
type: 'error',
message: '请选择患者',
});
return;
}
if (!isTemplate.value) {
ElMessage({
type: 'error',
message: '体温单未配置,请联系管理员',
});
return;
}
isOpenDraw.value = true;
nextTick(() => {
actionType.value = type;
if (attrRef.value) {
attrRef.value.onActionEdit(type);
}
});
};
// 打印体温单
function printPage() {
const element = printRef.value;
if (!element) {
console.error('未找到可打印的内容');
return;
}
// 创建一个克隆元素用于打印,避免修改原 DOM
const clone = element.cloneNode(true);
// 设置宽度为 A4780px ≈ 210mm高度自适应
clone.style.transform = 'scale(0.7)';
clone.style.transformOrigin = 'top left';
clone.style.width = 'calc(210mm * 1.11)';
clone.style.height = 'calc(297mm * 1.11)';
clone.style.marginLeft = '50px';
// 插入到 body 中以便 html2pdf 渲染
document.body.appendChild(clone);
// 设置 html2pdf 配置
const opt = {
margin: 0,
filename: '体温单.pdf',
image: { type: 'jpeg', quality: 1 },
html2canvas: { scale: 2, useCORS: true }, // 启用跨域资源支持
jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' },
pagebreak: { mode: ['avoid-all'] },
onclone: (clonedDoc) => {
const chart = clonedDoc.getElementById(clone.id);
if (chart) {
chart.style.width = '210mm'; // 强制 A4 宽度
chart.style.margin = '0 auto';
}
},
};
// 导出为 PDF 并打印
html2pdf()
.from(clone)
.set(opt)
.toPdf()
.get('pdf')
.then(function (pdf) {
pdf.autoPrint(); // 自动打印
window.open(pdf.output('bloburl'), '_blank'); // 在新窗口打开 PDF以便用户确认
})
.finally(() => {
document.body.removeChild(clone); // 清理临时元素
});
}
const confirmClick = () => {
attrRef.value.saveData();
};
const cancelClick = () => {
isOpenDraw.value = false;
};
// 子组件查询方法
const onSearch = (value) => {
getTemRequset();
isOpenDraw.value = false;
};
</script>
<style scoped>
.main {
height: 100%;
display: flex;
flex-direction: row;
.empty {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.business-temperature-sheet {
height: 100%;
width: 100px;
.custom-tooltip {
height: 100%;
margin-left: 10px;
margin-right: 10px;
display: flex;
flex-direction: column;
justify-content: center;
}
}
.sheet {
flex: 1;
/* background: red; */
}
}
</style>

View File

@@ -1,58 +0,0 @@
<template>
<div class="inpatientNurse-home-container">
<PatientList :selected-patient="patientInfo" :on-select="handlePatientSelect" />
<el-container>
<el-header>
<inPatientBarDoctorFold></inPatientBarDoctorFold>
</el-header>
<el-main>
<Details></Details>
</el-main>
</el-container>
</div>
</template>
<script setup>
import { computed } from 'vue';
import inPatientBarDoctorFold from '@/components/patientBar/inPatientBarDoctorFold.vue';
import Details from './compoents/details.vue';
import { patientInfo, updatePatientInfo } from '@/views/inpatientNurse/components/store/patient';
import PatientList from '@/components/PatientList/patient-list.vue';
// 处理患者选择
const handlePatientSelect = (patient) => {
updatePatientInfo(patient);
};
</script>
<style lang="scss" scoped>
.inpatientNurse-home-container {
padding-top: 10px;
display: flex;
height: 100%;
.el-container {
height: 100%;
}
.inpatientNurse-home-main {
background-color: #ffffff;
:deep(.el-header) {
padding: 0px;
margin-bottom: 0px;
}
.el-main {
padding: 0px 8px;
}
:deep(.patient-tabs) {
height: 100%;
.el-tabs__header {
margin: 0;
}
.el-tabs__content {
}
.el-tab-pane {
height: 100%;
}
}
}
}
</style>

Some files were not shown because too many files have changed in this diff Show More