1686 lines
57 KiB
Vue
Raw Normal View History

2026-07-03 18:04:09 +08:00
/**
* @file index.vue
* @description: 输血申请
* @author: w
* @since: 2026-06-30
*/
2026-06-09 18:00:10 +08:00
<template>
2026-06-17 17:49:37 +08:00
<div class="box-container">
2026-06-12 18:01:21 +08:00
<!-- 顶部工具栏 -->
<div class="toolbar">
2026-07-10 17:40:50 +08:00
<el-button type="primary" plain @click="openJsDialog">检索</el-button>
<el-button type="primary" plain @click="addHandle">新增</el-button>
<el-button type="success" plain @click="handleSubmit" :loading="saveLoading">保存</el-button>
2026-07-14 18:05:18 +08:00
<el-button @click="blHandle">电子病历</el-button>
2026-07-10 17:40:50 +08:00
<el-button :loading="shLoading" @click="reviewHandle">审核</el-button>
<el-button type="danger" plain @click="cancelreviewHandle">取消审核</el-button>
<el-button type="info" plain @click="invalidateHandle">作废</el-button>
2026-07-24 17:37:42 +08:00
<el-button type="warning" :disabled="!xkTransfuseApply.bill_no" plain
@click="printHandle('BLOOD_APPLY')">打印输血申请单</el-button>
2026-07-14 18:05:18 +08:00
<el-button @click="goHistoryBlood">患者输血历史</el-button>
2026-07-23 17:57:58 +08:00
<el-button type="warning" :disabled="!xkTransfuseApply.bill_no" plain :loading="printLoading"
2026-07-24 17:37:42 +08:00
@click="printHandle('LARGE_APPLY')">打印大量输血审批单</el-button>
2026-07-23 17:57:58 +08:00
<el-button type="warning" :disabled="!xkTransfuseApply.assess_bill_no" plain :loading="printLoading"
2026-07-24 17:37:42 +08:00
@click="printHandle('INFORMED_CONSENT')">打印输血知情同意书</el-button>
2026-06-09 18:00:10 +08:00
</div>
2026-06-12 18:01:21 +08:00
<!-- 主体区域 左2 : 右1 -->
2026-06-09 18:00:10 +08:00
<div class="main-content">
2026-07-14 18:05:18 +08:00
<!-- 左侧区域 占2份left-wrap -->
2026-06-12 18:01:21 +08:00
<div class="left-wrap">
2026-07-16 18:09:10 +08:00
<el-form ref="formRef" label-width="auto" size="small" class="blood-transfusion-form" :model="xkTransfuseApply"
:rules="formRules" :show-message="false"
2026-07-10 17:40:50 +08:00
:disabled="xkTransfuseApply.bill_stasus && xkTransfuseApply.bill_stasus != 'A'">
2026-07-14 18:05:18 +08:00
<div class="card-box base-info-card">
<div class="section-title">
<div>患者信息</div>
</div>
<div class="base-info-content">
<div class="base-info">
<div class="info-row">
<div class="info-item">
<span class="label">住院号:</span>
2026-07-23 17:57:58 +08:00
<span class="value">{{ xkPatientInfo.beinhos_id }}</span>
2026-07-14 18:05:18 +08:00
</div>
<div class="info-item">
<span class="label">姓名:</span>
<span class="value">{{ xkPatientInfo.patient_name }}</span>
</div>
<div class="info-item">
<span class="label">性别:</span>
<span class="value">{{ xkPatientInfo.patient_sex }}</span>
</div>
<div class="info-item">
<span class="label">年龄:</span>
<span class="value">{{ xkPatientInfo.age }}</span>
</div>
<div class="info-item">
<span class="label">属地:</span>
<span class="value">{{ formatDict(xkPatientInfo.apanage, 'sd') }}</span>
</div>
<div class="info-item">
<span class="label">病区:</span>
<span class="value ellipsis-one-line" :title="formatDict(xkTransfuseApply.zone_id, 'bq')">
{{ formatDict(xkTransfuseApply.zone_id, 'bq') }}</span>
</div>
<div class="info-item">
<span class="label">科室:</span>
<span class="value ellipsis-one-line" :title="formatDict(xkTransfuseApply.dept_id, 'ks')">
{{ formatDict(xkTransfuseApply.dept_id, 'ks') }}</span>
</div>
<div class="info-item">
<span class="label">床位号:</span>
<span class="value">{{ xkTransfuseApply.patient_bed }}</span>
</div>
<div class="info-item">
<span class="label">临床诊断:</span>
<span class="value ellipsis-one-line" :title="xkTransfuseApply.diagnoses">
{{ xkTransfuseApply.diagnoses }}</span>
</div>
</div>
<div class="blood-type-group">
<div class="blood-type-tag ab"><span class="x_type">{{ xkPatientInfo.abo || '-' }}</span> 型</div>
<div :class="['blood-type-tag', 'rh',]">
2026-07-23 17:57:58 +08:00
<span :class="[xkPatientInfo.rh == '+' ? '' : xkPatientInfo.rh == '-' ? 'red' : '']">
{{ xkPatientInfo.rh == '+' ? '阳性' : xkPatientInfo.rh == '-' ? '阴性' : '未知' }}</span> RH
2026-07-14 18:05:18 +08:00
</div>
</div>
</div>
</div>
</div>
<div class="card-box">
<div class="section-title">
<div>开单信息</div>
<div style="width: 200px">
申请单号: {{ xkTransfuseApply.bill_no }}
</div>
</div>
<el-row :gutter="10">
2026-06-12 18:01:21 +08:00
<el-col :span="6">
2026-07-14 18:05:18 +08:00
<el-form-item label="评估单" prop="assess_bill_no">
<DropdownTableSelect v-model="xkTransfuseApply.assess_bill_no" :columnList="pgcolumnList"
:tableData="pgList" tableWidth="700px" labelField="bill_no" :showSearch="false" @open="getPgList"
2026-08-07 18:02:12 +08:00
:readonly="true" @change="getPgInfo">
<template #assess_person="{ row }">
2026-08-12 18:04:04 +08:00
{{userList.find(v => v.value == row.assess_person)?.label || row.assess_person}}
2026-08-07 18:02:12 +08:00
</template>
</DropdownTableSelect>
2026-06-12 18:01:21 +08:00
</el-form-item>
</el-col>
2026-07-14 18:05:18 +08:00
2026-07-16 18:09:10 +08:00
<el-col :span="18">
<el-form-item label="申请类型" prop="apply_type">
<el-radio-group v-model="xkTransfuseApply.apply_type">
<el-radio v-for="v in dictData.sqlx" :value="v.value">{{ v.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
2026-06-12 18:01:21 +08:00
<el-col :span="6">
2026-07-10 17:40:50 +08:00
<el-form-item label="申请日期" prop="apply_date">
2026-07-16 18:09:10 +08:00
<el-date-picker v-model="xkTransfuseApply.apply_date" type="datetime" style="width:100%"
2026-07-10 17:40:50 +08:00
value-format="YYYY-MM-DD HH:mm:ss" />
2026-06-12 18:01:21 +08:00
</el-form-item>
</el-col>
2026-07-14 18:05:18 +08:00
<el-col :span="5">
2026-07-10 17:40:50 +08:00
<el-form-item label="申请医师" prop="apply_medic">
<SelectTable v-model:data="xkTransfuseApply.apply_medic" :tableData="userList" size="small"
placeholder="" :disabled="xkTransfuseApply.bill_stasus && xkTransfuseApply.bill_stasus != 'A'" />
2026-06-12 18:01:21 +08:00
</el-form-item>
</el-col>
2026-07-16 18:09:10 +08:00
<el-col :span="6">
2026-07-10 17:40:50 +08:00
<el-form-item label="主治医师" prop="attending_medic">
<SelectTable v-model:data="xkTransfuseApply.attending_medic" :tableData="userList" size="small"
placeholder="" :disabled="xkTransfuseApply.bill_stasus && xkTransfuseApply.bill_stasus != 'A'" />
2026-06-12 18:01:21 +08:00
</el-form-item>
</el-col>
2026-07-16 18:09:10 +08:00
2026-07-14 18:05:18 +08:00
<el-col :span="6">
<el-checkbox v-model="xkTransfuseApply.agreement_ink" true-value="Y"
false-value="N">病人/病人家属是否签署输血同意书</el-checkbox>
2026-06-12 18:01:21 +08:00
</el-col>
2026-07-16 18:09:10 +08:00
<el-col :span="6">
<el-form-item label="预定输血日期" prop="use1_date">
<el-date-picker v-model="xkTransfuseApply.use1_date" type="datetime" placeholder="选择日期"
value-format="YYYY-MM-DD HH:mm:ss" />
</el-form-item>
</el-col>
2026-07-10 17:40:50 +08:00
<el-col :span="5">
2026-07-14 18:05:18 +08:00
<el-form-item label="单据类型" prop="bill_type">
<el-select v-model="xkTransfuseApply.bill_type">
<el-option label="正常" value="正常" />
<el-option label="补单" value="补单" />
2026-07-10 17:40:50 +08:00
</el-select>
2026-06-12 18:01:21 +08:00
</el-form-item>
</el-col>
<el-col :span="6">
2026-07-10 17:40:50 +08:00
<el-form-item label="科室类型" prop="dept_Type">
<el-select v-model="xkTransfuseApply.dept_Type" placeholder="" style="width:50%" clearable
@change="xkTransfuseApply.use_type = ''">
<el-option v-for="v in dictData.depttype" :label="v.label" :value="v.value" />
</el-select>
2026-07-14 18:05:18 +08:00
<el-select v-model="xkTransfuseApply.use_type" placeholder="" style="width:50%" clearable
v-if="!xkTransfuseApply.dept_Type">
</el-select>
2026-07-10 17:40:50 +08:00
<el-select v-model="xkTransfuseApply.use_type" placeholder="" style="width:50%" clearable
v-if="xkTransfuseApply.dept_Type == 'A'">
<el-option v-for="v in dictData.operatype" :label="v.label" :value="v.value" />
</el-select>
<el-select v-model="xkTransfuseApply.use_type" placeholder="" style="width:50%" clearable
v-if="xkTransfuseApply.dept_Type == 'B'">
<el-option v-for="v in dictData.nooperatype" :label="v.label" :value="v.value" />
</el-select>
2026-06-12 18:01:21 +08:00
</el-form-item>
</el-col>
2026-07-14 18:05:18 +08:00
<el-col :span="6"></el-col>
2026-07-10 17:40:50 +08:00
<el-col :span="6">
<el-form-item label="手术名称" prop="operation_name">
<DropdownTableSelect v-model="xkTransfuseApply.operation_name" :columnList="operationColumn"
2026-07-14 18:05:18 +08:00
:tableData="operationList" tableWidth="350px" labelField="oper_name" @change="getOperationInfo" />
2026-06-12 18:01:21 +08:00
</el-form-item>
</el-col>
2026-07-14 18:05:18 +08:00
<el-col :span="5">
2026-07-10 17:40:50 +08:00
<el-form-item label="手术级别" prop="operation_level">
2026-07-14 18:05:18 +08:00
<el-select v-model="xkTransfuseApply.operation_level" placeholder="" clearable>
2026-07-10 17:40:50 +08:00
<el-option label="一级手术" value="1" />
<el-option label="二级手术" value="2" />
<el-option label="三级手术" value="3" />
<el-option label="四级手术" value="4" />
</el-select>
2026-06-12 18:01:21 +08:00
</el-form-item>
</el-col>
2026-07-14 18:05:18 +08:00
<el-col :span="6">
<el-form-item label="单病种" prop="ill_Code">
<SelectTable v-model:data="xkTransfuseApply.ill_Code" :tableData="diaList" size="small" placeholder=""
:disabled="xkTransfuseApply.bill_stasus && xkTransfuseApply.bill_stasus != 'A'" />
2026-06-12 18:01:21 +08:00
</el-form-item>
</el-col>
2026-07-14 18:05:18 +08:00
</el-row>
<el-row :gutter="10">
<el-form-item label="输血史:" prop="transfuse_history">
2026-07-16 18:09:10 +08:00
<el-radio-group v-model="xkTransfuseApply.transfuse_history">
2026-07-14 18:05:18 +08:00
<el-radio value="Y">有</el-radio>
<el-radio value="N">无</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="反应史:" prop="reaction_history" label-width="80px">
2026-07-16 18:09:10 +08:00
<el-radio-group v-model="xkTransfuseApply.reaction_history">
2026-07-14 18:05:18 +08:00
<el-radio value="Y">有</el-radio>
<el-radio value="N">无</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="移植配型史:" prop="match_history" label-width="100px">
2026-07-16 18:09:10 +08:00
<el-radio-group v-model="xkTransfuseApply.match_history">
2026-07-14 18:05:18 +08:00
<el-radio value="Y">有</el-radio>
<el-radio value="N">无</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="妊娠史:" prop="gestation_history" label-width="80px">
2026-07-16 18:09:10 +08:00
<el-radio-group v-model="xkTransfuseApply.gestation_history"
2026-07-14 18:05:18 +08:00
:disabled="xkPatientInfo.patient_sex == '男' || (xkTransfuseApply.bill_stasus && xkTransfuseApply.bill_stasus != 'A')">
<el-radio value="Y">有</el-radio>
<el-radio value="N">无</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="分娩史:" prop="parturition_history" label-width="80px">
2026-07-16 18:09:10 +08:00
<el-radio-group v-model="xkTransfuseApply.parturition_history"
2026-07-14 18:05:18 +08:00
:disabled="xkPatientInfo.patient_sex == '男' || (xkTransfuseApply.bill_stasus && xkTransfuseApply.bill_stasus != 'A')">
<el-radio value="Y">有</el-radio>
<el-radio value="N">无</el-radio>
</el-radio-group>
</el-form-item>
</el-row>
<div class="line"></div>
2026-07-15 17:56:22 +08:00
<div class="flow-wrap">
<div class="flow-item" v-for="(item, index) in processList" :key="index">
2026-07-23 17:57:58 +08:00
<el-tooltip effect="dark" placement="top">
<template #content>
<div v-if="item.occurDate">
操作时间:{{ item.occurDate }}<br>
操作人:{{userList.find(v => v.value == item.occurName)?.label || ''}}
</div>
<div v-else>暂未操作</div>
</template>
2026-07-15 17:56:22 +08:00
<div class="circle-node" :class="[getNodeStatusClass(item, index)]">
2026-07-23 17:57:58 +08:00
{{ item.statusName }}
2026-07-15 17:56:22 +08:00
</div>
</el-tooltip>
<div v-if="Number(index) < Number(processList.length) - 1" class="arrow-line"
2026-07-23 17:57:58 +08:00
:class="{ arrow_finish: item.visible == 'Y' }"></div>
2026-07-15 17:56:22 +08:00
</div>
</div>
2026-07-10 17:40:50 +08:00
<div class="status"
:style="{ borderColor: getBillStatusInfo(xkTransfuseApply.bill_stasus).color, color: getBillStatusInfo(xkTransfuseApply.bill_stasus).color }">
{{ getBillStatusInfo(xkTransfuseApply.bill_stasus).label }}
</div>
2026-06-09 18:00:10 +08:00
</div>
2026-06-12 18:01:21 +08:00
<!-- 血液品种 -->
2026-07-14 18:05:18 +08:00
<div class="card-box">
<div class="section-title">
<div>血液品种</div>
<div>
2026-06-12 18:01:21 +08:00
<el-button type="primary" @click="openBloodDialog">增加</el-button>
2026-06-09 18:00:10 +08:00
</div>
</div>
2026-07-14 18:05:18 +08:00
<el-table :data="bloodList" border height="120" show-overflow-tooltip>
<el-table-column prop="blood_breed" label="血液品种" align="center" width="150">
2026-07-10 17:40:50 +08:00
<template #default="{ row }">
2026-08-12 18:04:04 +08:00
{{bloodBreed.find(v => v.value == row.blood_breed)?.label || row.blood_breed}}
2026-07-10 17:40:50 +08:00
</template>
</el-table-column>
<el-table-column prop="blood_num" label="申请血量" align="center" />
2026-06-12 18:01:21 +08:00
<el-table-column prop="unit" label="单位" align="center" />
2026-07-10 17:40:50 +08:00
<el-table-column prop="onetime_num" label="每次血量" align="center" />
<el-table-column prop="apply_bloodtype" label="申请血型" align="center">
<template #default="{ row }">
{{ formatDict(row.apply_bloodtype, 'abotype') }}
</template>
</el-table-column>
2026-07-14 18:05:18 +08:00
<el-table-column prop="intent" label="输血目的" align="center" width="200">
2026-07-10 17:40:50 +08:00
<template #default="{ row }">
{{ formatDict(row.intent, 'sxmd') }}
</template>
</el-table-column>
2026-07-14 18:05:18 +08:00
<el-table-column prop="causalis" label="输血指征" align="center" width="200">
2026-07-10 17:40:50 +08:00
<template #default="{ row }">
{{ formatDict(row.causalis, 'sxzz') }}
</template>
</el-table-column>
<el-table-column prop="special_deal" label="特殊处理" align="center">
<template #default="{ row }">
{{ formatDict(row.special_deal, 'sxzz') }}
</template>
</el-table-column>
<el-table-column prop="replace_bloodbreed" label="替代血液品种" align="center" width="120">
<template #default="{ row }">
2026-08-12 18:04:04 +08:00
{{bloodBreed.find(v => v.value == row.replace_bloodbreed)?.label || row.replace_bloodbreed}}
2026-07-10 17:40:50 +08:00
</template>
</el-table-column>
<el-table-column prop="remark" label="备注" align="center" />
<el-table-column label="操作" align="center" width="120" fixed="right">
2026-06-12 18:01:21 +08:00
<template #default="scope">
<el-button link type="primary" @click="editBlood(scope.row, scope.$index)">编辑</el-button>
<el-button link type="primary" @click="deleteSingleBlood(scope.$index)">删除</el-button>
</template>
</el-table-column>
</el-table>
2026-06-09 18:00:10 +08:00
</div>
2026-07-14 18:05:18 +08:00
<div class="card-box jcBox">
<div class="section-title">
<div>病人最近检查结果</div>
</div>
<div class="tableBox">
2026-07-15 17:56:22 +08:00
<PatientLisTable v-model:lis-list="lisProject" />
2026-07-14 18:05:18 +08:00
</div>
</div>
2026-06-12 18:01:21 +08:00
</el-form>
2026-06-09 18:00:10 +08:00
</div>
2026-06-12 18:01:21 +08:00
<!-- 右侧列表 占1份 -->
<div class="right-wrap">
<div class="box-title">申请单列表</div>
<div class="filter-bar">
2026-07-10 17:40:50 +08:00
<el-radio-group v-model="listScope" size="small" @change="radioChange">
<el-radio value="1">当前病人</el-radio>
<el-radio value="2">本科室</el-radio>
<el-radio value="3">当前医生</el-radio>
2026-06-12 18:01:21 +08:00
</el-radio-group>
<div class="date-filter">
<span>单据状态:</span>
2026-07-10 17:40:50 +08:00
<el-select v-model="queryForm.bill_status" style="width:110px" size="small" @change="getSqdList">
<el-option v-for="item in dictData.billApplyStatus" :label="item.label" :value="item.value" />
2026-06-12 18:01:21 +08:00
</el-select>
2026-07-10 17:40:50 +08:00
<el-input v-model="queryForm.day" type="number" style="width:80px" class="ml10" size="small"
@keydown.enter="getSqdList" />天内
2026-06-09 18:00:10 +08:00
</div>
</div>
2026-07-10 17:40:50 +08:00
<div class="table-box">
<el-table ref="orderRef" :data="orderList" border style="width:100%" height="100%" :cell-style="cellStyle"
highlight-current-row show-overflow-tooltip @row-click="rowClick">
<el-table-column prop="bill_stasus" label="单据状态" align="center">
<template #default="scope">
{{ formatDict(scope.row.bill_stasus, 'billApplyStatus') }}
</template>
</el-table-column>
<el-table-column prop="patient_name" label="姓名" align="center" />
<el-table-column prop="beinhos_id" label="住院号" align="center" />
<el-table-column prop="bill_no" label="申请单号" align="center" width="120" />
<el-table-column prop="dept_id" label="科室" align="center">
<template #default="scope">
{{ formatDict(scope.row.dept_id, 'ks') }}
</template>
</el-table-column>
<el-table-column prop="abo_type" label="血型" align="center" />
<el-table-column prop="rh_type" label="Rh(D)" align="center" />
<el-table-column prop="req_breed" label="申请品种" align="center" />
<el-table-column prop="apply_date" label="申请日期" width="120" align="center" />
<el-table-column prop="apply_medic" label="申请医师" align="center">
<template #default="scope">
{{userList.find(item => item.value == scope.row.apply_medic)?.label || ''}}
</template>
</el-table-column>
</el-table>
</div>
2026-06-09 18:00:10 +08:00
</div>
</div>
2026-06-12 18:01:21 +08:00
<!-- 血液品种编辑弹窗 -->
2026-07-16 18:09:10 +08:00
<el-dialog v-model="bloodDialogVisible" title="血液品种信息" width="600px" :close-on-click-modal="false"
@close="resetBloodForm">
2026-06-09 18:00:10 +08:00
<el-form ref="bloodFormRef" :model="bloodForm" label-width="100px" :rules="bloodFormRules">
2026-06-12 18:01:21 +08:00
<el-row :gutter="10">
2026-06-09 18:00:10 +08:00
<el-col :span="12">
2026-07-10 17:40:50 +08:00
<el-form-item label="血液品种" prop="blood_breed">
<el-select v-model="bloodForm.blood_breed" placeholder="" @change="breedChange">
<el-option v-for="item in bloodBreed" :label="item.label" :value="item.value" />
</el-select>
2026-06-09 18:00:10 +08:00
</el-form-item>
</el-col>
<el-col :span="12">
2026-07-10 17:40:50 +08:00
<el-form-item label="申请血量" prop="blood_num">
2026-07-16 18:09:10 +08:00
<el-input v-model="bloodForm.blood_num" type="number">
<template #suffix>
<div>
{{ bloodForm.unit }}
</div>
</template>
</el-input>
2026-06-09 18:00:10 +08:00
</el-form-item>
</el-col>
2026-07-16 18:09:10 +08:00
<!-- <el-col :span="4">
<el-input v-model="bloodForm.unit" disabled />
</el-col> -->
<el-col :span="24">
<el-form-item label="输血目的" prop="intent">
<el-select v-model="bloodForm.intent" placeholder="">
<el-option v-for="item in dictData.sxmd" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="输血指征" prop="causalis">
<el-select v-model="bloodForm.causalis" placeholder="">
<el-option v-for="item in dictData.sxzz" :label="item.label" :value="item.value" />
</el-select>
2026-06-09 18:00:10 +08:00
</el-form-item>
</el-col>
<el-col :span="12">
2026-07-10 17:40:50 +08:00
<el-form-item label="每次血量" prop="onetime_num">
<el-input v-model="bloodForm.onetime_num" type="number" />
2026-06-09 18:00:10 +08:00
</el-form-item>
</el-col>
<el-col :span="12">
2026-07-10 17:40:50 +08:00
<el-form-item label="申请血型" prop="apply_bloodtype">
<el-select v-model="bloodForm.apply_bloodtype" placeholder="">
<el-option v-for="item in dictData.abotype" :label="item.label" :value="item.value" />
</el-select>
2026-06-09 18:00:10 +08:00
</el-form-item>
</el-col>
2026-07-16 18:09:10 +08:00
2026-06-09 18:00:10 +08:00
<el-col :span="12">
2026-07-10 17:40:50 +08:00
<el-form-item label="特殊处理" prop="special_deal">
<el-input v-model="bloodForm.special_deal" placeholder="请输入特殊处理" />
2026-06-09 18:00:10 +08:00
</el-form-item>
</el-col>
<el-col :span="12">
2026-07-10 17:40:50 +08:00
<el-form-item label="替代血液品种" prop="replace_bloodbreed">
<el-select v-model="bloodForm.replace_bloodbreed" placeholder="">
<el-option v-for="item in bloodBreed" :label="item.label" :value="item.value" />
</el-select>
2026-06-09 18:00:10 +08:00
</el-form-item>
</el-col>
2026-06-12 18:01:21 +08:00
<el-col :span="24">
2026-06-09 18:00:10 +08:00
<el-form-item label="备注" prop="remark">
<el-input v-model="bloodForm.remark" placeholder="请输入备注" type="textarea" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
2026-06-12 18:01:21 +08:00
<el-button type="primary" @click="saveBloodForm">确定</el-button>
2026-06-09 18:00:10 +08:00
<el-button @click="bloodDialogVisible = false">取消</el-button>
</template>
</el-dialog>
2026-07-10 17:40:50 +08:00
<el-dialog title="输血申请检索" v-model="visible" width="1000px" :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="30">
<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" style="width: 6%;display: inline-block;text-align: center;">-</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="7">
<el-form-item label="患者姓名">
<el-input v-model="searchForm.patient_name" placeholder="" />
</el-form-item>
</el-col>
<el-col :span="7">
<el-form-item label="患者科室">
<SelectTable v-model:data="searchForm.zone_id" :tableData="dictData.ks" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="10">
<el-form-item label="申请单号">
<el-input v-model="searchForm.bill_no" placeholder="" />
</el-form-item>
</el-col>
<el-col :span="7">
<el-form-item label="住院号/ID号">
<el-input v-model="searchForm.beinhos_id" placeholder="" />
</el-form-item>
</el-col>
<el-col :span="7">
<el-form-item label="单据状态">
<SelectTable v-model:data="searchForm.bill_status" :tableData="dictData.billApplyStatus" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<!-- 结果表格区 -->
<el-table :data="jsTabdeList" border style="width: 100%; margin-top: 10px" height="350" show-overflow-tooltip
@row-click="handleRowClick" highlight-current-row :cell-style="cellStyle">
<el-table-column prop="bill_stasus" label="单据状态" align="center">
<template #default="scope">
{{ formatDict(scope.row.bill_stasus, 'billApplyStatus') }}
</template>
</el-table-column>
<el-table-column prop="patient_name" label="姓名" align="center" />
<el-table-column prop="beinhos_id" label="住院号" align="center" />
<el-table-column prop="bill_no" label="申请单号" align="center" width="120" />
<el-table-column prop="dept_id" label="科室" align="center">
<template #default="scope">
{{ formatDict(scope.row.dept_id, 'ks') }}
</template>
</el-table-column>
<el-table-column prop="abo_type" label="血型" align="center" />
<el-table-column prop="rh_type" label="Rh(D)" align="center" />
<el-table-column prop="req_breed" label="申请品种" align="center" />
<el-table-column prop="apply_date" label="申请日期" width="120" align="center" />
<el-table-column prop="apply_medic" label="申请医师" align="center">
<template #default="scope">
{{userList.find(item => item.value == scope.row.apply_medic)?.label || ''}}
</template>
</el-table-column>
</el-table>
</el-dialog>
<el-dialog title="审核" v-model="shShow" width="350px" :close-on-click-modal="false" @closed="shClose">
<el-form ref="shFormRef" :model="shForm" label-width="auto">
<el-form-item label="上级医师">
<SelectTable v-model:data="shForm.checkMedic" :tableData="userList" placeholder="" />
</el-form-item>
<el-form-item label="审核时间">
<el-date-picker v-model="shForm.checkDate" type="datetime" placeholder="选择日期"
value-format="YYYY-MM-DD HH:mm:ss" style="width:100%" />
</el-form-item>
</el-form>
<template #footer>
<el-button type="primary" @click="handleSh">确定</el-button>
<el-button @click="shClose">取消</el-button>
</template>
</el-dialog>
<el-dialog title="作废" v-model="zfShow" width="350px" :close-on-click-modal="false" @closed="() => {
reason = ''; reasonText = ''
}">
<DropdownTableSelect v-model="reasonText" :tableData="dictData.sqdzfyy" labelField="label"
:columnList="[{ label: '字典名称', prop: 'label' }, { label: '代号', prop: 'value' }]" placeholder="作废原因"
@change="(row) => { reason = row.value }" />
<template #footer>
<el-button type="primary" @click="handleZf">确定</el-button>
<el-button @click="zfShow = false">取消</el-button>
</template>
</el-dialog>
<!-- 审核意见弹窗 -->
<ReviewComments ref="reviewCommentsRef"
@success="() => { getQueryOneInfo(xkTransfuseApply.bill_no); getSqdList() }" />
<!-- 校验用户身份 -->
<CheckUser ref="checkUserRef" @onConfirm="handleCheckUserConfirm" />
2026-07-23 17:57:58 +08:00
<!-- 输血指征校验 -->
<Indication ref="indicationRef" @confirm="indicationComfirm" />
2026-06-09 18:00:10 +08:00
</div>
</template>
2026-07-10 17:40:50 +08:00
<script setup lang="ts" name="Application">
2026-06-12 18:01:21 +08:00
import type { ElForm, ElTable } from 'element-plus'
import { ElMessageBox, ElMessage } from 'element-plus'
2026-07-10 17:40:50 +08:00
import { getDictData, formatDict, dictData, useCommonDict, useSysParam } from '@/hooks'
import DropdownTableSelect from '@/components/DropdownTableSelect/index.vue'
import dayjs from 'dayjs'
import {
2026-07-14 18:05:18 +08:00
querysqList, getPatInfo, checkSelfBlood, checkCausalis, savePreApplyInfo, saveApplyInfo, queryApplyOne, queryApplyBeforeList, applyCheck, applyMedicCheck,
2026-07-23 17:57:58 +08:00
cancelApplyMedicCheck, cancelApplyCheck, cancelApply, invokeEMR, bloodCloseLoop
2026-07-10 17:40:50 +08:00
} from '@/api/doctor/application'
2026-07-23 17:57:58 +08:00
import { printPat } from '@/api/doctor/assessment'
2026-07-10 17:40:50 +08:00
import { queryOperation, getDeptType, checkLoginAffirm } from '@/api/common'
import ReviewComments from './component/reviewComments.vue'
2026-07-23 17:57:58 +08:00
import Indication from './component/indication.vue'
2026-07-15 17:56:22 +08:00
import PatientLisTable from '../components/PatientLisTable.vue'
2026-07-10 17:40:50 +08:00
import CheckUser from '@/components/CheckUser/index.vue'
import useUserStore from '@/store/modules/user'
2026-07-14 18:05:18 +08:00
import router from '@/router/index.js'
2026-07-23 17:57:58 +08:00
import { printBase64PDF } from '@/utils/classCom.js'
2026-07-10 17:40:50 +08:00
const userInfo = useUserStore()
2026-06-09 18:00:10 +08:00
2026-07-10 17:40:50 +08:00
const {
getServerTime,
userList,
getUserData,
bloodBreed,
getBloodList,
lisProject,
getLisProject,
diaList,
getDiaList,
loadAllDict
} = useCommonDict()
2026-06-09 18:00:10 +08:00
2026-07-10 17:40:50 +08:00
const route = useRoute()
2026-07-14 18:05:18 +08:00
2026-07-10 17:40:50 +08:00
const saveLoading = ref(false)
const bloodFormRef = ref<InstanceType<typeof ElForm>>()
const queryForm = reactive({
day: 7,
bill_status: '',
2026-07-23 17:57:58 +08:00
dept_code: '',
2026-07-10 17:40:50 +08:00
doctor_code: userInfo.name,
beinhos_id: ''
2026-06-09 18:00:10 +08:00
})
2026-07-10 17:40:50 +08:00
const listScope = ref('3')
2026-07-23 17:57:58 +08:00
const indicationRef = useTemplateRef('indicationRef')
2026-07-10 17:40:50 +08:00
const radioChange = (val: string) => {
switch (val) {
case '1':
queryForm.beinhos_id = xkTransfuseApply.value.beinhos_id
queryForm.dept_code = ''
queryForm.doctor_code = ''
break;
case '2':
queryForm.dept_code = xkTransfuseApply.value.dept_id ? xkTransfuseApply.value.dept_id : userInfo.deptParam.deptId
queryForm.beinhos_id = ''
queryForm.doctor_code = ''
break;
case '3':
queryForm.doctor_code = userInfo.name
queryForm.dept_code = ''
queryForm.beinhos_id = ''
break;
default:
break;
}
getSqdList()
}
const pgcolumnList = ref([
2026-07-14 18:05:18 +08:00
{ label: '评估单号', prop: 'bill_no' },
2026-07-10 17:40:50 +08:00
{ label: '住院号', prop: 'beinhos_id' },
{ label: '姓名', prop: 'patient_name', width: 100 },
{ label: '评估日期(24h内有效)', prop: 'assess_data', width: 200 },
2026-08-07 18:02:12 +08:00
{ label: '评估人', prop: 'assess_person', width: 100, slotName: 'assess_person' },
2026-06-12 18:01:21 +08:00
])
2026-06-09 18:00:10 +08:00
2026-07-10 17:40:50 +08:00
const tableData = ref([])
const dictList = ref([
{ label: '代号', prop: 'value' },
{ label: '字典', prop: 'label' }
2026-06-09 18:00:10 +08:00
])
2026-07-16 18:09:10 +08:00
2026-07-15 17:56:22 +08:00
const xkPatientInfo = ref({}) //病人信息
2026-07-10 17:40:50 +08:00
const xkTransfuseApply = ref({
agreement_ink: 'Y',
bill_type: '正常',
2026-07-16 18:09:10 +08:00
apply_type: '001',
apply_date: '',
apply_medic: userInfo.name
2026-07-10 17:40:50 +08:00
}) //输血申请信息
2026-06-12 18:01:21 +08:00
2026-07-16 18:09:10 +08:00
const formRef = useTemplateRef('formRef')
const formRules = reactive({
assess_bill_no: [{ required: true, message: '请选择评估单', trigger: 'change' }],
apply_type: [{ required: true, message: '请选择申请类型', trigger: 'change' }],
use1_date: [{ required: true, message: '请选择预定输血日期', trigger: 'change' }],
dept_Type: [{ required: true, message: '请选择科室类型', trigger: 'change' }],
})
2026-07-10 17:40:50 +08:00
// 根据单据状态获取单元格样式(背景色+白色文字)
const cellStyle = ({ row, column, rowIndex, columnIndex }) => {
if (column.label == '单据状态') {
return {
background: `${getBillStatusInfo(row.bill_stasus).color} !important`,
color: '#ffffff',
fontWeight: 500
}
}
}
const getBillStatusInfo = (code: string) => {
const statusList = dictData.value?.billApplyStatus ?? []
const target = statusList.find(item => item.value == code)
if (target) {
return { label: target.label, color: target.remark }
}
2026-07-30 17:59:51 +08:00
return { label: '未审核', color: '#909399' }
2026-07-10 17:40:50 +08:00
}
// 血液品种列表
const bloodList = ref([])
const orderList = ref([]) // 输血申请单列表
const orderRef = useTemplateRef('orderRef')
2026-06-12 18:01:21 +08:00
// 血液品种弹窗相关
const bloodDialogVisible = ref(false)
const editIndex = ref(-1)
2026-07-10 17:40:50 +08:00
const bloodForm = reactive({})
2026-06-09 18:00:10 +08:00
2026-06-12 18:01:21 +08:00
// 血液品种表单验证规则
const bloodFormRules = reactive({
2026-07-10 17:40:50 +08:00
blood_breed: [{ required: true, message: '请输入血液品种', trigger: 'blur' }],
blood_num: [
{ required: true, message: '请输入申请血量', trigger: 'blur' },
{
validator: (rule: any, value: number, callback: Function) => {
if (value <= 0) {
callback(new Error('申请血量必须大于0'))
2026-07-16 18:09:10 +08:00
} else if (bloodForm.unit == 'ml' && value < 25) {
callback(new Error('申请血量必须大于等于25ml'))
} else if (bloodForm.unit == 'u' && value > 25) {
callback(new Error('申请血量必须小于25'))
2026-07-10 17:40:50 +08:00
} else {
callback()
}
},
trigger: 'blur'
}
2026-07-16 18:09:10 +08:00
],
intent: [{ required: true, message: '请选择输血目的', trigger: 'change' }],
causalis: [{ required: true, message: '请选择输血指征', trigger: 'change' }],
2026-07-10 17:40:50 +08:00
})
2026-07-15 17:56:22 +08:00
//流程节点
const processList = ref([
2026-07-23 17:57:58 +08:00
{ statusName: '开单', occurDate: '' },
{ statusName: '上级医生审核', occurDate: '' },
{ statusName: '输血科审核', occurDate: '' },
// { statusName: '医务部审核', occurDate: '' },
// { statusName: '输血科审核', occurDate: '' },
{ statusName: '血型复核', occurDate: '' },
{ statusName: '交叉配血', occurDate: '' },
{ statusName: '临床发血', occurDate: '' },
2026-07-15 17:56:22 +08:00
])
// 当前激活步骤下标
const currentStepIndex = computed(() => {
const list = processList.value
for (let i = 0; i < list.length; i++) {
2026-07-23 17:57:58 +08:00
if (!list[i].occurDate) return i
2026-07-15 17:56:22 +08:00
}
return list.length - 1
})
// 节点状态类名
2026-07-23 17:57:58 +08:00
const getNodeStatusClass = (item, index: number) => {
2026-07-15 17:56:22 +08:00
const currIdx = currentStepIndex.value
// 已完成:有时间
2026-07-23 17:57:58 +08:00
if (item.visible == 'Y') return 'finish'
2026-07-15 17:56:22 +08:00
// 当前待办节点
if (index === currIdx) return 'active'
// 未开始
return 'wait'
}
2026-07-10 17:40:50 +08:00
const visible = ref(false)
const searchForm = ref({
stime: dayjs().format('YYYY-MM-DD'),
etime: dayjs().format('YYYY-MM-DD'),
patient_name: '',
bill_no: '',
beinhos_id: '',
bill_status: ''
})
const selectRow = ref({})
const jsTabdeList = ref([])
// 检索
const openJsDialog = () => {
getList()
visible.value = true
}
const handleClose = () => {
visible.value = false
searchForm.value = {
stime: dayjs().format('YYYY-MM-DD'),
etime: dayjs().format('YYYY-MM-DD'),
patient_name: '',
bill_no: '',
beinhos_id: '',
bill_status: ''
}
selectRow.value = {}
}
const handleSearch = () => {
selectRow.value = {}
getList()
}
const handleConfirm = () => {
if (!selectRow.value.bill_no) return ElMessage.warning('请选择评估单')
getQueryOneInfo(selectRow.value.bill_no)
visible.value = false
selectRow.value = {}
}
const handleRowClick = (row) => {
selectRow.value = row
}
// 检索列表
const getList = () => {
const data = {
...searchForm.value,
stime: dayjs(searchForm.value.stime).format('YYYY-MM-DD') + ' 00:00:00',
etime: dayjs(searchForm.value.etime).format('YYYY-MM-DD') + ' 23:59:59',
}
querysqList(data).then((res) => {
jsTabdeList.value = res.data
})
}
// 查询申请单列表
const getSqdList = () => {
querysqList(queryForm).then((res) => {
orderList.value = res.data
if (res.data.length) {
nextTick(() => {
2026-07-23 17:57:58 +08:00
const row = res.data.find(item => item.bill_no == xkTransfuseApply.value.bill_no)
2026-07-10 17:40:50 +08:00
if (row) {
orderRef.value.setCurrentRow(row)
}
})
}
})
}
const rowClick = (row) => {
getQueryOneInfo(row.bill_no)
}
//新增申请单
const addHandle = () => {
2026-07-15 17:56:22 +08:00
xkPatientInfo.value = {} //病人信息
2026-07-10 17:40:50 +08:00
xkTransfuseApply.value = {
agreement_ink: 'Y',
bill_type: '正常',
2026-07-16 18:09:10 +08:00
apply_type: '001',
2026-07-10 17:40:50 +08:00
assess_bill_no: ''
}
2026-07-16 18:09:10 +08:00
bloodList.value = []
2026-07-10 17:40:50 +08:00
getServerTime().then(time => {
2026-07-16 18:09:10 +08:00
xkTransfuseApply.value.apply_date = time
xkTransfuseApply.value.use1_date = time
nextTick(() => {
formRef.value?.clearValidate()
})
2026-07-10 17:40:50 +08:00
})
2026-07-23 17:57:58 +08:00
processList.value = [
{ statusName: '开单', occurDate: '' },
{ statusName: '上级医生审核', occurDate: '' },
{ statusName: '输血科审核', occurDate: '' },
{ statusName: '血型复核', occurDate: '' },
{ statusName: '交叉配血', occurDate: '' },
{ statusName: '临床发血', occurDate: '' },
]
2026-07-10 17:40:50 +08:00
getLisProject()
}
const checkUserRef = useTemplateRef('checkUserRef')
const shShow = ref(false)
const shForm = ref({
checkMedic: '',
checkDate: dayjs().format('YYYY-MM-DD HH:mm:ss'),
agreement_ink: 'Y'
2026-06-09 18:00:10 +08:00
})
2026-07-10 17:40:50 +08:00
const shLoading = ref(false)
const reviewCommentsRef = useTemplateRef('reviewCommentsRef')
// 审核
// 如果是001 代表是临床科室,此时需要调用“上级医生审核” 审核接口,
// 如果是002 代表是输血科室,调用“申请单审核前校验”
const reviewHandle = () => {
if (!xkTransfuseApply.value.bill_no) return ElMessage.warning('请选择申请单')
shLoading.value = true
getDeptType({ userId: userInfo.name }).then(res => {
if (res.data == '001') {
shForm.value.checkMedic = userInfo.name
shShow.value = true
} else if (res.data = '002') {
applyCheck({ billNo: xkTransfuseApply.value.bill_no }).then(res => {
if (res.code == 0) {
reviewCommentsRef.value.open(res.data)
}
})
}
}).finally(() => {
shLoading.value = false
})
}
// 上级医生审核
const handleSh = () => {
if (userInfo.name != shForm.value.checkMedic) {
//和当前登录的用户不一致的时候,需要输入工号密码验证
checkUserRef.value.open()
} else {
handleReviewConfirm()
}
}
const cancelreviewHandle = () => {
if (!xkTransfuseApply.value.bill_no) return ElMessage.warning('请选择申请单')
getDeptType({ userId: userInfo.name }).then(res => {
ElMessageBox.confirm(
`申请单号${xkTransfuseApply.value.bill_no}确定取消审核吗?`,
'提示',
{ type: 'warning', }
).then(() => {
if (res.data == '001') {
cancelApplyMedicCheck({ billNo: xkTransfuseApply.value.bill_no }).then(res => {
if (res.code == 0) {
ElMessage.success(res.msg)
getQueryOneInfo(xkTransfuseApply.value.bill_no)
getSqdList()
}
})
} else if (res.data == '002') {
cancelApplyCheck({ billNo: xkTransfuseApply.value.bill_no }).then(res => {
if (res.code == 0) {
ElMessage.success(res.msg)
getQueryOneInfo(xkTransfuseApply.value.bill_no)
getSqdList()
}
})
}
})
})
}
//作废
const reason = ref('')
const reasonText = ref('')
const zfShow = ref(false)
const invalidateHandle = () => {
// sqdzfyy
if (!xkTransfuseApply.value.bill_no) return ElMessage.warning('请选择申请单')
zfShow.value = true
}
const handleZf = () => {
if (!reason.value) return ElMessage.warning('请填写作废原因')
cancelApply({ billNo: xkTransfuseApply.value.bill_no, reason: reason.value }).then(res => {
if (res.code == 0) {
ElMessage.success(res.msg)
zfShow.value = false
getQueryOneInfo(xkTransfuseApply.value.bill_no)
getSqdList()
}
})
}
// 校验用户
const handleCheckUserConfirm = (info: { yhdh: string, mm: string }) => {
checkLoginAffirm({ userId: info.yhdh, password: info.mm }).then((response: any) => {
if (response.code == 0) {
shForm.value.checkMedic = info.yhdh
handleReviewConfirm()
}
})
}
//输血科审核
const handleReviewConfirm = () => {
const data = {
billNo: xkTransfuseApply.value.bill_no,
...shForm.value
}
applyMedicCheck(data).then(res => {
if (res.code == 0) {
ElMessage.success(res.msg)
shShow.value = false
getQueryOneInfo(xkTransfuseApply.value.bill_no)
getSqdList()
}
})
}
//审核意见
const shClose = () => {
shShow.value = false
shForm.value = {
checkMedic: '',
checkDate: dayjs().format('YYYY-MM-DD HH:mm:ss'),
agreement_ink: 'Y'
}
}
2026-07-23 17:57:58 +08:00
const printLoading = ref(false)
//打印输血评估单
2026-07-24 17:37:42 +08:00
const printHandle = (name: string) => {
2026-07-23 17:57:58 +08:00
printLoading.value = true
let billno = ''
if (name == 'INFORMED_CONSENT') {
billno = xkTransfuseApply.value.assess_bill_no
2026-07-24 17:37:42 +08:00
} else {
2026-07-23 17:57:58 +08:00
billno = xkTransfuseApply.value.bill_no
}
printPat({ billNo: billno, templateName: name }).then((res) => {
if (res.data) {
printBase64PDF(res.data)
}
}).finally(() => {
printLoading.value = false
})
}
2026-07-14 18:05:18 +08:00
//患者历史
const goHistoryBlood = () => {
router.push({
path: '/doctor/historyBlood',
query: {
patientName: xkPatientInfo.value.patient_name,
}
})
}
2026-06-12 18:01:21 +08:00
// 打开新增弹窗
const openBloodDialog = () => {
editIndex.value = -1
2026-06-09 18:00:10 +08:00
resetBloodForm()
2026-07-16 18:09:10 +08:00
bloodForm.apply_bloodtype = xkPatientInfo.value.abo
2026-06-09 18:00:10 +08:00
bloodDialogVisible.value = true
}
2026-06-12 18:01:21 +08:00
// 重置弹窗表单
const resetBloodForm = () => {
if (bloodFormRef.value) {
bloodFormRef.value.clearValidate()
}
2026-07-10 17:40:50 +08:00
// 删除所有key,清空表单
Object.keys(bloodForm).forEach(key => delete bloodForm[key])
2026-06-09 18:00:10 +08:00
}
2026-06-12 18:01:21 +08:00
// 编辑血液品种
const editBlood = (row: any, index: number) => {
editIndex.value = index
2026-07-10 17:40:50 +08:00
// 清空原有表单
Object.keys(bloodForm).forEach(key => delete bloodForm[key])
// 深拷贝行数据再赋值,切断和表格原数据的引用
Object.assign(bloodForm, JSON.parse(JSON.stringify(row)))
2026-06-12 18:01:21 +08:00
bloodDialogVisible.value = true
2026-06-09 18:00:10 +08:00
}
2026-07-10 17:40:50 +08:00
// 删除单条血液品种
const deleteSingleBlood = (index: number) => {
ElMessageBox.confirm(
'确定要删除这条血液品种信息吗?',
'提示',
{
type: 'warning',
size: 'small'
}
).then(() => {
bloodList.value.splice(index, 1)
ElMessage.success('删除成功')
})
}
const breedChange = (value: string) => {
bloodForm.unit = bloodBreed.value.find(item => item.value === value)?.unit
}
2026-06-12 18:01:21 +08:00
// 保存血液品种表单
const saveBloodForm = async () => {
2026-06-09 18:00:10 +08:00
if (!bloodFormRef.value) return
2026-06-12 18:01:21 +08:00
try {
await bloodFormRef.value.validate()
2026-07-10 17:40:50 +08:00
// 深拷贝一份再存入列表,防止双向联动
const formCopy = JSON.parse(JSON.stringify(bloodForm))
2026-06-12 18:01:21 +08:00
if (editIndex.value === -1) {
2026-07-10 17:40:50 +08:00
bloodList.value.push(formCopy)
2026-06-12 18:01:21 +08:00
} else {
2026-07-10 17:40:50 +08:00
bloodList.value.splice(editIndex.value, 1, formCopy)
2026-06-09 18:00:10 +08:00
}
2026-06-12 18:01:21 +08:00
bloodDialogVisible.value = false
} catch (error) {
ElMessage.error('请完善必填信息')
2026-06-09 18:00:10 +08:00
}
}
2026-07-14 18:05:18 +08:00
//电子病历
const blHandle = () => {
if (!xkTransfuseApply.value.beinhos_id) return ElMessage.warning('请选择患者')
invokeEMR({ beinhos_id: xkTransfuseApply.value.beinhos_id }).then(res => {
if (res.code == 0) {
ElMessage.success(res.msg)
}
})
}
2026-06-09 18:00:10 +08:00
2026-07-14 18:05:18 +08:00
//保存申请单
2026-07-10 17:40:50 +08:00
const handleSubmit = async () => {
2026-07-16 18:09:10 +08:00
formRef.value.validate((valid) => {
if (valid) {
if (!bloodList.value.length) return ElMessage.error('请添加血液品种')
// 申请类型 003 || 002 手术信息必填校验
if (xkTransfuseApply.value.apply_type === '003' || xkTransfuseApply.value.apply_type === '002') {
if (!xkTransfuseApply.value.operation_name || !xkTransfuseApply.value.operation_level) {
return ElMessage.error('请完善手术名称、级别信息')
}
}
saveLoading.value = true
const tempPatient = { ...xkPatientInfo.value, beinhos_id: xkTransfuseApply.value.beinhos_id }
const data = {
transfuseApplyInfoOne: {
xkPatientInfo: tempPatient,
xkTransfuseApply: xkTransfuseApply.value
},
xkTransfuseApplyBloodbreedList: bloodList.value,
xkTransfuseApplyTestitemList: lisProject.value,
}
2026-07-10 17:40:50 +08:00
2026-07-23 17:57:58 +08:00
// 自体血校验
2026-07-16 18:09:10 +08:00
checkSelfBlood({ beinhos_id: xkTransfuseApply.value.beinhos_id }).then((res) => {
if (res.code == 0) {
2026-07-23 17:57:58 +08:00
// 校验是否符合输血指征的规则
2026-07-16 18:09:10 +08:00
checkCausalis(data).then((res1) => {
if (res1.code == 0) {
2026-07-23 17:57:58 +08:00
// 保存前校验
2026-07-16 18:09:10 +08:00
savePreApplyInfo(data).then((res2) => {
if (res2.code == 0) {
2026-07-23 17:57:58 +08:00
// 保存申请单
2026-07-16 18:09:10 +08:00
saveApplyInfo(data).then((res3) => {
2026-07-23 17:57:58 +08:00
if (res3.data) {
getQueryOneInfo(res3.data)
getSqdList()
}
2026-07-16 18:09:10 +08:00
if (res3.code == 0) {
ElMessage.success('保存成功')
}
})
} else if (res2.code == 1) {
2026-07-10 17:40:50 +08:00
getSqdList()
2026-07-16 18:09:10 +08:00
ElMessage.success(res2.msg)
} else if (res2.code == 2) {
//2 弹窗提示
ElMessageBox.confirm(res2.msg, '提示',
{
confirmButtonText: '是',
cancelButtonText: '否',
type: 'warning',
showClose: false,
closeOnClickModal: false,
closeOnPressEscape: false,
}
).then(() => {
getQueryOneInfo(res2.data)
}).catch(() => {
2026-07-23 17:57:58 +08:00
// 保存申请单
2026-07-16 18:09:10 +08:00
saveApplyInfo(data).then((res3) => {
2026-07-23 17:57:58 +08:00
if (res3.data) {
getQueryOneInfo(res3.data)
2026-07-16 18:09:10 +08:00
getSqdList()
2026-07-23 17:57:58 +08:00
}
if (res3.code == 0) {
2026-07-16 18:09:10 +08:00
ElMessage.success('保存成功')
}
})
})
2026-07-10 17:40:50 +08:00
}
})
2026-07-23 17:57:58 +08:00
} else if (res1.code == 1) {
indicationRef.value.openDialog(res1.data, xkTransfuseApply.value.bill_no)
2026-07-10 17:40:50 +08:00
}
})
}
2026-07-16 18:09:10 +08:00
}).finally(() => {
saveLoading.value = false
2026-07-10 17:40:50 +08:00
})
2026-07-16 18:09:10 +08:00
} else {
ElMessage.error('请完善必填信息')
2026-06-12 18:01:21 +08:00
}
2026-06-09 18:00:10 +08:00
})
}
2026-07-23 17:57:58 +08:00
//输血指征校验弹窗确定
const indicationComfirm = (arr) => {
const tempPatient = { ...xkPatientInfo.value, beinhos_id: xkTransfuseApply.value.beinhos_id }
const data = {
transfuseApplyInfoOne: {
xkPatientInfo: tempPatient,
xkTransfuseApply: xkTransfuseApply.value
},
xkTransfuseApplyBloodbreedList: bloodList.value,
xkTransfuseApplyTestitemList: lisProject.value,
xkTransfuseApplyCausalisList: arr
}
saveApplyInfo(data).then((res) => {
if (res.data) {
getQueryOneInfo(res.data)
getSqdList()
}
if (res.code == 0) {
ElMessage.success('保存成功')
}
})
}
2026-07-14 18:05:18 +08:00
//获取申请单信息
2026-07-10 17:40:50 +08:00
const getQueryOneInfo = (bill_no: string) => {
queryApplyOne({ billNo: bill_no }).then((res) => {
xkPatientInfo.value = res.data.transfuseApplyInfoOne.xkPatientInfo
xkTransfuseApply.value = res.data.transfuseApplyInfoOne.xkTransfuseApply
bloodList.value = res.data.xkTransfuseApplyBloodbreedList
2026-07-23 17:57:58 +08:00
lisProject.value = mergeLisTestItem(lisProject.value, res.data.xkTransfuseApplyTestitemList)
})
//获取申请单状态
bloodCloseLoop({ billNo: bill_no }).then(res => {
if (res.code == 0) {
processList.value = res.data
}
2026-07-10 17:40:50 +08:00
})
}
2026-07-14 18:05:18 +08:00
//获取患者信息
2026-07-23 17:57:58 +08:00
const getInfo = (billNo: string) => {
2026-07-10 17:40:50 +08:00
//PJD2026061623
getPatInfo({ bill_no: billNo }).then((res) => {
xkPatientInfo.value = res.data.transfuseApplyInfoOne.xkPatientInfo
xkTransfuseApply.value = res.data.transfuseApplyInfoOne.xkTransfuseApply
2026-07-14 18:05:18 +08:00
bloodList.value = res.data.xkTransfuseApplyBloodbreedList || []
2026-07-23 17:57:58 +08:00
lisProject.value = mergeLisTestItem(lisProject.value, res.data.xkTransfuseApplyTestitemList)
})
}
//合并检查结果
const mergeLisTestItem = (oldList: Array<any>, apiList: Array<any>) => {
const currentBillNo = xkTransfuseApply.value?.bill_no ?? ''
if (apiList.length === 0) {
// 过滤脏数据
return oldList.filter(item => item?.item_name).map(item => {
2026-07-10 17:40:50 +08:00
return {
2026-07-23 17:57:58 +08:00
...item,
item_result: '',
bill_no: currentBillNo
2026-07-10 17:40:50 +08:00
}
})
2026-07-23 17:57:58 +08:00
}
const oldMap = new Map<string, any>()
oldList.forEach(item => {
if (item?.item_name) oldMap.set(item.item_name, item)
})
return apiList.map(apiItem => {
if (!apiItem || !apiItem.item_name) {
return {
bill_no: currentBillNo,
item_name: '',
item_result: '',
item_unit: '',
test_date: '',
sid: '',
result_type: ''
}
}
const apiData = {
bill_no: apiItem.bill_no ?? currentBillNo,
item_name: apiItem.item_name ?? '',
item_result: apiItem.item_result ?? '',
item_unit: apiItem.item_unit ?? '',
test_date: apiItem.test_date ?? '',
sid: apiItem.sid ?? ''
}
const localItem = oldMap.get(apiItem.item_name)
if (localItem) {
// 接口所有字段覆盖,仅复用旧result_type
return {
...apiData,
result_type: localItem.result_type ?? ''
}
}
return {
...apiData,
result_type: ''
}
2026-07-10 17:40:50 +08:00
})
}
// 回显时拆分 年龄 + 单位
const splitAge = (ageStr: string) => {
const unitList = dictData.value.nldw.map(item => item.value)
let age = ageStr
let unit = '岁'
for (const u of unitList) {
if (ageStr.includes(u)) {
age = ageStr.replace(u, '')
unit = u
break
}
2026-06-12 18:01:21 +08:00
}
2026-07-10 17:40:50 +08:00
xkPatientInfo.value.age = age
xkPatientInfo.value.nldw = unit
2026-06-12 18:01:21 +08:00
}
2026-07-10 17:40:50 +08:00
const pgList = ref([])
//获取评估申请单
const getPgList = () => {
queryApplyBeforeList({ user_id: userInfo.name, dept_id: userInfo.deptParam.deptId }).then((res) => {
pgList.value = res.data
})
}
let needClearState = false // 标记是否需要清理state
// 加载单据
const loadBillInfo = () => {
const state = history.state as { billNo?: string; isJump?: boolean } | null
// 只有主动跳转带过来的参数才执行查询
if (state?.isJump && state.billNo) {
getInfo(state.billNo)
2026-07-23 17:57:58 +08:00
addHandle()
2026-07-10 17:40:50 +08:00
needClearState = true // 标记本次有跳转参数,页面销毁时清空
2026-06-12 18:01:21 +08:00
}
2026-06-09 18:00:10 +08:00
}
2026-07-10 17:40:50 +08:00
//住院号点击
const getPgInfo = (row) => {
getInfo(row.bill_no)
}
//手术名称
const operationList = ref([])
const operationColumn = [
{ label: '手术代号', prop: 'icd_code' },
{ label: '手术名称', prop: 'oper_name', width: 200 },
// { label: '手术级别', prop: 'oper_level' },
]
2026-07-14 18:05:18 +08:00
const getOperationInfo = (row) => {
if (row.oper_level) {
switch (row.oper_level) {
case '一级':
xkTransfuseApply.value.operation_level = '1'
break;
case '二级':
xkTransfuseApply.value.operation_level = '2'
break;
case '三级':
xkTransfuseApply.value.operation_level = '3'
break;
case '四级':
xkTransfuseApply.value.operation_level = '4'
break;
default:
break;
}
}
}
//手术名称
2026-07-10 17:40:50 +08:00
const getSxList = () => {
queryOperation({ pageNum: 1, pageSize: 99999 }).then(res => {
operationList.value = res.rows
})
}
2026-07-14 18:05:18 +08:00
2026-07-10 17:40:50 +08:00
onMounted(() => {
loadAllDict()
getServerTime().then(time => {
2026-07-16 18:09:10 +08:00
xkTransfuseApply.value.apply_date = time
xkTransfuseApply.value.use1_date = time
2026-07-10 17:40:50 +08:00
})
getSxList()
2026-07-14 18:05:18 +08:00
getDictData('sqdzfyy', 'rhtype', 'abotype', 'nldw', 'billApplyStatus', 'sd', 'ks', 'depttype', 'bq', 'sxmd', 'sxzz', 'test_result', 'sqlx', 'lczd', 'xylx', 'operatype', 'nooperatype')
2026-07-10 17:40:50 +08:00
getSqdList()
loadBillInfo()
})
// 监听路由变化
watch(() => route.fullPath, loadBillInfo)
// 页面关闭/切换标签时再清空state,不影响同路由二次跳转
onBeforeUnmount(() => {
if (needClearState) {
history.replaceState({}, document.title)
}
})
2026-06-09 18:00:10 +08:00
</script>
<style scoped lang="scss">
2026-06-17 17:49:37 +08:00
.box-container {
2026-06-09 18:00:10 +08:00
display: flex;
2026-06-12 18:01:21 +08:00
flex-direction: column;
2026-06-09 18:00:10 +08:00
box-sizing: border-box;
2026-06-12 18:01:21 +08:00
overflow-y: auto;
2026-06-09 18:00:10 +08:00
2026-06-12 18:01:21 +08:00
.toolbar {
padding: 8px;
2026-06-09 18:00:10 +08:00
background: #fff;
2026-06-12 18:01:21 +08:00
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
2026-06-09 18:00:10 +08:00
border-radius: 4px;
2026-07-14 18:05:18 +08:00
margin-bottom: 10px;
2026-06-09 18:00:10 +08:00
}
2026-06-12 18:01:21 +08:00
.main-content {
flex: 1;
2026-06-09 18:00:10 +08:00
display: flex;
2026-06-12 18:01:21 +08:00
gap: 10px;
overflow: hidden;
.box-title {
position: relative;
padding-left: 12px;
padding-bottom: 6px;
font-size: 15px;
font-weight: 600;
display: flex;
justify-content: space-between;
// align-items: center;
/* 左侧蓝色小竖线 */
2026-06-09 18:00:10 +08:00
&::before {
content: '';
2026-06-12 18:01:21 +08:00
position: absolute;
left: 0;
top: 2px;
bottom: 2px;
2026-06-09 18:00:10 +08:00
width: 4px;
height: 14px;
background-color: #409eff;
margin-right: 8px;
border-radius: 0 4px 4px 0;
}
2026-06-12 18:01:21 +08:00
.title-btn {
display: flex;
gap: 6px;
}
2026-06-09 18:00:10 +08:00
}
2026-06-12 18:01:21 +08:00
/* 左侧 2份 */
.left-wrap {
2026-06-09 18:00:10 +08:00
flex: 1;
2026-06-12 18:01:21 +08:00
display: flex;
flex-direction: column;
2026-07-14 18:05:18 +08:00
overflow: hidden;
2026-06-09 18:00:10 +08:00
2026-06-12 18:01:21 +08:00
.blood-transfusion-form {
2026-07-14 18:05:18 +08:00
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
2026-07-10 17:40:50 +08:00
.el-radio {
margin-right: 10px !important;
2026-07-14 18:05:18 +08:00
}
2026-07-10 17:40:50 +08:00
2026-07-14 18:05:18 +08:00
.jcBox {
flex: 1;
min-height: 0;
.tableBox {
height: calc(100% - 30px);
}
2026-07-10 17:40:50 +08:00
}
2026-06-12 18:01:21 +08:00
}
2026-06-09 18:00:10 +08:00
2026-07-14 18:05:18 +08:00
.card-box {
2026-07-10 17:40:50 +08:00
position: relative;
2026-06-09 18:00:10 +08:00
2026-06-12 18:01:21 +08:00
:deep(.el-form-item) {
margin-bottom: 6px !important;
2026-06-09 18:00:10 +08:00
}
2026-07-10 17:40:50 +08:00
.col-project {
position: relative;
}
.unit {
position: absolute;
left: 100%;
top: 0;
color: #aeb1b7;
margin-left: 5px;
}
.status {
position: absolute;
right: 20px;
2026-07-14 18:05:18 +08:00
top: 100px;
2026-07-10 17:40:50 +08:00
color: #409eff;
font-size: 18px;
font-weight: 700;
border: 2px solid #409eff;
border-radius: 5px;
padding: 10px;
}
2026-06-09 18:00:10 +08:00
}
2026-07-10 17:40:50 +08:00
2026-06-09 18:00:10 +08:00
}
2026-06-12 18:01:21 +08:00
/* 右侧 1份 */
.right-wrap {
width: 35%;
display: flex;
flex-direction: column;
background: #fff;
border-radius: 4px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
padding: 10px;
.filter-bar {
margin-bottom: 8px;
// display: flex;
// align-items: center;
gap: 10px;
flex-wrap: wrap;
}
2026-06-09 18:00:10 +08:00
2026-06-12 18:01:21 +08:00
.date-filter {
font-size: 14px;
color: #333;
}
2026-07-10 17:40:50 +08:00
.table-box {
flex: 1;
overflow: hidden;
}
2026-06-12 18:01:21 +08:00
}
2026-06-09 18:00:10 +08:00
}
}
2026-07-10 17:40:50 +08:00
.text-danger {
color: #f00 !important;
margin-left: 20px;
:deep(.el-checkbox__label) {
color: #f00 !important;
}
}
2026-07-14 18:05:18 +08:00
.base-info-card {
.base-info-content {
display: flex;
flex-wrap: wrap;
box-sizing: border-box;
.base-info {
display: flex;
width: 100%;
}
.info-row {
display: flex;
width: 100%;
flex-wrap: wrap;
.info-item {
width: 20%;
display: flex;
font-size: 14px;
.label {
2026-07-23 17:57:58 +08:00
font-weight: 600;
font-size: 14px;
color: #333;
2026-07-14 18:05:18 +08:00
min-width: 70px;
text-align: right;
margin-right: 8px;
}
.value {
color: #1d2d42;
flex: 1;
font-size: 15px;
}
}
}
.blood-type-group {
display: flex;
gap: 16px;
margin-left: 20px;
.blood-type-tag {
width: 150px;
height: 50px;
line-height: 50px;
border-radius: 4px;
color: #fff;
font-size: 30px;
font-weight: 600;
padding-left: 20px;
&.ab {
background: url('@/assets/images/blood_zero.png');
background-size: 100% 100%;
color: #3594c7;
.x_type {
color: #ff3b62;
}
}
&.rh {
background-color: #e8f7ff;
color: #3594c7;
}
.red {
color: #f00 !important;
}
}
}
}
}
.line {
height: 1px;
background-color: #ccc;
}
2026-07-15 17:56:22 +08:00
.flow-wrap {
display: flex;
align-items: center;
width: 100%;
overflow-x: auto;
margin-top: 5px;
}
.flow-item {
display: flex;
align-items: center;
flex-shrink: 0;
}
// 圆圈节点
.circle-node {
font-size: 12px;
padding: 6px;
border: 2px solid;
}
// 已完成(绿色)
.circle-node.finish {
background: #e6f9ef;
border-color: #00b42a;
color: #00b42a;
}
// 当前节点(蓝色)
.circle-node.active {
background: #e8f3ff;
border-color: #409eff;
color: #409eff;
font-weight: bold;
}
// 未操作(灰色)
.circle-node.wait {
background: #f5f7fa;
border-color: #dcdcdc;
color: #86909c;
}
// 默认灰色箭头
.arrow-line {
width: 40px;
height: 2px;
background: #c0c4cc;
position: relative;
margin: 0 8px;
flex-shrink: 0;
&::after {
content: '';
position: absolute;
right: 0;
top: -4px;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-left: 8px solid #c0c4cc;
}
}
// 已完成节点对应的绿色箭头
.arrow-line.arrow_finish {
background: #00b42a;
&::after {
border-left-color: #00b42a;
}
}
2026-06-09 18:00:10 +08:00
</style>