临床发血退血

This commit is contained in:
wuyy 2026-09-04 18:08:45 +08:00
parent 163cfda204
commit 2e00ada8cd
6 changed files with 544 additions and 65 deletions

View File

@ -298,6 +298,24 @@ export function printReport(query?: Object) {
params: query params: query
}) })
} }
// 临床发血获取血液信息
export function queryBloodInfo(query?: Object) {
return request({
url: '/bus/bloodbank/backin/queryBloodInfo',
method: 'get',
params: query
})
}
// 临床发血退血保存数据
export function txsaveData(query?: Object) {
return request({
url: '/bus/bloodbank/backin/saveData',
method: 'post',
data: query
})
}

View File

@ -158,3 +158,17 @@ export function useAutoSize() {
return autoSize; return autoSize;
} }
/**
* 字节转 MB,保留n位小数
* @param size 字节 string|number
* @param digits 保留小数,默认2
* @returns {string} "0.03 MB"
*/
export function formatByteToMB(size: string | number, digits = 2): string {
const byte = Number(size)
if (isNaN(byte) || byte <= 0) return '0 MB'
const mb = byte / 1024 / 1024
return `${mb.toFixed(digits)} MB`
}

View File

@ -388,7 +388,8 @@
</el-row> </el-row>
</el-form> </el-form>
<el-table :data="matchTableData" border height="450" @row-click="dcRowclick" highlight-current-row> <el-table :data="matchTableData" border height="450" @row-click="dcRowclick" highlight-current-row
show-overflow-tooltip>
<el-table-column prop="apply_no" label="申请单号" align="center" /> <el-table-column prop="apply_no" label="申请单号" align="center" />
<el-table-column prop="dept_id" label="科室" align="center"> <el-table-column prop="dept_id" label="科室" align="center">
<template #default="scope"> <template #default="scope">
@ -398,7 +399,7 @@
<el-table-column prop="patient_bed" label="床号" align="center" /> <el-table-column prop="patient_bed" label="床号" align="center" />
<el-table-column prop="patient_name" label="患者姓名" align="center" /> <el-table-column prop="patient_name" label="患者姓名" align="center" />
<el-table-column prop="beinhos_id" label="住院号/ID号" align="center" /> <el-table-column prop="beinhos_id" label="住院号/ID号" align="center" />
<el-table-column prop="blood_breed" label="血液品种" align="center"> <el-table-column prop="blood_breed" label="血液品种" align="center" width="200">
<template #default="{ row }"> <template #default="{ row }">
{{bloodBreed.find(v => v.value == row.blood_breed)?.label || row.blood_breed}} {{bloodBreed.find(v => v.value == row.blood_breed)?.label || row.blood_breed}}
</template> </template>

View File

