Files
his/openhis-ui-vue3/src/views/surgicalschedule/index.vue
2026-02-10 17:10:34 +08:00

1813 lines
64 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="app-container">
<!-- 顶部筛选区 -->
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" class="query-form">
<el-form-item label="安排时间" prop="scheduleDate">
<el-tooltip :content="queryParams.scheduleDate" placement="top" :disabled="!queryParams.scheduleDate">
<el-date-picker
v-model="queryParams.scheduleDate"
type="date"
placeholder="请选择安排时间"
value-format="YYYY-MM-DD"
style="width: 200px"
/>
</el-tooltip>
</el-form-item>
<el-form-item label="卫生机构" prop="tenantId">
<el-select v-model="queryParams.tenantId" placeholder="请选择卫生机构" style="width: 200px">
<el-option
v-for="item in orgList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="申请科室" prop="applyDeptId">
<el-select v-model="queryParams.applyDeptId" placeholder="请选择申请科室" style="width: 200px">
<el-option
v-for="item in deptList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="姓名/拼音码" prop="patientName">
<el-input
v-model="queryParams.patientName"
placeholder="请输入姓名/拼音码"
clearable
@keyup.enter="handleQuery"
style="width: 200px"
/>
</el-form-item>
<el-form-item class="search-buttons">
<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 :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd"> 新增手术安排 </el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Money" @click="handleChargeCharge(selectedRow)" :disabled="!selectedRow"> 计费 </el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Document" @click="handleMedicalAdvice(selectedRow)" :disabled="!selectedRow"> 医嘱 </el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Download" @click="handleExport">导出表格</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<!-- 中部表格区 -->
<el-table v-loading="loading" :data="surgeryList" row-key="scheduleId" :row-class-name="getRowClassName" @current-change="handleCurrentChange">
<el-table-column label="ID" align="center" width="80">
<template #default="{ $index }">
{{ (applyQueryParams.pageNo - 1) * applyQueryParams.pageSize + $index + 1 }}
</template>
</el-table-column>
<el-table-column label="卫生机构" align="center" prop="orgName" width="120" show-overflow-tooltip />
<el-table-column label="姓名" align="center" prop="patientName" width="100" />
<el-table-column label="就诊卡号" align="center" prop="visitId" width="120" />
<el-table-column label="手术单号" align="center" prop="operCode" width="120" show-overflow-tooltip />
<el-table-column label="手术名称" align="center" prop="operName" min-width="140" show-overflow-tooltip />
<el-table-column label="申请科室" align="center" prop="applyDeptName" width="100" show-overflow-tooltip />
<el-table-column label="手术类型" align="center" width="100">
<template #default="scope">
{{ getSurgeryTypeName(scope.row.surgeryNature) }}
</template>
</el-table-column>
<el-table-column label="手术性质" align="center" width="100">
<template #default="scope">
{{ getSurgeryTypeName(scope.row.surgeryNature) }}
</template>
</el-table-column>
<el-table-column label="主刀医生" align="center" width="100" prop="surgeonName"/>
<el-table-column label="麻醉方法" align="center" width="120">
<template #default="scope">
{{ getAnesthesiaName(scope.row.anesMethod) }}
</template>
</el-table-column>
<el-table-column label="安排时间" align="center" prop="scheduleDate" width="140">
<template #default="scope">
{{ parseTime(scope.row.scheduleDate, '{y}-{m}-{d}') }}
</template>
</el-table-column>
<el-table-column label="操作人" align="center" width="100" prop="createByName" />
<el-table-column label="操作" align="center" width="240" fixed="right">
<template #default="scope">
<el-button link type="primary" @click="handleView(scope.row)">查看</el-button>
<el-button link type="primary" @click="handleEdit(scope.row)">编辑</el-button>
<el-button link type="danger" @click="handleDelete(scope.row)" v-has="['surgicalSchedule:delete']">取消</el-button>
</template>
</el-table-column>
</el-table>
<!-- 底部分页区 -->
<div class="pagination-container">
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getPageList"
/>
</div>
<!-- 手术安排弹窗 -->
<el-dialog :title="title" v-model="open" width="1200px" @close="cancel" append-to-body :close-on-click-modal="false">
<!-- 弹窗头部操作按钮 -->
<div class="dialog-header-buttons" v-if="!isViewMode && !isEditMode">
<el-button @click="handleFindApply">查找</el-button>
<el-button @click="handleRefresh">刷新</el-button>
<el-button @click="cancel">返回</el-button>
<el-button type="primary" :disabled="isViewMode" @click="submitForm">保存</el-button>
</div>
<!-- 表单内容区 -->
<el-form ref="surgeryRef" :model="form" :rules="rules" label-width="120px" :disabled="isViewMode">
<!-- 病人基本信息组 -->
<el-divider content-position="left">病人基本信息</el-divider>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="患者id" prop="patientId">
<el-tooltip :content="form.patientId" placement="top" :disabled="!form.patientId">
<el-input v-model="form.patientId" :disabled="true" style="width: 100%" />
</el-tooltip>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="就诊卡号" prop="visitId">
<el-tooltip :content="form.visitId" placement="top" :disabled="!form.visitId">
<el-input v-model="form.visitId" :disabled="true" style="width: 100%" />
</el-tooltip>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="姓名" prop="patientName">
<el-tooltip :content="form.patientName" placement="top" :disabled="!form.patientName">
<el-input v-model="form.patientName" :disabled="true" style="width: 100%" />
</el-tooltip>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="性别" width="80">
<el-tooltip :content="form.gender == 0 ? '男' : form.gender == 1 ? '女' : ''" placement="top" :disabled="!form.gender">
<el-input :value="form.gender == 0 ? '男' : form.gender == 1 ? '女' : form.gender=='男'?'男': form.gender=='女'?'女':''" :disabled="true" style="width: 100%" />
</el-tooltip>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="年龄" prop="age">
<el-tooltip :content="form.age" placement="top" :disabled="!form.age">
<el-input v-model="form.age" :disabled="true" style="width: 100%" />
</el-tooltip>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="病人体重" prop="patientWeight">
<el-input v-model="form.patientWeight" placeholder="请输入病人体重kg" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="病人身高" prop="patientHeight">
<el-input v-model="form.patientHeight" placeholder="请输入病人身高cm" />
</el-form-item>
</el-col>
</el-row>
<!-- 手术申请信息组 -->
<el-divider content-position="left">手术申请信息</el-divider>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="手术单号" prop="surgeryNo">
<el-tooltip :content="form.surgeryNo" placement="top" :disabled="!form.surgeryNo">
<el-input v-model="form.surgeryNo" :disabled="true" style="width: 100%" />
</el-tooltip>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="手术类型" prop="surgeryType">
<el-select v-model="form.surgeryType" placeholder="请选择手术类型" style="width: 100%">
<el-option
v-for="item in surgery_type"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="费用类别" prop="feeType">
<el-tooltip :content="form.feeType" placement="top" :disabled="!form.feeType">
<el-input v-model="form.feeType" :disabled="true" style="width: 100%" />
</el-tooltip>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="申请时间" prop="applyTime">
<el-tooltip :content="formattedApplyTime" placement="top" :disabled="!form.applyTime">
<el-input v-model="formattedApplyTime" :disabled="true" style="width: 100%" />
</el-tooltip>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="申请医生" prop="applyDoctorName">
<el-tooltip :content="form.applyDoctorName" placement="top" :disabled="!form.applyDoctorName">
<el-input v-model="form.applyDoctorName" :disabled="true" style="width: 100%" />
</el-tooltip>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="手术名称" prop="operName">
<el-tooltip :content="form.operName" placement="top" :disabled="!form.operName">
<el-input v-model="form.operName" :disabled="true" style="width: 100%" />
</el-tooltip>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="申请科室" prop="applyDeptName">
<el-tooltip :content="form.applyDeptName" placement="top" :disabled="!form.applyDeptName">
<el-input v-model="form.applyDeptName" :disabled="true" style="width: 100%" />
</el-tooltip>
</el-form-item>
</el-col>
</el-row>
<!-- 手术安排组 -->
<el-divider content-position="left">手术安排</el-divider>
<el-row :gutter="20">
<el-col :span="10">
<el-form-item label="安排时间" prop="scheduleDate">
<el-date-picker
v-model="form.scheduleDate"
type="datetime"
placeholder="选择安排时间"
value-format="YYYY-MM-DD"
format="YYYY-MM-DD"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="10">
<el-form-item label="手术台次" prop="sequenceNo">
<el-input v-model.number="form.sequenceNo" placeholder="请输入手术台次" />
</el-form-item>
</el-col>
<el-col :span="10">
<el-form-item label="手术间号" prop="roomCode">
<el-select v-model="form.roomCode" placeholder="请选择手术间号" style="width: 100%">
<el-option
v-for="item in operatingRoomList"
:key="item.roomCode"
:label="item.roomCode"
:value="item.roomCode"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="10">
<el-form-item label="手术台" prop="tableNo">
<el-input v-model.number="form.tableNo" placeholder="请输入手术台" />
</el-form-item>
</el-col>
<el-col :span="10">
<el-form-item label="是否首次手术" prop="isFirstSurgery" >
<el-radio-group v-model="form.isFirstSurgery">
<el-radio :value="1"></el-radio>
<el-radio :value="0"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<!-- 手术性质和部位 -->
<el-divider content-position="left">手术性质和部位</el-divider>
<el-row :gutter="20">
<el-col :span="10">
<el-form-item label="手术性质" prop="surgeryNature">
<el-select v-model="form.surgeryNature" placeholder="请选择手术性质" style="width: 100%">
<el-option
v-for="item in surgery_type"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="10">
<el-form-item label="手术部位" prop="surgerySite">
<el-select v-model="form.surgerySite" placeholder="请选择手术部位" style="width: 100%">
<el-option
v-for="item in surgerySiteList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="10">
<el-form-item label="过敏药物" prop="isAllergyMedication">
<el-radio-group v-model="form.isAllergyMedication">
<el-radio :value="1"></el-radio>
<el-radio :value="0"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="过敏药物备注" prop="allergyRemark">
<el-input v-model="form.allergyRemark" type="textarea" placeholder="请输入过敏药物备注" :rows="3" />
</el-form-item>
</el-col>
</el-row>
<!-- 医护人员组 -->
<el-divider content-position="left">医护人员</el-divider>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="主刀医生" prop="surgeonCode">
<el-tooltip :content="form.surgeonName" placement="top" :disabled="!form.surgeonName">
<el-input v-model="form.surgeonName" :disabled="true" style="width: 100%" />
</el-tooltip>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="助手1" prop="assistant1Code">
<el-select v-model="form.assistant1Code" placeholder="请选择助手1" filterable style="width: 100%">
<el-option
v-for="item in doctorList"
:key="item.code"
:label="item.name"
:value="item.code"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="助手2" prop="assistant2Code">
<el-select v-model="form.assistant2Code" placeholder="请选择助手2" filterable style="width: 100%">
<el-option
v-for="item in doctorList"
:key="item.code"
:label="item.name"
:value="item.code"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="助手3" prop="assistant3Code">
<el-select v-model="form.assistant3Code" placeholder="请选择助手3" filterable style="width: 100%">
<el-option
v-for="item in doctorList"
:key="item.code"
:label="item.name"
:value="item.code"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="洗手护士" prop="scrubNurseCode">
<el-select v-model="form.scrubNurseCode" placeholder="请选择洗手护士" filterable style="width: 100%">
<el-option
v-for="item in nurseList"
:key="item.code"
:label="item.name"
:value="item.code"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="器械护士1" prop="scrubNurse1Code">
<el-select v-model="form.scrubNurse1Code" placeholder="请选择器械护士1" filterable style="width: 100%">
<el-option
v-for="item in nurseList"
:key="item.code"
:label="item.name"
:value="item.code"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="器械护士2" prop="scrubNurse2Code">
<el-select v-model="form.scrubNurse2Code" placeholder="请选择器械护士2" filterable style="width: 100%">
<el-option
v-for="item in nurseList"
:key="item.code"
:label="item.name"
:value="item.code"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="巡回护士1" prop="circuNurse1Code">
<el-select v-model="form.circuNurse1Code" placeholder="请选择巡回护士1" filterable style="width: 100%">
<el-option
v-for="item in nurseList"
:key="item.code"
:label="item.name"
:value="item.code"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="麻醉方法" prop="anesMethod">
<el-select v-model="form.anesMethod" placeholder="请选择麻醉方法" style="width: 100%">
<el-option
v-for="item in anesthesiaList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="巡回护士2" prop="circuNurse2Code">
<el-select v-model="form.circuNurse2Code" placeholder="请选择巡回护士2" filterable style="width: 100%">
<el-option
v-for="item in nurseList"
:key="item.code"
:label="item.name"
:value="item.code"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="外请专家" prop="isExternalExpert">
<el-radio-group v-model="form.isExternalExpert">
<el-radio :value="1"></el-radio>
<el-radio :value="0"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="外请专家姓名" prop="externalExpertName">
<el-input v-model="form.externalExpertName" placeholder="请输入外请专家姓名" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="10">
<el-form-item label="麻醉医师1" prop="anesDoctor1Code">
<el-select v-model="form.anesDoctor1Code" placeholder="请选择麻醉医师1" filterable style="width: 100%">
<el-option
v-for="item in doctorList"
:key="item.code"
:label="item.name"
:value="item.code"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="10">
<el-form-item label="麻醉医师2" prop="anesDoctor2Code">
<el-select v-model="form.anesDoctor2Code" placeholder="请选择麻醉医师2" filterable style="width: 100%">
<el-option
v-for="item in doctorList"
:key="item.code"
:label="item.name"
:value="item.code"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="10">
<el-form-item label="麻醉医师3" prop="anesDoctor3Code">
<el-select v-model="form.anesDoctor3Code" placeholder="请选择麻醉医师3" filterable style="width: 100%">
<el-option
v-for="item in doctorList"
:key="item.code"
:label="item.name"
:value="item.code"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="术前诊断" prop="preoperativeDiagnosis">
<el-input v-model="form.preoperativeDiagnosis" placeholder="请输入术前诊断" />
</el-form-item>
<el-form-item label="术后诊断" prop="postoperativeDiagnosis">
<el-input v-model="form.postoperativeDiagnosis" placeholder="请输入术后诊断" />
</el-form-item>
<!-- 手术过程组 -->
<el-divider content-position="left">手术过程</el-divider>
<el-row :gutter="20">
<el-col :span="10">
<el-form-item label="入室时间" prop="admissionTime">
<el-date-picker
v-model="form.admissionTime"
type="datetime"
placeholder="选择入室时间"
value-format="YYYY-MM-DDTHH:mm:ss"
format="YYYY-MM-DD HH:mm"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="10">
<el-form-item label="进室时间" prop="entryTime">
<el-date-picker
v-model="form.entryTime"
type="datetime"
placeholder="选择进室时间"
value-format="YYYY-MM-DDTHH:mm:ss"
format="YYYY-MM-DD HH:mm"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="10">
<el-form-item label="麻醉开始时间" prop="anesStart">
<el-date-picker
v-model="form.anesStart"
type="datetime"
placeholder="选择麻醉开始时间"
value-format="YYYY-MM-DDTHH:mm:ss"
format="YYYY-MM-DD HH:mm"
style="width: 100%"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="10">
<el-form-item label="切开时间" prop="startTime">
<el-date-picker
v-model="form.startTime"
type="datetime"
placeholder="选择切开时间"
value-format="YYYY-MM-DDTHH:mm:ss"
format="YYYY-MM-DD HH:mm"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="10">
<el-form-item label="手术结束时间" prop="endTime">
<el-date-picker
v-model="form.endTime"
type="datetime"
placeholder="选择手术结束时间"
value-format="YYYY-MM-DDTHH:mm:ss"
format="YYYY-MM-DD HH:mm"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="10">
<el-form-item label="麻醉结束时间" prop="anesEnd">
<el-date-picker
v-model="form.anesEnd"
type="datetime"
placeholder="选择麻醉结束时间"
value-format="YYYY-MM-DDTHH:mm:ss"
format="YYYY-MM-DD HH:mm"
style="width: 100%"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="切口类型" prop="incisionType">
<el-select v-model="form.incisionType" placeholder="请选择切口类型" style="width: 100%">
<el-option
v-for="item in incisionTypeList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="感染诊断" prop="infectionDiagnosis">
<el-input v-model="form.infectionDiagnosis" placeholder="请输入感染诊断" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="隔离种类" prop="isolationType">
<el-input v-model="form.isolationType" placeholder="请输入隔离种类" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="是否植入标志" prop="implantFlag">
<el-radio-group v-model="form.implantFlag">
<el-radio :value="1"></el-radio>
<el-radio :value="0"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="植入物序列号/批号" prop="implantSerial">
<el-input v-model="form.implantSerial" placeholder="请输入植入物序列号/批号" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="出血量" prop="bloodLoss">
<el-input v-model="form.bloodLoss" placeholder="请输入出血量" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="输血量" prop="bloodTrans">
<el-input v-model="form.bloodTrans" placeholder="请输入输血量" />
</el-form-item>
</el-col>
</el-row>
<!-- 备注信息组 -->
<el-divider content-position="left">备注信息</el-divider>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="手术相关对话信息" prop="communicationInfo">
<el-input v-model="form.communicationInfo" type="textarea" placeholder="请输入手术相关对话信息" :rows="3" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="手术相关备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入手术相关备注" :rows="3" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<!-- 底部操作区 -->
<template #footer>
<div class="dialog-footer" v-if="!isViewMode">
<el-button @click="cancel">取消</el-button>
<el-button type="primary" @click="submitForm">保存</el-button>
</div>
</template>
</el-dialog>
<!-- 手术申请查询弹窗 -->
<el-dialog :title="'手术申请查询'" v-model="showApplyDialog" width="1200px" @close="cancelApplyDialog">
<!-- 查询条件区 -->
<el-form :model="applyQueryParams" ref="applyQueryRef" :inline="true" class="query-form">
<el-form-item label="申请时间范围" prop="applyTimeRange">
<el-tooltip :content="applyQueryParams.applyTimeRange ? applyQueryParams.applyTimeRange.join(' 至 ') : ''" placement="top" :disabled="!applyQueryParams.applyTimeRange || applyQueryParams.applyTimeRange.length === 0">
<el-date-picker
v-model="applyQueryParams.applyTimeRange"
type="daterange"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="YYYY-MM-DD"
style="width: 240px"
/>
</el-tooltip>
</el-form-item>
<el-form-item label="申请科室" prop="applyDeptId">
<el-select v-model="applyQueryParams.applyDeptId" placeholder="请选择申请科室" style="width: 150px">
<el-option
v-for="item in deptList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="主刀医生" prop="mainDoctorId">
<el-select v-model="applyQueryParams.mainDoctorId" placeholder="请选择主刀医生" style="width: 150px">
<el-option
v-for="item in doctorList"
:key="item.code"
:label="item.name"
:value="item.code"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleApplyQuery">查询</el-button>
<el-button icon="Refresh" @click="resetApplyQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 结果表格区 -->
<el-table
ref="applyTableRef"
v-loading="applyLoading"
:data="applyList"
row-key="surgeryNo"
@row-click="handleApplyRowClick"
:row-class-name="tableRowClassName"
style="width: 100%"
max-height="400"
:scroll="{ y: 400 }"
>
<el-table-column type="selection" width="55" :selectable="handleSelectable" />
<el-table-column label="ID" align="center" width="80" fixed>
<template #default="{ $index }">
{{ (applyQueryParams.pageNo - 1) * applyQueryParams.pageSize + $index + 1 }}
</template>
</el-table-column>
<el-table-column label="姓名" align="center" prop="name" width="100" />
<el-table-column label="手术单号" align="center" prop="surgeryNo" width="120" />
<el-table-column label="手术名称" align="center" prop="descJson.surgeryName" min-width="140" show-overflow-tooltip />
<el-table-column label="申请科室" align="center" width="100" prop="applyDeptName" />
<el-table-column label="手术类型" align="center" width="90">
<template #default="scope">
{{ getSurgeryTypeName(scope.row.surgeryType) }}
</template>
</el-table-column>
<el-table-column label="手术等级" align="center" width="90">
<template #default="scope">
{{ getSurgeryLevelName(scope.row.descJson?.surgeryLevel) }}
</template>
</el-table-column>
<el-table-column label="主刀医生" align="center" width="100" prop="mainSurgeonName" />
</el-table>
<!-- 底部分页区 -->
<div class="pagination-container" style="margin-top: 10px; padding-bottom: 10px">
<pagination
v-show="applyTotal > 0"
:total="applyTotal"
:page="applyQueryParams.pageNo"
:limit="applyQueryParams.pageSize"
@update:page="val => applyQueryParams.pageNo = val"
@update:limit="val => applyQueryParams.pageSize = val"
@pagination="getSurgicalScheduleList"
/>
</div>
<!-- 底部操作区 -->
<template #footer>
<div class="dialog-footer">
<el-button @click="cancelApplyDialog">取消</el-button>
<el-button type="primary" @click="confirmApply">确认</el-button>
</div>
</template>
</el-dialog>
<!-- 手术计费弹窗 -->
<el-dialog :title="chargeDialogTitle" v-model="showChargeDialog" width="1400px" @close="closeChargeDialog" append-to-body>
<div style="display: flex; justify-content: space-between; height: 80vh">
<div style="width: 100%; border: 1px solid #eee; position: relative">
<div style="padding: 10px; border: 1px solid #eee; height: 50px; border-left: 0">
<el-descriptions :column="4">
<el-descriptions-item label="患者信息:" width="150">
{{
Object.keys(chargePatientInfo).length !== 0
? chargePatientInfo.patientName +
' / ' +
chargePatientInfo.age +
' / ' +
chargePatientInfo.genderEnum_enumText +
' / ' +
chargePatientInfo.typeCode_dictText
: '-'
}}
</el-descriptions-item>
<el-descriptions-item label="安排时间" width="150">
{{ Object.keys(chargePatientInfo).length !== 0 ? formatChargeDate(chargePatientInfo.registerTime) : '-' }}
</el-descriptions-item>
<el-descriptions-item label="计费账号" width="150">{{ userStore.name }}</el-descriptions-item>
<el-descriptions-item label="手术名称" width="150">{{ chargeSurgeryInfo.surgeryName }}</el-descriptions-item>
</el-descriptions>
</div>
<div style="padding: 10px">
<prescriptionlist :patientInfo="chargePatientInfo" ref="prescriptionRef" />
<div class="overlay" v-if="disabled"></div>
</div>
</div>
</div>
</el-dialog>
<!-- 临时医嘱弹窗 -->
<el-dialog :title="temporaryMedicalTitle" v-model="showTemporaryMedical" width="80%" append-to-body :close-on-click-modal="false">
<temporary-medical
:patient-info="temporaryPatientInfo"
:billing-medicines="temporaryBillingMedicines"
v-model:temporary-advices="temporaryAdvices"
@submit="handleTemporaryMedicalSubmit"
@cancel="handleTemporaryMedicalCancel"
@delete-advice="handleDeleteTemporaryAdvice"
/>
</el-dialog>
</div>
</template>
<script setup name="SurgicalSchedule">
import { ref, reactive, onMounted, nextTick, computed } from 'vue'
import { getCurrentInstance } from 'vue'
import { parseTime } from '@/utils/openhis'
import { useDict } from '@/utils/dict'
import download from '@/plugins/download'
import Prescriptionlist from '@/views/clinicmanagement/bargain/component/prescriptionlist.vue'
import useUserStore from '@/store/modules/user'
import { ElMessage } from 'element-plus'
// 导入计费相关接口
import { getPrescriptionList } from '@/views/clinicmanagement/bargain/component/api'
// API 导入
import { getSurgerySchedulePage, addSurgerySchedule, updateSurgerySchedule, deleteSurgerySchedule, getSurgeryScheduleDetail } from '@/api/surgicalschedule'
import { listUser } from '@/api/system/user'
import { deptTreeSelect } from '@/api/system/user'
import { listOperatingRoom } from '@/api/operatingroom'
import { getTestResultPage} from '@/views/inpatientDoctor/home/components/applicationShow/api.js'
import { getTenantPage } from '@/api/system/tenant'
import { getContract } from '@/views/inpatientDoctor/home/components/api.js'
import SurgeryCharge from '../charge/surgerycharge/index.vue'
import TemporaryMedical from './temporaryMedical.vue'
const { proxy } = getCurrentInstance()
const userStore = useUserStore()
const loading = ref(true)
const showSearch = ref(true)
const surgeryList = ref([])
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
scheduleDate: undefined,
tenantId: undefined,
applyDeptId: undefined,
patientName: undefined
})
const open = ref(false)
const isEditMode = ref(false)
const isViewMode = ref(false)
// 选中行状态管理
const selectedRow = ref(null)
const selectedRowIndex = ref(-1)
const form = reactive({
scheduleId:undefined,
applyId: undefined,
patientId: undefined,
visitId: undefined,
operCode: undefined,
operName: undefined,
preoperativeDiagnosis: undefined,
postoperativeDiagnosis: undefined,
scheduleDate: undefined,
sequenceNo: undefined,
isFirstSurgery: 0,
isAllergyMedication: 0,
allergyRemark: undefined,
surgeryNature: undefined,
surgerySite: undefined,
admissionTime: undefined,
entryTime: undefined,
roomCode: undefined,
tableNo: undefined,
anesMethod: undefined,
anesDoctor1Code: undefined,
anesDoctor2Code: undefined,
anesDoctor3Code: undefined,
scrubNurseCode: undefined,
circuNurse1Code: undefined,
circuNurse2Code: undefined,
scrubNurse1Code: undefined,
scrubNurse2Code: undefined,
surgeonCode: undefined,
assistant1Code: undefined,
assistant2Code: undefined,
assistant3Code: undefined,
startTime: undefined,
endTime: undefined,
anesStart: undefined,
anesEnd: undefined,
operStatus: 0,
implantFlag: 0,
implantSerial: undefined,
bloodLoss: undefined,
bloodTrans: undefined,
infectionDiagnosis: undefined,
isolationType: undefined,
patientWeight: undefined,
patientHeight: undefined,
communicationInfo: undefined,
remark: undefined,
createTime: undefined,
creatorId: undefined,
patientName: undefined,
gender: undefined,
birthDay: undefined,
orgName: undefined,
applyDeptName: undefined,
surgeonName: undefined,
isExternalExpert: 0,
externalExpertName: undefined
})
const surgeryRef = ref()
const total = ref(0)
const title = ref('')
// 表单验证规则
const rules = reactive({
scheduleDate: [
{ required: true, message: '请选择安排时间', trigger: 'change' }
],
sequenceNo: [
{ required: true, message: '请输入手术台次', trigger: 'blur' },
{ type: 'number', message: '手术台次必须为数字', trigger: 'blur' }
],
roomCode: [
{ required: true, message: '请选择手术间号', trigger: 'change' }
],
tableNo: [
{ required: true, message: '请选择手术台', trigger: 'change' }
],
surgeryNature: [
{ required: true, message: '请选择手术性质', trigger: 'change' }
],
surgerySite: [
{ required: true, message: '请选择手术部位', trigger: 'change' }
],
anesMethod: [
{ required: true, message: '请选择麻醉方法', trigger: 'change' }
],
surgeonCode: [
{ required: true, message: '请选择主刀医生', trigger: 'change' }
]
})
// 手术申请查询弹窗
const showApplyDialog = ref(false)
const applyLoading = ref(false)
const applyList = ref([])
const applyTotal = ref(0)
const applyTableRef = ref()
// 手术计费弹窗
const showChargeDialog = ref(false)
const chargeDialogTitle = ref('')
const chargePatientInfo = ref({})
const chargeSurgeryInfo = ref({})
const prescriptionRef = ref()
// 临时医嘱弹窗
const showTemporaryMedical = ref(false)
const temporaryMedicalTitle = ref('门诊术中临时医嘱')
const temporaryPatientInfo = ref({})
const temporaryBillingMedicines = ref([])
const temporaryAdvices = ref([])
// 下拉列表数据
const orgList = ref([])
const deptList = ref([])
const doctorList = ref([])
const nurseList = ref([])
const operatingRoomList = ref([])
function flattenOrgTree(tree = []) {
const result = []
const stack = Array.isArray(tree) ? [...tree] : []
while (stack.length) {
const node = stack.shift()
if (!node) continue
const id = node.id ?? node.orgId ?? node.deptId
const name = node.name ?? node.label ?? node.deptName ?? node.orgName
if (id !== undefined && id !== null && name) {
result.push({ id, name })
}
const children = node.children || node.childList
if (Array.isArray(children) && children.length) {
stack.unshift(...children)
}
}
// 去重
const seen = new Set()
return result.filter(it => {
const key = String(it.id)
if (seen.has(key)) return false
seen.add(key)
return true
})
}
function mapPractitionerToOption(item) {
// user-practitioner-page 常见字段practitionerId / nickName / orgId 等
const code = item.code ?? item.practitionerId ?? item.userId ?? item.id
const name = item.name ?? item.nickName ?? item.userName ?? item.userNickName
return { code, name }
}
function mapOperatingRoomToOption(item) {
const roomCode = item.roomCode ?? item.code ?? item.no ?? item.name
return { ...item, roomCode }
}
// 字典数据
// 字典返回的字段名就是字典 key 本身(参照 surgerymanageconst { surgical_site } = useDict('surgical_site')
const {
surgical_site: surgerySiteList,
anesthesia_type: anesthesiaList,
incision_type: incisionTypeList,
isolation_type: isolationTypeList,
surgery_type,
surgery_level,
surgery_nature: surgeryNatureList
} = useDict('surgical_site', 'anesthesia_type', 'incision_type', 'isolation_type', 'surgery_type', 'surgery_level', 'surgery_nature')
// 加载数据
onMounted(() => {
getPageList()
loadOrgList()
loadDeptList()
loadDoctorList()
loadNurseList()
loadOperatingRoomList()
})
// 加载卫生机构列表
function loadOrgList() {
getTenantPage({ pageNo: 1, pageSize: 1000 })
.then(res => {
if (res.code === 200) {
const records = res.data?.records || res.data || []
orgList.value = records.map(item => ({ id: item.id, name: item.tenantName || item.name }))
} else {
proxy.$modal.msgError('获取卫生机构列表失败')
orgList.value = []
}
})
.catch(() => {
proxy.$modal.msgError('获取卫生机构列表失败')
orgList.value = []
})
}
// 加载科室列表
function loadDeptList() {
deptTreeSelect()
.then(res => {
if (res.code === 200) {
const tree = res.data?.records || res.data || []
deptList.value = flattenOrgTree(tree)
} else {
proxy.$modal.msgError('获取科室列表失败')
deptList.value = []
}
})
.catch(error => {
proxy.$modal.msgError('获取科室列表失败')
deptList.value = []
})
}
// 加载医生列表
function loadDoctorList() {
listUser({ pageNo: 1, pageSize: 1000 })
.then(res => {
if (res.code === 200) {
const records = res.data?.records || []
doctorList.value = records.map(mapPractitionerToOption).filter(it => it.code && it.name)
} else {
proxy.$modal.msgError('获取医生列表失败')
doctorList.value = []
}
})
.catch(error => {
proxy.$modal.msgError('获取医生列表失败')
doctorList.value = []
})
}
// 加载护士列表
function loadNurseList() {
listUser({ pageNo: 1, pageSize: 1000 })
.then(res => {
if (res.code === 200) {
const records = res.data?.records || []
nurseList.value = records.map(mapPractitionerToOption).filter(it => it.code && it.name)
} else {
proxy.$modal.msgError('获取护士列表失败')
nurseList.value = []
}
})
.catch(error => {
proxy.$modal.msgError('获取护士列表失败')
nurseList.value = []
})
}
// 加载手术室列表
function loadOperatingRoomList() {
listOperatingRoom({ pageNo: 1, pageSize: 1000, statusEnum: 1 })
.then(res => {
if (res.code === 200) {
const records = res.data?.records || []
operatingRoomList.value = records.map(mapOperatingRoomToOption).filter(it => it.roomCode)
} else {
proxy.$modal.msgError('获取手术室列表失败')
operatingRoomList.value = []
}
})
.catch(error => {
proxy.$modal.msgError('获取手术室列表失败')
operatingRoomList.value = []
})
}
// 获取手术安排列表
function getList() {
loading.value = true
getSurgerySchedulePage(queryParams).then((res) => {
surgeryList.value = res.data.records
total.value = res.data.total
}).catch(error => {
proxy.$modal.msgError('获取手术安排列表失败,请稍后重试')
surgeryList.value = []
total.value = 0
}).finally(() => {
loading.value = false
})
}
function getPageList() {
queryParams.pageNo = 1
getList()
}
function handleQuery() {
queryParams.pageNo = 1
getList()
}
function resetQuery() {
proxy.resetForm('queryRef')
Object.assign(queryParams, {
pageNo: 1,
pageSize: 10,
scheduleDate: undefined,
tenantId: undefined,
applyDeptId: undefined,
patientName: undefined
})
getList()
}
// 新增手术安排
function handleAdd() {
title.value = '新增手术安排'
isEditMode.value = false
isViewMode.value = false
resetForm()
open.value = true
}
// 编辑手术安排
function handleEdit(row) {
title.value = '编辑手术安排'
isEditMode.value = true
isViewMode.value = false
resetForm()
getSurgeryScheduleDetail(row.scheduleId).then(res => {
if (res.code === 200) {
const data = res.data
Object.assign(form, data)
} else {
proxy.$modal.msgError('获取手术安排详情失败')
}
}).catch(() => {
proxy.$modal.msgError('获取手术安排详情失败')
})
open.value = true
}
// 查看手术安排
function handleView(row) {
title.value = '查看手术安排'
isEditMode.value = false
isViewMode.value = true
resetForm()
getSurgeryScheduleDetail(row.scheduleId).then(res => {
if (res.code === 200) {
const data = res.data
Object.assign(form, data)
} else {
proxy.$modal.msgError('获取手术安排详情失败')
}
}).catch(() => {
proxy.$modal.msgError('获取手术安排详情失败')
})
open.value = true
}
// 行选中事件处理
function handleCurrentChange(currentRow, oldRow) {
if (currentRow) {
selectedRow.value = currentRow
selectedRowIndex.value = surgeryList.value.findIndex(row => row.scheduleId === currentRow.scheduleId)
} else {
selectedRow.value = null
selectedRowIndex.value = -1
}
}
// 删除手术安排
function handleDelete(row) {
proxy.$modal.confirm('是否确认取消手术安排"' + row.operName + '"?').then(() => {
return deleteSurgerySchedule(row.scheduleId)
}).then(() => {
getPageList()
proxy.$modal.msgSuccess('手术安排已取消')
}).catch(() => {
return
})
}
// 手术计费
async function handleChargeCharge(row) {
// 如果没有传入行数据,使用选中的行
if (!row && selectedRow.value) {
row = selectedRow.value
}
// 如果还是没有行数据,显示提示
if (!row) {
proxy.$modal.msgWarning('请先选择要计费的手术安排')
return
}
// 调用接口获取账户信息
let accountId = null
try {
const contractResult = await getContract({ encounterId: row.visitId })
if (contractResult.code === 200 && contractResult.data && contractResult.data.length > 0) {
// 从返回数据中提取accountId - data是数组取第一个元素的accountId
accountId = contractResult.data[0].accountId || contractResult.data[0].id
} else {
proxy.$modal.msgError('获取账户信息失败')
}
} catch (error) {
return
}
// 设置计费弹窗数据 - 直接复制划价页面的逻辑
chargeDialogTitle.value = '手术计费 - ' + row.patientName + ' - ' + row.operName
// 构建患者信息传递encounterId和机构ID
chargePatientInfo.value = {
encounterId: row.visitId, // 就诊ID
patientId: row.patientId,
patientName: row.patientName,
genderEnum: row.gender,
age: row.age,
organizationName: row.applyDeptName,
registerTime: row.scheduleDate,
typeCode_dictText: row.applyDeptName,
genderEnum_enumText: row.gender === 0 ? '男' : row.gender === 1 ? '女' : '未知',
// 添加机构ID
orgId: userStore.organizationId || userStore.orgId || userStore.tenantId || 1,
// 添加账户ID
accountId: accountId,
// 添加手术申请单号用于追溯
sourceBillNo: row.applyId,
//添加计费标志手术计费
generateSourceEnum: 6
}
chargeSurgeryInfo.value = {
surgeryName: row.operName,
surgeryNo: row.operCode
}
// 打开计费弹窗
showChargeDialog.value = true
// 延迟加载处方列表,确保组件已经渲染
nextTick(() => {
if (prescriptionRef.value && prescriptionRef.value.getListInfo) {
prescriptionRef.value.getListInfo()
}
})
}
// 关闭计费弹窗
function closeChargeDialog() {
showChargeDialog.value = false
chargePatientInfo.value = {}
chargeSurgeryInfo.value = {}
}
// 处理医嘱按钮点击事件
function handleMedicalAdvice(row) {
// 如果没有传入行数据,使用选中的行
if (!row && selectedRow.value) {
row = selectedRow.value
}
// 如果还是没有行数据,显示提示
if (!row) {
proxy.$modal.msgWarning('请先选择要开具医嘱的手术安排')
return
}
// 设置临时医嘱弹窗数据
temporaryPatientInfo.value = {
patientName: row.patientName,
visitId: row.visitId,
operCode: row.operCode,
roomCode: row.roomCode,
doctorName: userStore.nickName,
role: userStore.roles[0],
}
// 初始化临时医嘱列表
temporaryAdvices.value = []
// 调用计费接口获取数据
getPrescriptionList(row.visitId).then((res) => {
if (res.code === 200 && res.data) {
// 过滤数据,只保留 adviceType 值为 1 的药品
const filteredItems = res.data.filter(item => {
try {
// 尝试从 contentJson 中解析数据
const contentData = JSON.parse(item.contentJson)
const adviceType = Number(contentData.adviceType)
return adviceType === 3
} catch (e) {
// 如果解析失败,尝试使用顶层的 adviceType
const adviceType = Number(item.adviceType)
return adviceType === 3
}
})
// 将过滤后的数据转换为临时医嘱需要的格式
temporaryBillingMedicines.value = filteredItems.map(item => {
try {
// 从 contentJson 中解析详细数据
const contentData = JSON.parse(item.contentJson)
return {
medicineName: contentData.adviceName || item.adviceName || '',
specification: contentData.volume || contentData.specification || '',
quantity: contentData.quantity || item.quantity || 0,
batchNumber: contentData.lotNumber || item.lotNumber || '',
unitPrice: contentData.unitPrice || item.unitPrice || 0,
subtotal: contentData.totalPrice || item.totalPrice || 0,
insuranceType: contentData.insuranceType === 1 ? '医保' : '自费'
}
} catch (e) {
// 如果解析失败,使用顶层数据
return {
medicineName: item.adviceName || '',
specification: item.specification || '',
quantity: item.quantity || 0,
batchNumber: item.lotNumber || '',
unitPrice: item.unitPrice || 0,
subtotal: item.totalPrice || 0,
insuranceType: item.insuranceType === 1 ? '医保' : '自费'
}
}
})
} else {
// 如果没有数据或接口调用失败,初始化空列表
temporaryBillingMedicines.value = []
}
// 将计费药品转换为临时医嘱数据
temporaryAdvices.value = temporaryBillingMedicines.value.map((medicine, index) => {
// 解析规格中的数值和单位
const specMatch = medicine.specification ? medicine.specification.match(/(\d+)(\D+)/) : null
const specValue = specMatch ? parseInt(specMatch[1]) : 1
const specUnit = specMatch ? specMatch[2] : 'ml'
// 计算剂量 = 规格数值 × 数量
const dosage = specValue * (medicine.quantity || 1)
// 根据药品名称判断用法
let usage = '静脉注射'
if (medicine.medicineName && medicine.medicineName.includes('注射液')) {
usage = '静脉注射'
} else if (medicine.medicineName && medicine.medicineName.includes('片')) {
usage = '口服'
} else if (medicine.medicineName && medicine.medicineName.includes('胶囊')) {
usage = '口服'
}
return {
id: index + 1,
adviceName: medicine.medicineName || '',
dosage: dosage,
unit: specUnit,
usage: usage,
frequency: '临时',
executeTime: new Date().toLocaleString('zh-CN'),
originalMedicine: medicine
}
})
// 打开临时医嘱弹窗
showTemporaryMedical.value = true
}).catch(() => {
temporaryBillingMedicines.value = []
temporaryAdvices.value = []
showTemporaryMedical.value = true
})
}
// 关闭临时医嘱弹窗
function closeTemporaryMedical() {
showTemporaryMedical.value = false
temporaryPatientInfo.value = {}
temporaryBillingMedicines.value = []
temporaryAdvices.value = []
}
// 处理临时医嘱提交
function handleTemporaryMedicalSubmit(data) {
// 这里可以调用后端API保存临时医嘱数据
proxy.$modal.msgSuccess('临时医嘱提交成功')
closeTemporaryMedical()
}
// 处理临时医嘱取消
function handleTemporaryMedicalCancel() {
closeTemporaryMedical()
}
// 处理删除临时医嘱
function handleDeleteTemporaryAdvice(index) {
temporaryAdvices.value.splice(index, 1)
proxy.$modal.msgSuccess('临时医嘱已删除')
}
// 格式化计费弹窗中的日期
function formatChargeDate(date) {
if (!date) return '-'
return new Date(date).toLocaleString()
}
// 计算是否禁用
const disabled = computed(() => {
return Object.keys(chargePatientInfo.value).length === 0
})
// 重置表单
function resetForm() {
Object.assign(form, {
scheduleId: undefined,
applyId: undefined,
patientId: undefined,
visitId: undefined,
operCode: undefined,
operName: undefined,
preoperativeDiagnosis: undefined,
postoperativeDiagnosis: undefined,
scheduleDate: undefined,
sequenceNo: undefined,
isFirstSurgery: 0,
isAllergyMedication: 0,
allergyRemark: undefined,
surgeryNature: undefined,
surgerySite: undefined,
admissionTime: undefined,
entryTime: undefined,
roomCode: undefined,
tableNo: undefined,
anesMethod: undefined,
anesDoctor1Code: undefined,
anesDoctor2Code: undefined,
anesDoctor3Code: undefined,
scrubNurseCode: undefined,
circuNurse1Code: undefined,
circuNurse2Code: undefined,
scrubNurse1Code: undefined,
scrubNurse2Code: undefined,
surgeonCode: undefined,
assistant1Code: undefined,
assistant2Code: undefined,
assistant3Code: undefined,
startTime: undefined,
endTime: undefined,
anesStart: undefined,
anesEnd: undefined,
operStatus: 0,
implantFlag: 0,
implantSerial: undefined,
bloodLoss: undefined,
bloodTrans: undefined,
infectionDiagnosis: undefined,
isolationType: undefined,
patientWeight: undefined,
patientHeight: undefined,
communicationInfo: undefined,
remark: undefined,
patientName: undefined,
gender: undefined,
age: undefined,
orgName: undefined,
applyDeptName: undefined,
surgeonName: undefined,
isExternalExpert: 0,
externalExpertName: undefined
})
if (surgeryRef.value) {
surgeryRef.value.resetFields()
}
}
// 提交表单
function submitForm() {
proxy.$refs['surgeryRef'].validate((valid) => {
if (valid) {
const submitData = { ...form }
if (!form.scheduleId) {
// 新增手术安排
addSurgerySchedule(submitData).then((res) => {
proxy.$modal.msgSuccess('新增成功')
open.value = false
getPageList()
}).catch(() => {
proxy.$message.error('新增手术安排失败,请检查表单信息')
})
} else {
// 修改手术安排
updateSurgerySchedule(submitData).then((res) => {
proxy.$modal.msgSuccess('修改成功')
open.value = false
getPageList()
}).catch(() => {
proxy.$message.error('更新手术安排失败,请检查表单信息')
})
}
} else {
proxy.$message.error('请检查表单信息,标红字段为必填项')
}
})
}
// 取消
function cancel() {
open.value = false
isViewMode.value = false
resetForm()
}
// 刷新
function handleRefresh() {
resetForm()
}
// 查找手术申请
function handleFindApply() {
showApplyDialog.value = true
applyQueryParams.pageNo = 1
getSurgicalScheduleList()
}
// 获取手术申请列表(用于“查找”弹窗)
function getSurgicalScheduleList() {
applyLoading.value = true
const params = { ...applyQueryParams }
if (params.applyTimeRange && params.applyTimeRange.length === 2) {
params.applyTimeStart = params.applyTimeRange[0]
params.applyTimeEnd = params.applyTimeRange[1]
delete params.applyTimeRange
}
getTestResultPage(params).then((res) => {
// Check if data is nested under data.data or directly under data
const responseData = res.data.data || res.data
applyList.value = responseData.records || []
applyTotal.value = responseData.total || 0
}).catch(() => {
proxy.$modal.msgError('获取手术申请列表失败,请稍后重试')
applyList.value = []
applyTotal.value = 0
})
.finally(() => {
applyLoading.value = false
})
}
const applyQueryParams = reactive({
pageNo: 1,
pageSize: 10,
applyTimeRange: undefined,
applyDeptId: undefined,
mainDoctorId: undefined,
})
// 手术申请查询
function handleApplyQuery() {
applyQueryParams.pageNo = 1
getSurgicalScheduleList()
}
// 重置手术申请查询条件
function resetApplyQuery() {
Object.assign(applyQueryParams, {
pageNo: 1,
pageSize: 10,
applyTimeRange: undefined,
applyDeptId: undefined,
mainDoctorId: undefined,
})
getSurgicalScheduleList()
}
// 取消手术申请查询
function cancelApplyDialog() {
showApplyDialog.value = false
Object.assign(applyQueryParams, {
pageNo: 1,
pageSize: 10,
applyTimeRange: undefined,
applyDeptId: undefined,
mainDoctorId: undefined,
})
applyList.value = []
applyTotal.value = 0
}
// 行点击事件处理
function handleApplyRowClick(row) {
const selectedRows = applyTableRef.value?.getSelectionRows ? applyTableRef.value.getSelectionRows() : []
// 如果已经有选中的行,先清除所有选择
if (selectedRows.length > 0) {
applyTableRef.value.clearSelection()
}
// 然后选择当前行
applyTableRef.value.toggleRowSelection(row)
}
// 表格行样式
function tableRowClassName({ row, rowIndex }) {
// 检查当前行是否被选中
const selectedRows = applyTableRef.value?.getSelectionRows ? applyTableRef.value.getSelectionRows() : []
const isSelected = selectedRows.some(selectedRow => selectedRow.surgeryNo === row.surgeryNo)
return isSelected ? 'selected-row' : ''
}
// 控制表格只能单选
function handleSelectable(row, rowIndex) {
const selectedRows = applyTableRef.value?.getSelectionRows ? applyTableRef.value.getSelectionRows() : []
// 如果还没有选中的行,或者当前行就是已经选中的行,则允许选择
return selectedRows.length === 0 || selectedRows.some(selectedRow => selectedRow.surgeryNo === row.surgeryNo)
}
// 获取手术类型名称
function getSurgeryTypeName(surgeryType) {
if (!surgeryType) return ''
const type = surgery_type.value.find(item => String(item.value) === String(surgeryType))
return type ? type.label : String(surgeryType)
}
// 获取手术等级名称
function getSurgeryLevelName(surgeryLevel) {
if (!surgeryLevel) return ''
const level = surgery_level.value.find(item => String(item.value) === String(surgeryLevel))
return level ? level.label : ''
}
// 获取麻醉方法名称
function getAnesthesiaName(anesMethod) {
if (!anesMethod) return ''
const anesthesia = anesthesiaList.value.find(item => String(item.value) === String(anesMethod))
return anesthesia ? anesthesia.label : ''
}
// 根据出生日期计算年龄
function calculateAge(birthDay) {
if (!birthDay) return ''
const birthDate = new Date(birthDay)
const today = new Date()
let age = today.getFullYear() - birthDate.getFullYear()
const monthDiff = today.getMonth() - birthDate.getMonth()
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
age--
}
return age
}
// 计算属性:格式化申请时间为年月日时分秒
const formattedApplyTime = computed(() => {
if (!form.applyTime) return ''
try {
const date = new Date(form.applyTime)
if (isNaN(date.getTime())) return form.applyTime
return parseTime(date, '{y}-{m}-{d} {h}:{i}:{s}')
} catch (error) {
return form.applyTime
}
})
// 确认手术申请
function confirmApply() {
const selectedRows = applyTableRef.value?.getSelectionRows ? applyTableRef.value.getSelectionRows() : []
if (!selectedRows || selectedRows.length === 0) {
proxy.$modal.msgWarning('请先选择一条手术申请记录')
return
}
const selectedRow = selectedRows[0]
// 填充手术申请信息到表单
form.surgeryNo = selectedRow.surgeryNo // 手术单号对应填入手术单号
form.applyId=selectedRow.applyId// 手术申请id
form.patientId = selectedRow.patientId// 患者id
form.visitId = selectedRow.encounterId // id对应填入就诊id
form.operCode = selectedRow.surgeryNo // 手术单号作为手术编码
form.operName = selectedRow.descJson.surgeryName//手术名称
form.preoperativeDiagnosis = selectedRow.preoperativeDiagnosis
form.patientName = selectedRow.name// 患者姓名对应填入患者姓名
form.gender = selectedRow.gender//患者性别
form.birthDay = selectedRow.birthDay//患者出生日期
form.age = calculateAge(selectedRow.birthDay)//计算患者年龄
form.applyDeptName = selectedRow.applyDeptName//申请部门名称
form.applyDoctorName = selectedRow.applyDoctorName//申请医生
form.applyTime = selectedRow.applyTime//申请时间
form.surgeryType = selectedRow.surgeryTypeEnum//手术类型
form.surgeryNature = selectedRow.surgeryTypeEnum//手术性质
form.surgeonCode = selectedRow.mainSurgeonId//主刀医生id
form.surgeonName = selectedRow.mainSurgeonName//主刀医生姓名
showApplyDialog.value = false
}
// 导出手术安排列表
function handleExport() {
proxy.$modal.confirm('确定要导出当前筛选条件下的手术安排列表吗?').then(() => {
download.downloadGet('/clinical-manage/surgery-schedule/export', queryParams, '手术安排列表.csv')
}).catch(() => {
// 取消导出,不做任何操作
})
}
// 获取行样式
function getRowClassName({ row, rowIndex }) {
if (selectedRow.value && row.scheduleId === selectedRow.value.scheduleId) {
return 'selected-row'
}
return ''
}
</script>
<style scoped>
.app-container {
padding: 20px;
}
.query-form {
margin-bottom: 20px;
}
.search-buttons {
margin-left: 10px;
}
.mb8 {
margin-bottom: 8px;
}
.pagination-container {
margin-top: 20px;
text-align: right;
}
.dialog-header-buttons {
display: flex;
justify-content: flex-end;
margin-bottom: 20px;
}
.dialog-header-buttons .el-button {
margin-left: 10px;
}
.dialog-footer {
display: flex;
justify-content: flex-end;
}
.dialog-footer .el-button {
margin-left: 10px;
}
/* 选中行样式 */
:deep(.el-table .selected-row) {
background-color: #ecf5ff !important;
}
:deep(.el-table .selected-row > td) {
border-bottom: 1px solid #d9ecff !important;
}
</style>