@ -0,0 +1,424 @@
/**
* @file index.vue
* @description: 临床发血退血
* @author: w
* @since: 2026-09-04
*/
<template>
<div class="box-container">
<div class="card-box toolbar">
<el-button type="primary" plain @click="searchHandle">检索</el-button>
<el-button type="primary" plain @click="addHandle">新增单据</el-button>
<el-button type="success" plain :loading="saveLoading" @click="saveHandle">保存</el-button>
<el-button type="primary" plain @click="auditHandle">审核</el-button>
<el-button type="warning" plain @click="printHandle">打印</el-button>
</div>
<el-form :model="formData" label-width="auto" class="retreat-form">
<div class="card-box retreat-info">
<div class="section-title"> 退血主信息 </div>
<div class="status">未审核</div>
<el-row :gutter="10">
<el-col :span="4">
<el-form-item label="退血单号">
<el-input v-model="formData.bill_no" disabled />
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="经手人">
<SelectTable v-model:data="formData.handle_person" :tableData="userList" placeholder="" />
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="退回日期">
<el-date-picker v-model="formData.back_date" type="datetime" value-format="YYYY-MM-DD HH:mm:ss"
format="YYYY-MM-DD HH:mm:ss" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="12">
<el-form-item label="备注">
<el-input v-model="formData.remark" />
</el-form-item>
</el-col>
</el-row>
</div>
<div class="content-row">
<div class="card-box scan-panel">
<div class="section-title">逐袋扫描</div>
<el-form-item label="血液流水号">
<el-input v-model="bloodInfo.blood_no" @keyup.enter="scanHandle" />
</el-form-item>
<el-form-item label="产品码">
<el-input v-model="bloodInfo.product_no" disabled />
</el-form-item>
<el-form-item label="血液品种">
<el-input v-model="bloodInfo.blood_breed" disabled />
</el-form-item>
<el-form-item label="血型">
<el-input v-model="bloodInfo.blood_type" disabled />
</el-form-item>
<el-form-item label="容量">
<div class="capacity-fields">
<el-input v-model="bloodInfo.capacity" disabled />
<el-input v-model="bloodInfo.unit" disabled />
</div>
</el-form-item>
<el-form-item label="有效日期">
<el-date-picker v-model="bloodInfo.valid_date" type="datetime" value-format="YYYY-MM-DD HH:mm"
format="YYYY-MM-DD HH:mm" disabled style="width:100%" />
</el-form-item>
<el-form-item label="退血原因">
<el-select v-model="reason" placeholder="请选择退血原因">
<el-option v-for="item in dictData.lctxyy" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</div>
<div class="card-box patient-panel">
<div class="section-title">患者信息</div>
<el-row :gutter="10">
<el-col :span="5">
<el-form-item label="住院号/ID号">
<el-input v-model="patientInfo.beinhos_id" disabled />
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item label="姓名">
<el-input v-model="patientInfo.patient_name" disabled />
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item label="性别">
<el-input v-model="patientInfo.patient_sex" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="5">
<el-form-item label="年龄">
<el-input v-model="patientInfo.age" disabled />
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item label="血型">
<el-input v-model="patientInfo.abo_type" disabled />
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item label="科室">
<el-select v-model="patientInfo.dept_id" placeholder="" disabled>
<el-option v-for="item in dictData.ks" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<div class="table-title">已扫描列表</div>
<el-table :data="scannedList" border height="calc(100% - 130px)" show-overflow-tooltip>
<el-table-column prop="blood_no" label="血液流水号" min-width="140" align="center" />
<el-table-column prop="product_no" label="产品码" min-width="120" align="center" />
<el-table-column prop="blood_breed" label="血液品种" min-width="120" align="center">
<template #default="{ row }">
{{bloodBreed.find(v => v.value == row.blood_breed)?.label || row.blood_breed}}
</template>
</el-table-column>
<el-table-column prop="blood_type" label="血型" width="70" align="center" />
<el-table-column prop="capacity" label="容量" width="80" align="center" />
<el-table-column prop="unit" label="单位" width="60" align="center" />
<el-table-column prop="validDate" label="有效日期" min-width="130" align="center" />
<el-table-column prop="reason" label="退血原因" min-width="120" align="center">
<template #default="{ row }">
{{dictData.lctxyy.find(v => v.value == row.reason)?.label || row.reason}}
</template>
</el-table-column>
</el-table>
</div>
</div>
</el-form>
<el-dialog title="临床发血退血检索" v-model="visible" width="1200px" :close-on-click-modal="false" @closed="handleClose">
<div class="mb10">
<el-button type="primary" @click="handleSearch">检索</el-button>
<el-button type="success" @click="handleConfirm">确认</el-button>
</div>
<!-- 检索条件区 -->
<el-form :model="searchForm" label-width="auto" class="search-form">
<el-row :gutter="10">
<el-col :span="10">
<el-form-item label="检索时间">
<div class="date-range">
<el-date-picker v-model="searchForm.stime" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
style="width: 47%" />
<span class="separator">-</span>
<el-date-picker v-model="searchForm.etime" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
style="width: 47%" />
</div>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="单号">
<el-input v-model="searchForm.applyNo" placeholder="" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-table :data="tableData" border height="450" @row-click="jsRowclick" @row-dblclick="dblClickRow"
highlight-current-row show-overflow-tooltip>
<el-table-column prop="bill_no" label="出库单号" align="center" />
<el-table-column prop="occur_date" label="退血日期" align="center" width="150" />
<el-table-column prop="handle_person" label="经手人" align="center">
<template #default="scope">
{{userList.find(v => v.value == scope.row.handle_person)?.label || scope.row.handle_person}}
</template>
</el-table-column>
<el-table-column label="总金额" prop="money" align="center" />
<el-table-column prop="beinhos_id" label="住院号/ID号" align="center" width="150" />
<el-table-column label="患者姓名" prop="patient_name" align="center" />
</el-table>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import dayjs from 'dayjs'
import { ElMessage } from 'element-plus'
import { getDictData, formatDict, dictData, useCommonDict } from '@/hooks'
import { getBloodBreed, queryBloodInfoByBloodNo } from '@/api/common'
import { queryBloodInfo, txsaveData } from '@/api/blood'
const { userList, getUserData, getServerTime, bloodBreed, getBloodList, } = useCommonDict()
import useUserStore from '@/store/modules/user'
const userInfo = useUserStore()
const bloodInfo = ref({})
const formData = ref({
handle_person: userInfo.name,
back_date: dayjs().format('YYYY-MM-DD HH:mm:ss'),
})
const reason = ref('')
const patientInfo = ref({})
const saveLoading = ref(false)
const searchForm = ref({
stime: dayjs().format('YYYY-MM-DD'),
etime: dayjs().format('YYYY-MM-DD'),
})
const scannedList = ref<Array<Record<string, string>>>([])
const visible = ref(false)
const searchHandle = () => {
getTxList()
visible.value = true
}
const saveHandle = () => {
const data = {
xkBackinMain: {
...formData.value,
input_person: userInfo.name,
input_date: dayjs().format('YYYY-MM-DD HH:mm:ss'),
},
xkBackinDetailList: scannedList.value
}
saveLoading.value = true
txsaveData(data).then(res => {
if (res.code == 0) {
ElMessage.success("保存成功!")
}
}).finally(() => {
saveLoading.value = false
})
}
const auditHandle = () => {
}
const printHandle = () => {
}
const addHandle = () => {
formData.value = {}
bloodInfo.value = {}
scannedList.value = []
}
const getTxList = () => {
searchForm.value.stime = dayjs(searchForm.value.stime).format('YYYY-MM-DD') + ' 00:00:00'
searchForm.value.etime = dayjs(searchForm.value.etime).format('YYYY-MM-DD') + ' 23:59:59'
}
const handleSearch = () => {
getTxList()
}
const handleConfirm = () => {
if (!searchForm.value.billNo) return ElMessage.warning('请输入退血单号进行检索')
}
const jsRowclick = (row) => {
if (!row) return
getBloodInfo(row)
}
const dblClickRow = (row) => {
if (!row) return
getBloodInfo(row)
visible.value = false
}
const handleClose = () => {
}
const scanHandle = () => {
if (!reason.value) return ElMessage.warning('请选择退血原因')
if (!bloodInfo.value.blood_no) return
queryBloodInfoByBloodNo({ bloodNo: bloodInfo.value.blood_no }).then(res => {
if (res.data.length) {
const row = res.data[0]
getBloodInfo(row)
}
})
}
const getBloodInfo = (row) => {
queryBloodInfo({ bloodNo: row.blood_no, productNo: row.product_no }).then(res => {
bloodInfo.value = res.data.xkBloodInfo || {}
patientInfo.value = res.data.patientInfoList[0] || {}
const row = {
blood_no: bloodInfo.value.blood_no,
product_no: bloodInfo.value.product_no,
blood_breed: bloodInfo.value.blood_breed,
blood_type: bloodInfo.value.blood_type,
capacity: bloodInfo.value.capacity,
unit: bloodInfo.value.unit,
validDate: bloodInfo.value.valid_date,
reason: reason.value,
sid: scannedList.value.length + 1,
}
scannedList.value.push(row)
bloodInfo.value.blood_no = ''
})
}
onMounted(() => {
getUserData()
getBloodList()
getDictData('ks', 'lctxyy')
})
</script>
<style scoped lang="scss">
.box-container {
display: flex;
flex-direction: column;
}
.toolbar {
flex: none;
}
.retreat-form {
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
}
.retreat-info {
position: relative;
flex: none;
}
.status {
position: absolute;
top: 34px;
right: 30px;
color: #409eff;
font-size: 18px;
font-weight: 700;
border: 2px solid #409eff;
border-radius: 5px;
padding: 10px;
}
.content-row {
flex: 1;
min-height: 0;
display: flex;
gap: 10px;
}
.scan-panel {
width: 350px;
flex: none;
}
.patient-panel {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
margin-bottom: 10px;
}
.capacity-fields {
display: flex;
gap: 5px;
width: 100%;
}
.capacity-fields .el-input:first-child {
flex: 1;
}
.capacity-fields .el-input:last-child {
width: 52px;
}
.table-title {
position: relative;
padding-left: 12px;
padding-bottom: 6px;
font-size: 15px;
font-weight: 600;
display: flex;
justify-content: space-between;
// align-items: center;
/* 左侧蓝色小竖线 */
&::before {
content: '';
position: absolute;
left: 0;
top: 2px;
bottom: 2px;
width: 4px;
height: 14px;
background-color: #409eff;
margin-right: 8px;
border-radius: 0 4px 4px 0;
}
}
.patient-panel :deep(.el-table) {
flex: 1;
min-height: 120px;
}
:deep(.el-form-item) {
margin-bottom: 8px;
}
</style>

View File

@ -592,8 +592,6 @@ import router from '@/router/index.js'
import { printBase64PDF } from '@/utils/classCom.js' import { printBase64PDF } from '@/utils/classCom.js'
import { sendWebSocketMessage } from '@/utils/webSocket.js' import { sendWebSocketMessage } from '@/utils/webSocket.js'
const userInfo = useUserStore() const userInfo = useUserStore()
const { const {
getServerTime, getServerTime,
userList, userList,
@ -606,9 +604,7 @@ const {
getDiaList, getDiaList,
loadAllDict loadAllDict
} = useCommonDict() } = useCommonDict()
const route = useRoute() const route = useRoute()
const saveLoading = ref(false) const saveLoading = ref(false)
const bloodFormRef = ref<InstanceType<typeof ElForm>>() const bloodFormRef = ref<InstanceType<typeof ElForm>>()
const queryForm = reactive({ const queryForm = reactive({
@ -618,7 +614,6 @@ const queryForm = reactive({
doctor_code: userInfo.name, doctor_code: userInfo.name,
beinhos_id: '' beinhos_id: ''
}) })
const listScope = ref('3') const listScope = ref('3')
const indicationRef = useTemplateRef('indicationRef') const indicationRef = useTemplateRef('indicationRef')
const radioChange = (val: string) => { const radioChange = (val: string) => {
@ -643,7 +638,6 @@ const radioChange = (val: string) => {
} }
getSqdList() getSqdList()
} }
const pgcolumnList = ref([ const pgcolumnList = ref([
{ label: '评估单号', prop: 'bill_no' }, { label: '评估单号', prop: 'bill_no' },
{ label: '住院号', prop: 'beinhos_id' }, { label: '住院号', prop: 'beinhos_id' },
@ -651,14 +645,11 @@ const pgcolumnList = ref([
{ label: '评估日期(24h内有效)', prop: 'assess_data', width: 200 }, { label: '评估日期(24h内有效)', prop: 'assess_data', width: 200 },
{ label: '评估人', prop: 'assess_person', width: 100, slotName: 'assess_person' }, { label: '评估人', prop: 'assess_person', width: 100, slotName: 'assess_person' },
]) ])
const tableData = ref([]) const tableData = ref([])
const dictList = ref([ const dictList = ref([
{ label: '代号', prop: 'value' }, { label: '代号', prop: 'value' },
{ label: '字典', prop: 'label' } { label: '字典', prop: 'label' }
]) ])
const xkPatientInfo = ref({}) //病人信息 const xkPatientInfo = ref({}) //病人信息
const xkTransfuseApply = ref({ const xkTransfuseApply = ref({
agreement_ink: 'Y', agreement_ink: 'Y',
@ -667,7 +658,6 @@ const xkTransfuseApply = ref({
apply_date: '', apply_date: '',
apply_medic: userInfo.name apply_medic: userInfo.name
}) //输血申请信息 }) //输血申请信息
const formRef = useTemplateRef('formRef') const formRef = useTemplateRef('formRef')
const formRules = reactive({ const formRules = reactive({
assess_bill_no: [{ required: true, message: '请选择评估单', trigger: 'change' }], assess_bill_no: [{ required: true, message: '请选择评估单', trigger: 'change' }],
@ -675,6 +665,66 @@ const formRules = reactive({
use1_date: [{ required: true, message: '请选择预定输血日期', trigger: 'change' }], use1_date: [{ required: true, message: '请选择预定输血日期', trigger: 'change' }],
dept_Type: [{ required: true, message: '请选择科室类型', trigger: 'change' }], dept_Type: [{ required: true, message: '请选择科室类型', trigger: 'change' }],
}) })
/** 数据快照,keep‑alive缓存页面,组件不会销毁;切换单据必须重写快照 */
const snapshotApply = ref<{
xkTransfuseApply: Record<string, any>
bloodList: any[]
lisProject: any[]
}>({
xkTransfuseApply: {},
bloodList: [],
lisProject: []
})
/** 更新快照:加载单据、新增单据、保存成功调用;记录当前基准状态 */
const updateSnapshot = () => {
snapshotApply.value.xkTransfuseApply = JSON.parse(JSON.stringify(xkTransfuseApply.value))
snapshotApply.value.bloodList = JSON.parse(JSON.stringify(bloodList.value))
snapshotApply.value.lisProject = JSON.parse(JSON.stringify(lisProject.value))
}
/**
* 判断表单是否存在未保存修改
* @returns true:有修改 false:无修改
*/
const isDataChanged = (): boolean => {
const currApply = JSON.parse(JSON.stringify(xkTransfuseApply.value))
const snapApply = JSON.parse(JSON.stringify(snapshotApply.value.xkTransfuseApply))
const currBlood = JSON.parse(JSON.stringify(bloodList.value))
const snapBlood = JSON.parse(JSON.stringify(snapshotApply.value.bloodList))
const currLis = JSON.parse(JSON.stringify(lisProject.value))
const snapLis = JSON.parse(JSON.stringify(snapshotApply.value.lisProject))
const applyStr = JSON.stringify(currApply)
const snapApplyStr = JSON.stringify(snapApply)
const bloodStr = JSON.stringify(currBlood)
const snapBloodStr = JSON.stringify(snapBlood)
const lisStr = JSON.stringify(currLis)
const snapLisStr = JSON.stringify(snapLis)
return applyStr !== snapApplyStr || bloodStr !== snapBloodStr || lisStr !== snapLisStr
}
/** 通用校验函数:审核/取消审核/作废共用,有变更直接返回true提示拦截 */
const checkDataChangeBeforeOperate = (): boolean => {
if (isDataChanged()) {
ElMessage.warning('表单数据已修改,请先保存后再操作')
return true
}
return false
}
// keep‑alive激活钩子:缓存页面,切回页面,如果当前有单据,重新刷新快照,防止快照为旧单据数据
onActivated(() => {
const currBill = xkTransfuseApply.value?.bill_no
const snapBill = snapshotApply.value?.xkTransfuseApply?.bill_no
if (currBill && currBill !== snapBill) {
nextTick(() => updateSnapshot())
}
})
// 根据单据状态获取单元格样式(背景色+白色文字) // 根据单据状态获取单元格样式(背景色+白色文字)
const cellStyle = ({ row, column, rowIndex, columnIndex }) => { const cellStyle = ({ row, column, rowIndex, columnIndex }) => {
if (column.label == '单据状态') { if (column.label == '单据状态') {
@ -684,29 +734,23 @@ const cellStyle = ({ row, column, rowIndex, columnIndex }) => {
fontWeight: 500 fontWeight: 500
} }
} }
} }
const getBillStatusInfo = (code: string) => { const getBillStatusInfo = (code: string) => {
const statusList = dictData.value?.billApplyStatus ?? [] const statusList = dictData.value?.billApplyStatus ?? []
const target = statusList.find(item => item.value == code) const target = statusList.find(item => item.value == code)
if (target) { if (target) {
return { label: target.label, color: target.remark } return { label: target.label, color: target.remark }
} }
return { label: '未审核', color: '#909399' } return { label: '未审核', color: '#909399' }
} }
// 血液品种列表 // 血液品种列表
const bloodList = ref([]) const bloodList = ref([])
const orderList = ref([]) // 输血申请单列表 const orderList = ref([]) // 输血申请单列表
const orderRef = useTemplateRef('orderRef') const orderRef = useTemplateRef('orderRef')
// 血液品种弹窗相关 // 血液品种弹窗相关
const bloodDialogVisible = ref(false) const bloodDialogVisible = ref(false)
const editIndex = ref(-1) const editIndex = ref(-1)
const bloodForm = reactive({}) const bloodForm = reactive({})
// 血液品种表单验证规则 // 血液品种表单验证规则
const bloodFormRules = reactive({ const bloodFormRules = reactive({
blood_breed: [{ required: true, message: '请输入血液品种', trigger: 'blur' }], blood_breed: [{ required: true, message: '请输入血液品种', trigger: 'blur' }],
@ -730,14 +774,11 @@ const bloodFormRules = reactive({
intent: [{ required: true, message: '请选择输血目的', trigger: 'change' }], intent: [{ required: true, message: '请选择输血目的', trigger: 'change' }],
causalis: [{ required: true, message: '请选择输血指征', trigger: 'change' }], causalis: [{ required: true, message: '请选择输血指征', trigger: 'change' }],
}) })
//流程节点 //流程节点
const processList = ref([ const processList = ref([
{ statusName: '开单', occurDate: '' }, { statusName: '开单', occurDate: '' },
{ statusName: '上级医生审核', occurDate: '' }, { statusName: '上级医生审核', occurDate: '' },
{ statusName: '输血科审核', occurDate: '' }, { statusName: '输血科审核', occurDate: '' },
// { statusName: '医务部审核', occurDate: '' },
// { statusName: '输血科审核', occurDate: '' },
{ statusName: '血型复核', occurDate: '' }, { statusName: '血型复核', occurDate: '' },
{ statusName: '交叉配血', occurDate: '' }, { statusName: '交叉配血', occurDate: '' },
{ statusName: '临床发血', occurDate: '' }, { statusName: '临床发血', occurDate: '' },
@ -750,7 +791,6 @@ const currentStepIndex = computed(() => {
} }
return list.length - 1 return list.length - 1
}) })
// 节点状态类名 // 节点状态类名
const getNodeStatusClass = (item, index: number) => { const getNodeStatusClass = (item, index: number) => {
const currIdx = currentStepIndex.value const currIdx = currentStepIndex.value
@ -799,11 +839,9 @@ const handleConfirm = () => {
visible.value = false visible.value = false
selectRow.value = {} selectRow.value = {}
} }
const handleRowClick = (row) => { const handleRowClick = (row) => {
selectRow.value = row selectRow.value = row
} }
const dblClickRow = (row) => { const dblClickRow = (row) => {
getQueryOneInfo(row.bill_no) getQueryOneInfo(row.bill_no)
visible.value = false visible.value = false
@ -819,7 +857,6 @@ const getList = () => {
jsTabdeList.value = res.data jsTabdeList.value = res.data
}) })
} }
// 查询申请单列表 // 查询申请单列表
const getSqdList = () => { const getSqdList = () => {
querysqList(queryForm).then((res) => { querysqList(queryForm).then((res) => {
@ -834,7 +871,6 @@ const getSqdList = () => {
} }
}) })
} }
const rowClick = (row) => { const rowClick = (row) => {
getQueryOneInfo(row.bill_no) getQueryOneInfo(row.bill_no)
} }
@ -848,12 +884,12 @@ const addHandle = () => {
assess_bill_no: '' assess_bill_no: ''
} }
bloodList.value = [] bloodList.value = []
getServerTime().then(time => { getServerTime().then(time => {
xkTransfuseApply.value.apply_date = time xkTransfuseApply.value.apply_date = time
xkTransfuseApply.value.use1_date = time xkTransfuseApply.value.use1_date = time
nextTick(() => { nextTick(() => {
formRef.value?.clearValidate() formRef.value?.clearValidate()
updateSnapshot() //新增单据更新快照
}) })
}) })
processList.value = [ processList.value = [
@ -876,10 +912,11 @@ const shForm = ref({
const shLoading = ref(false) const shLoading = ref(false)
const reviewCommentsRef = useTemplateRef('reviewCommentsRef') const reviewCommentsRef = useTemplateRef('reviewCommentsRef')
// 审核 // 审核
// 如果是001 代表是临床科室,此时需要调用“上级医生审核” 审核接口,
// 如果是002 代表是输血科室,调用“申请单审核前校验”
const reviewHandle = () => { const reviewHandle = () => {
if (!xkTransfuseApply.value.bill_no) return ElMessage.warning('该单据还未保存!') if (!xkTransfuseApply.value.bill_no) return ElMessage.warning('该单据还未保存!')
// 变更校验,有修改直接拦截
if (checkDataChangeBeforeOperate()) return
shLoading.value = true shLoading.value = true
getDeptType({ userId: userInfo.name }).then(res => { getDeptType({ userId: userInfo.name }).then(res => {
if (res.data == '001') { if (res.data == '001') {
@ -905,7 +942,6 @@ const handleSh = () => {
handleReviewConfirm() handleReviewConfirm()
} }
} }
const cancelreviewHandle = () => { const cancelreviewHandle = () => {
if (!xkTransfuseApply.value.bill_no) return ElMessage.warning('该单据还未保存!') if (!xkTransfuseApply.value.bill_no) return ElMessage.warning('该单据还未保存!')
getDeptType({ userId: userInfo.name }).then(res => { getDeptType({ userId: userInfo.name }).then(res => {
@ -934,13 +970,11 @@ const cancelreviewHandle = () => {
}) })
}) })
} }
//作废 //作废
const reason = ref('') const reason = ref('')
const reasonText = ref('') const reasonText = ref('')
const zfShow = ref(false) const zfShow = ref(false)
const invalidateHandle = () => { const invalidateHandle = () => {
// sqdzfyy
if (!xkTransfuseApply.value.bill_no) return ElMessage.warning('该单据还未保存!') if (!xkTransfuseApply.value.bill_no) return ElMessage.warning('该单据还未保存!')
zfShow.value = true zfShow.value = true
} }
@ -979,7 +1013,6 @@ const handleReviewConfirm = () => {
} }
}) })
} }
//审核意见 //审核意见
const shClose = () => { const shClose = () => {
shShow.value = false shShow.value = false
@ -990,7 +1023,6 @@ const shClose = () => {
} }
} }
const printLoading = ref(false) const printLoading = ref(false)
//打印输血评估单 //打印输血评估单
const printHandle = (name: string) => { const printHandle = (name: string) => {
printLoading.value = true printLoading.value = true
@ -1017,7 +1049,6 @@ const goHistoryBlood = () => {
} }
}) })
} }
// 打开新增弹窗 // 打开新增弹窗
const openBloodDialog = () => { const openBloodDialog = () => {
editIndex.value = -1 editIndex.value = -1
@ -1025,7 +1056,6 @@ const openBloodDialog = () => {
bloodForm.apply_bloodtype = xkPatientInfo.value.abo bloodForm.apply_bloodtype = xkPatientInfo.value.abo
bloodDialogVisible.value = true bloodDialogVisible.value = true
} }
// 重置弹窗表单 // 重置弹窗表单
const resetBloodForm = () => { const resetBloodForm = () => {
if (bloodFormRef.value) { if (bloodFormRef.value) {
@ -1034,7 +1064,6 @@ const resetBloodForm = () => {
// 删除所有key,清空表单 // 删除所有key,清空表单
Object.keys(bloodForm).forEach(key => delete bloodForm[key]) Object.keys(bloodForm).forEach(key => delete bloodForm[key])
} }
// 编辑血液品种 // 编辑血液品种
const editBlood = (row: any, index: number) => { const editBlood = (row: any, index: number) => {
editIndex.value = index editIndex.value = index
@ -1044,7 +1073,6 @@ const editBlood = (row: any, index: number) => {
Object.assign(bloodForm, JSON.parse(JSON.stringify(row))) Object.assign(bloodForm, JSON.parse(JSON.stringify(row)))
bloodDialogVisible.value = true bloodDialogVisible.value = true
} }
// 删除单条血液品种 // 删除单条血液品种
const deleteSingleBlood = (index: number) => { const deleteSingleBlood = (index: number) => {
ElMessageBox.confirm( ElMessageBox.confirm(
@ -1088,7 +1116,6 @@ const blHandle = () => {
} }
}) })
} }
//保存申请单 //保存申请单
const handleSubmit = async () => { const handleSubmit = async () => {
formRef.value.validate((valid) => { formRef.value.validate((valid) => {
@ -1102,7 +1129,6 @@ const handleSubmit = async () => {
} }
saveLoading.value = true saveLoading.value = true
const tempPatient = { ...xkPatientInfo.value, beinhos_id: xkTransfuseApply.value.beinhos_id } const tempPatient = { ...xkPatientInfo.value, beinhos_id: xkTransfuseApply.value.beinhos_id }
const data = { const data = {
transfuseApplyInfoOne: { transfuseApplyInfoOne: {
xkPatientInfo: tempPatient, xkPatientInfo: tempPatient,
@ -1116,7 +1142,6 @@ const handleSubmit = async () => {
}), }),
xkTransfuseApplyTestitemList: lisProject.value, xkTransfuseApplyTestitemList: lisProject.value,
} }
// 自体血校验 // 自体血校验
checkSelfBlood({ beinhos_id: xkTransfuseApply.value.beinhos_id }).then((res) => { checkSelfBlood({ beinhos_id: xkTransfuseApply.value.beinhos_id }).then((res) => {
if (res.code == 0) { if (res.code == 0) {
@ -1180,7 +1205,6 @@ const handleSubmit = async () => {
//输血指征校验弹窗确定 //输血指征校验弹窗确定
const indicationComfirm = (arr) => { const indicationComfirm = (arr) => {
const tempPatient = { ...xkPatientInfo.value, beinhos_id: xkTransfuseApply.value.beinhos_id } const tempPatient = { ...xkPatientInfo.value, beinhos_id: xkTransfuseApply.value.beinhos_id }
const data = { const data = {
transfuseApplyInfoOne: { transfuseApplyInfoOne: {
xkPatientInfo: tempPatient, xkPatientInfo: tempPatient,
@ -1195,7 +1219,6 @@ const indicationComfirm = (arr) => {
xkTransfuseApplyTestitemList: lisProject.value, xkTransfuseApplyTestitemList: lisProject.value,
xkTransfuseApplyCausalisList: arr xkTransfuseApplyCausalisList: arr
} }
saveApplyInfo(data).then((res) => { saveApplyInfo(data).then((res) => {
if (res.code == 0 && res.data) { if (res.code == 0 && res.data) {
getQueryOneInfo(res.data) getQueryOneInfo(res.data)
@ -1205,11 +1228,9 @@ const indicationComfirm = (arr) => {
} }
}) })
} }
const sendMsg = (billNo: string) => { const sendMsg = (billNo: string) => {
const arr = bloodList.value.map(item => item.blood_breed) const arr = bloodList.value.map(item => item.blood_breed)
const breedMap = new Map(bloodBreed.value.map(v => [v.value, v.label])); const breedMap = new Map(bloodBreed.value.map(v => [v.value, v.label]));
const bloodText = arr.map(item => breedMap.get(item) ?? item).join('、'); const bloodText = arr.map(item => breedMap.get(item) ?? item).join('、');
const data = { const data = {
type: "APPLY_NOTICE", type: "APPLY_NOTICE",
@ -1230,6 +1251,10 @@ const getQueryOneInfo = (bill_no: string) => {
xkTransfuseApply.value = res.data.transfuseApplyInfoOne.xkTransfuseApply xkTransfuseApply.value = res.data.transfuseApplyInfoOne.xkTransfuseApply
bloodList.value = res.data.xkTransfuseApplyBloodbreedList bloodList.value = res.data.xkTransfuseApplyBloodbreedList
lisProject.value = mergeLisTestItem(lisProject.value, res.data.xkTransfuseApplyTestitemList) lisProject.value = mergeLisTestItem(lisProject.value, res.data.xkTransfuseApplyTestitemList)
// 回显单据,更新快照
nextTick(() => {
updateSnapshot()
})
}) })
//获取申请单状态 //获取申请单状态
bloodCloseLoop({ billNo: bill_no }).then(res => { bloodCloseLoop({ billNo: bill_no }).then(res => {
@ -1238,15 +1263,16 @@ const getQueryOneInfo = (bill_no: string) => {
} }
}) })
} }
//获取患者信息 //获取患者信息
const getInfo = (billNo: string) => { const getInfo = (billNo: string) => {
//PJD2026061623
getPatInfo({ bill_no: billNo }).then((res) => { getPatInfo({ bill_no: billNo }).then((res) => {
xkPatientInfo.value = res.data.transfuseApplyInfoOne.xkPatientInfo xkPatientInfo.value = res.data.transfuseApplyInfoOne.xkPatientInfo
xkTransfuseApply.value = res.data.transfuseApplyInfoOne.xkTransfuseApply xkTransfuseApply.value = res.data.transfuseApplyInfoOne.xkTransfuseApply
bloodList.value = res.data.xkTransfuseApplyBloodbreedList || [] bloodList.value = res.data.xkTransfuseApplyBloodbreedList || []
lisProject.value = mergeLisTestItem(lisProject.value, res.data.xkTransfuseApplyTestitemList) lisProject.value = mergeLisTestItem(lisProject.value, res.data.xkTransfuseApplyTestitemList)
nextTick(() => {
updateSnapshot() //路由跳转加载单据更新快照
})
}) })
} }
//合并检查结果 //合并检查结果
@ -1262,12 +1288,10 @@ const mergeLisTestItem = (oldList: Array<any>, apiList: Array<any>) => {
} }
}) })
} }
const oldMap = new Map<string, any>() const oldMap = new Map<string, any>()
oldList.forEach(item => { oldList.forEach(item => {
if (item?.item_name) oldMap.set(item.item_name, item) if (item?.item_name) oldMap.set(item.item_name, item)
}) })
return apiList.map(apiItem => { return apiList.map(apiItem => {
if (!apiItem || !apiItem.item_name) { if (!apiItem || !apiItem.item_name) {
return { return {
@ -1302,7 +1326,6 @@ const mergeLisTestItem = (oldList: Array<any>, apiList: Array<any>) => {
} }
}) })
} }
// 回显时拆分 年龄 + 单位 // 回显时拆分 年龄 + 单位
const splitAge = (ageStr: string) => { const splitAge = (ageStr: string) => {
const unitList = dictData.value.nldw.map(item => item.value) const unitList = dictData.value.nldw.map(item => item.value)
@ -1318,9 +1341,6 @@ const splitAge = (ageStr: string) => {
xkPatientInfo.value.age = age xkPatientInfo.value.age = age
xkPatientInfo.value.nldw = unit xkPatientInfo.value.nldw = unit
} }
const pgList = ref([]) const pgList = ref([])
//获取评估申请单 //获取评估申请单
const getPgList = () => { const getPgList = () => {
@ -1328,7 +1348,6 @@ const getPgList = () => {
pgList.value = res.data pgList.value = res.data
}) })
} }
let needClearState = false // 标记是否需要清理state let needClearState = false // 标记是否需要清理state
// 加载单据 // 加载单据
const loadBillInfo = () => { const loadBillInfo = () => {
@ -1344,15 +1363,12 @@ const loadBillInfo = () => {
const getPgInfo = (row) => { const getPgInfo = (row) => {
getInfo(row.bill_no) getInfo(row.bill_no)
} }
//手术名称 //手术名称
const operationList = ref([]) const operationList = ref([])
const operationColumn = [ const operationColumn = [
{ label: '手术代号', prop: 'icd_code' }, { label: '手术代号', prop: 'icd_code' },
{ label: '手术名称', prop: 'oper_name', width: 200 }, { label: '手术名称', prop: 'oper_name', width: 200 },
// { label: '手术级别', prop: 'oper_level' },
] ]
const getOperationInfo = (row) => { const getOperationInfo = (row) => {
if (row.oper_level) { if (row.oper_level) {
switch (row.oper_level) { switch (row.oper_level) {
@ -1372,7 +1388,6 @@ const getOperationInfo = (row) => {
break; break;
} }
} }
} }
//手术名称 //手术名称
const getSxList = () => { const getSxList = () => {
@ -1380,8 +1395,6 @@ const getSxList = () => {
operationList.value = res.rows operationList.value = res.rows
}) })
} }
onMounted(() => { onMounted(() => {
loadAllDict() loadAllDict()
getServerTime().then(time => { getServerTime().then(time => {
@ -1393,10 +1406,8 @@ onMounted(() => {
getSqdList() getSqdList()
loadBillInfo() loadBillInfo()
}) })
// 监听路由变化 // 监听路由变化
watch(() => route.fullPath, loadBillInfo) watch(() => route.fullPath, loadBillInfo)
// 页面关闭/切换标签时再清空state,不影响同路由二次跳转 // 页面关闭/切换标签时再清空state,不影响同路由二次跳转
onBeforeUnmount(() => { onBeforeUnmount(() => {
if (needClearState) { if (needClearState) {
@ -1405,6 +1416,7 @@ onBeforeUnmount(() => {
}) })
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.box-container { .box-container {
display: flex; display: flex;

View File

@ -28,6 +28,9 @@
{{ row.report_no }} {{ row.report_no }}
</div> </div>
</template> </template>
<template #report_size="{ row }">
{{ formatByteToMB(row.report_size) }}
</template>
<template #action="{ row }"> <template #action="{ row }">
<el-button type="primary" text @click="handleEdit(row)">编辑</el-button> <el-button type="primary" text @click="handleEdit(row)">编辑</el-button>
<el-button type="primary" text @click="handleDel(row)">删除</el-button> <el-button type="primary" text @click="handleDel(row)">删除</el-button>
@ -41,8 +44,9 @@
<el-input v-model="form.report_name" placeholder="请输入文件名" /> <el-input v-model="form.report_name" placeholder="请输入文件名" />
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-upload ref="uploadRef" :limit="1" accept=".jrxml" action="#" :on-change="changeFile" :file-list="fileList" <el-upload ref="uploadRef" :limit="1" accept=".jrxml" :action="uploadUrl" :headers="headers"
:on-exceed="handleExceed" :on-remove="() => { fileList = [] }" :auto-upload="false" drag> :on-change="changeFile" :file-list="fileList" :on-exceed="handleExceed" :on-remove="() => { fileList = [] }"
drag>
<el-icon class="el-icon--upload"><upload-filled /></el-icon> <el-icon class="el-icon--upload"><upload-filled /></el-icon>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div> <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<template #tip> <template #tip>
@ -65,15 +69,19 @@
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { queryList, addTemplate, updateTemplate, delTemplate } from '@/api/system/template' import { queryList, addTemplate, updateTemplate, delTemplate } from '@/api/system/template'
import { getDictData, formatDict, dictData, useCommonDict } from '@/hooks' import { getDictData, formatDict, dictData, useCommonDict } from '@/hooks'
import { formatByteToMB } from '@/utils/classCom'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
const { userList, getUserData, } = useCommonDict() const { userList, getUserData, } = useCommonDict()
import Download from '@/plugins/download' import Download from '@/plugins/download'
import { getToken } from '@/utils/auth'
const searchForm = reactive({}) const searchForm = reactive({})
const fileList = ref([]) const fileList = ref([])
const open = ref(false) const open = ref(false)
const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload")
const headers = ref({ Authorization: "Bearer " + getToken() })
const form = ref({}) const form = ref({})
const rules = ref({ const rules = ref({
report_name: [ report_name: [
@ -90,6 +98,8 @@ const columns = ref([
{ label: '模板ID', prop: 'report_id', align: 'center', visible: true, width: 100 }, { label: '模板ID', prop: 'report_id', align: 'center', visible: true, width: 100 },
{ label: '模板名称', prop: 'report_name', align: 'center', visible: true, }, { label: '模板名称', prop: 'report_name', align: 'center', visible: true, },
{ label: '模板文件', prop: 'report_no', align: 'center', visible: true, slot: 'report_no' }, { label: '模板文件', prop: 'report_no', align: 'center', visible: true, slot: 'report_no' },
{ label: '文件大小', prop: 'report_size', align: 'center', visible: true, slot: 'report_size' },
{ label: '修改时间', prop: 'update_time', align: 'center', visible: true, },
{ label: '创建时间', prop: 'create_time', align: 'center', visible: true, }, { label: '创建时间', prop: 'create_time', align: 'center', visible: true, },
]) ])
const tableConfig = ref({ const tableConfig = ref({