985 lines
25 KiB
Vue
Executable File
985 lines
25 KiB
Vue
Executable File
<!--
|
||
* @Author: sjjh
|
||
* @Date: 2025-09-05 21:16:06
|
||
* @Description: 检验申请
|
||
-->
|
||
<template>
|
||
<div class="report-container">
|
||
<div class="report-section">
|
||
<div class="report-title">
|
||
<span>检验申请</span>
|
||
<el-icon
|
||
class="report-refresh-icon"
|
||
:class="{ 'is-loading': loading }"
|
||
@click="handleRefresh"
|
||
>
|
||
<Refresh />
|
||
</el-icon>
|
||
</div>
|
||
<!-- 筛选表单 -->
|
||
<div class="filter-form">
|
||
<el-form
|
||
:inline="true"
|
||
:model="filterForm"
|
||
class="filter-form-content"
|
||
>
|
||
<el-form-item label="申请日期">
|
||
<el-date-picker
|
||
v-model="filterForm.dateRange"
|
||
type="daterange"
|
||
range-separator="至"
|
||
start-placeholder="开始日期"
|
||
end-placeholder="结束日期"
|
||
value-format="YYYY-MM-DD"
|
||
clearable
|
||
style="width: 240px"
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item label="单据状态">
|
||
<el-select
|
||
v-model="filterForm.status"
|
||
placeholder="请选择"
|
||
clearable
|
||
style="width: 150px"
|
||
>
|
||
<el-option
|
||
label="全部"
|
||
value=""
|
||
/>
|
||
<el-option
|
||
label="待签发"
|
||
value="0"
|
||
/>
|
||
<el-option
|
||
label="已签发"
|
||
value="1"
|
||
/>
|
||
<el-option
|
||
label="已采证"
|
||
value="4"
|
||
/>
|
||
<el-option
|
||
label="已送检"
|
||
value="5"
|
||
/>
|
||
<el-option
|
||
label="报告已出"
|
||
value="6"
|
||
/>
|
||
<el-option
|
||
label="已作废"
|
||
value="7"
|
||
/>
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item label="关键字">
|
||
<el-input
|
||
v-model="filterForm.keyword"
|
||
placeholder="申请单号/检验项目"
|
||
clearable
|
||
style="width: 200px"
|
||
@keyup.enter="handleSearch"
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item>
|
||
<el-button
|
||
type="primary"
|
||
:loading="loading"
|
||
@click="handleSearch"
|
||
>
|
||
<el-icon><Search /></el-icon>
|
||
查询
|
||
</el-button>
|
||
<el-button @click="handleReset">
|
||
<el-icon><Refresh /></el-icon>
|
||
重置
|
||
</el-button>
|
||
</el-form-item>
|
||
</el-form>
|
||
</div>
|
||
<div class="report-table-wrapper">
|
||
<vxe-table
|
||
v-loading="loading"
|
||
:data="tableData"
|
||
border
|
||
size="small"
|
||
height="100%"
|
||
style="width: 100%"
|
||
>
|
||
<template #empty>
|
||
<div class="empty-data">
|
||
<el-empty
|
||
description="暂无匹配记录"
|
||
:image-size="80"
|
||
/>
|
||
</div>
|
||
</template>
|
||
<vxe-column
|
||
type="seq"
|
||
title="序号"
|
||
width="60"
|
||
align="center"
|
||
/>
|
||
<vxe-column
|
||
field="patientName"
|
||
title="患者姓名"
|
||
width="120"
|
||
/>
|
||
<vxe-column
|
||
title="申请单名称"
|
||
width="140"
|
||
>
|
||
<template #default="scope">
|
||
<el-tooltip
|
||
:content="buildFullName(scope.row)"
|
||
placement="top"
|
||
:disabled="!scope.row.requestFormDetailList || scope.row.requestFormDetailList.length <= 1"
|
||
>
|
||
<span>{{ buildApplicationName(scope.row) }}</span>
|
||
</el-tooltip>
|
||
</template>
|
||
</vxe-column>
|
||
<vxe-column
|
||
field="createTime"
|
||
title="创建时间"
|
||
width="160"
|
||
/>
|
||
<vxe-column
|
||
field="prescriptionNo"
|
||
title="申请单号"
|
||
width="140"
|
||
/>
|
||
<vxe-column
|
||
title="单据状态"
|
||
width="100"
|
||
align="center"
|
||
>
|
||
<template #default="scope">
|
||
<el-tag
|
||
:type="getBillStatusTagType(scope.row)"
|
||
effect="plain"
|
||
round
|
||
:class="{ 'report-status-tag': isReportStatus(scope.row) }"
|
||
@click="handleStatusClick(scope.row)"
|
||
>
|
||
{{ parseBillStatus(getBillStatus(scope.row)) }}
|
||
</el-tag>
|
||
</template>
|
||
</vxe-column>
|
||
<vxe-column
|
||
title="申请类型"
|
||
width="100"
|
||
align="center"
|
||
>
|
||
<template #default="scope">
|
||
<span>{{ parsePriorityCode(scope.row.descJson) }}</span>
|
||
</template>
|
||
</vxe-column>
|
||
<vxe-column
|
||
title="标本类型"
|
||
width="120"
|
||
align="center"
|
||
>
|
||
<template #default="scope">
|
||
<span>{{ parseSpecimenType(scope.row.descJson) }}</span>
|
||
</template>
|
||
</vxe-column>
|
||
<vxe-column
|
||
field="requesterId_dictText"
|
||
title="申请者"
|
||
width="120"
|
||
/>
|
||
<vxe-column
|
||
title="操作"
|
||
align="center"
|
||
fixed="right"
|
||
width="280"
|
||
>
|
||
<template #default="scope">
|
||
<el-button
|
||
link
|
||
type="primary"
|
||
@click="handleViewDetail(scope.row)"
|
||
>
|
||
详情
|
||
</el-button>
|
||
<template v-if="canManageRow(scope.row) && isPendingStatus(scope.row)">
|
||
<el-button
|
||
link
|
||
type="primary"
|
||
@click="handleEdit(scope.row)"
|
||
>
|
||
修改
|
||
</el-button>
|
||
<el-button
|
||
link
|
||
type="danger"
|
||
@click="handleDelete(scope.row)"
|
||
>
|
||
删除
|
||
</el-button>
|
||
</template>
|
||
<template v-if="canManageRow(scope.row) && isWithdrawableStatus(scope.row)">
|
||
<el-button
|
||
link
|
||
type="warning"
|
||
@click="handleWithdraw(scope.row)"
|
||
>
|
||
撤回
|
||
</el-button>
|
||
</template>
|
||
<template v-if="isReportStatus(scope.row)">
|
||
<el-button
|
||
link
|
||
type="success"
|
||
@click="handleViewReport(scope.row)"
|
||
>
|
||
查看报告
|
||
</el-button>
|
||
</template>
|
||
</template>
|
||
</vxe-column>
|
||
</vxe-table>
|
||
</div>
|
||
</div>
|
||
<!-- 详情弹窗 -->
|
||
<el-dialog
|
||
v-model="detailDialogVisible"
|
||
title="检验申请详情"
|
||
width="800px"
|
||
destroy-on-close
|
||
top="5vh"
|
||
:close-on-click-modal="false"
|
||
>
|
||
<div
|
||
v-if="currentDetail"
|
||
class="applicationShow-container"
|
||
>
|
||
<div class="applicationShow-container-content">
|
||
<el-descriptions
|
||
title="基本信息"
|
||
:column="2"
|
||
>
|
||
<el-descriptions-item label="患者姓名">
|
||
{{
|
||
currentDetail.patientName || '-'
|
||
}}
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="申请单名称">
|
||
{{
|
||
currentDetail.name || '-'
|
||
}}
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="创建时间">
|
||
{{
|
||
currentDetail.createTime || '-'
|
||
}}
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="申请单号">
|
||
{{
|
||
currentDetail.prescriptionNo || '-'
|
||
}}
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="申请者">
|
||
{{
|
||
currentDetail.requesterId_dictText || '-'
|
||
}}
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="就诊ID">
|
||
{{
|
||
currentDetail.encounterId || '-'
|
||
}}
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="申请单ID">
|
||
{{
|
||
currentDetail.requestFormId || '-'
|
||
}}
|
||
</el-descriptions-item>
|
||
</el-descriptions>
|
||
</div>
|
||
|
||
<div
|
||
v-if="descJsonData && hasMatchedFields"
|
||
class="applicationShow-container-content"
|
||
>
|
||
<el-descriptions
|
||
title="申请单描述"
|
||
:column="2"
|
||
>
|
||
<template
|
||
v-for="(value, key) in descJsonData"
|
||
:key="key"
|
||
>
|
||
<el-descriptions-item
|
||
v-if="isFieldMatched(key)"
|
||
:label="getFieldLabel(key)"
|
||
>
|
||
{{ value || '-' }}
|
||
</el-descriptions-item>
|
||
</template>
|
||
</el-descriptions>
|
||
</div>
|
||
|
||
<div
|
||
v-if="currentDetail.requestFormDetailList && currentDetail.requestFormDetailList.length"
|
||
class="applicationShow-container-table"
|
||
>
|
||
<vxe-table
|
||
:data="currentDetail.requestFormDetailList"
|
||
border
|
||
>
|
||
<vxe-column
|
||
type="seq"
|
||
title="序号"
|
||
width="60"
|
||
align="center"
|
||
/>
|
||
<vxe-column
|
||
field="adviceName"
|
||
title="医嘱名称"
|
||
/>
|
||
<vxe-column
|
||
field="quantity"
|
||
title="数量"
|
||
width="80"
|
||
align="center"
|
||
/>
|
||
<vxe-column
|
||
field="unitCode_dictText"
|
||
title="单位"
|
||
width="100"
|
||
/>
|
||
<vxe-column
|
||
field="totalPrice"
|
||
title="总价"
|
||
width="100"
|
||
align="right"
|
||
/>
|
||
</vxe-table>
|
||
</div>
|
||
</div>
|
||
<template #footer>
|
||
<el-button @click="detailDialogVisible = false">
|
||
关闭
|
||
</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
<!-- 编辑检验申请单弹窗 -->
|
||
<el-dialog
|
||
v-model="editDialogVisible"
|
||
title="编辑检验申请单"
|
||
width="1200px"
|
||
destroy-on-close
|
||
top="5vh"
|
||
:close-on-click-modal="false"
|
||
>
|
||
<LaboratoryTests
|
||
ref="editFormRef"
|
||
:edit-data="editRowData"
|
||
@submit-ok="handleEditSubmitOk"
|
||
/>
|
||
<template #footer>
|
||
<el-button @click="editDialogVisible = false">
|
||
取消
|
||
</el-button>
|
||
<el-button
|
||
type="primary"
|
||
@click="submitEditForm"
|
||
>
|
||
确认
|
||
</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import {computed, getCurrentInstance, nextTick, ref, watch} from 'vue';
|
||
import {Refresh, Search} from '@element-plus/icons-vue';
|
||
import {patientInfo} from '../../store/patient.js';
|
||
import {getInspection, deleteRequestForm, withdrawRequestForm, getProofResult} from './api';
|
||
import {getDepartmentList} from '@/api/public.js';
|
||
import LaboratoryTests from '../order/applicationForm/laboratoryTests.vue';
|
||
import useUserStore from '@/store/modules/user';
|
||
import auth from '@/plugins/auth';
|
||
|
||
const userStore = useUserStore();
|
||
|
||
const { proxy } = getCurrentInstance();
|
||
|
||
const tableData = ref([]);
|
||
const loading = ref(false);
|
||
const detailDialogVisible = ref(false);
|
||
const editDialogVisible = ref(false);
|
||
const editRowData = ref(null);
|
||
const editFormRef = ref(null);
|
||
const currentDetail = ref(null);
|
||
const descJsonData = ref(null);
|
||
const orgOptions = ref([]);
|
||
|
||
// 筛选表单数据
|
||
const filterForm = ref({
|
||
dateRange: [], // [startDate, endDate]
|
||
status: '', // 单据状态
|
||
keyword: '', // 关键字搜索
|
||
});
|
||
|
||
const fetchData = async () => {
|
||
if (!patientInfo.value?.encounterId) {
|
||
tableData.value = [];
|
||
loading.value = false;
|
||
return;
|
||
}
|
||
loading.value = true;
|
||
try {
|
||
// 构建查询参数
|
||
const params = { encounterId: patientInfo.value.encounterId };
|
||
|
||
// 添加日期范围筛选
|
||
if (filterForm.value.dateRange && filterForm.value.dateRange.length === 2) {
|
||
params.startDate = filterForm.value.dateRange[0];
|
||
params.endDate = filterForm.value.dateRange[1];
|
||
}
|
||
|
||
// 添加状态筛选
|
||
if (filterForm.value.status !== '' && filterForm.value.status !== undefined) {
|
||
params.status = filterForm.value.status;
|
||
}
|
||
|
||
// 添加关键字搜索
|
||
if (filterForm.value.keyword && filterForm.value.keyword.trim()) {
|
||
params.keyword = filterForm.value.keyword.trim();
|
||
}
|
||
|
||
const res = await getInspection(params);
|
||
if (res.code === 200 && res.data) {
|
||
const raw = res.data?.records || res.data;
|
||
const list = Array.isArray(raw) ? raw : [raw];
|
||
tableData.value = list.filter(Boolean).sort(sortByCreateTimeDesc);
|
||
} else {
|
||
tableData.value = [];
|
||
}
|
||
} catch (e) {
|
||
proxy.$modal?.msgError?.(e.message || '查询检验申请失败');
|
||
tableData.value = [];
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
};
|
||
|
||
const handleRefresh = async () => {
|
||
if (loading.value || !patientInfo.value?.encounterId) return;
|
||
await fetchData();
|
||
};
|
||
|
||
/**
|
||
* 查询按钮处理
|
||
*/
|
||
const handleSearch = async () => {
|
||
if (!patientInfo.value?.encounterId) {
|
||
proxy.$modal?.msgWarning?.('请先选择患者');
|
||
return;
|
||
}
|
||
await fetchData();
|
||
};
|
||
|
||
/**
|
||
* 重置按钮处理
|
||
*/
|
||
const handleReset = () => {
|
||
// 重置筛选条件为默认值
|
||
filterForm.value.dateRange = [];
|
||
filterForm.value.status = '';
|
||
filterForm.value.keyword = '';
|
||
// 重新加载数据
|
||
fetchData();
|
||
};
|
||
|
||
const labelMap = {
|
||
categoryType: '项目类别',
|
||
targetDepartment: '发往科室',
|
||
symptom: '症状',
|
||
sign: '体征',
|
||
clinicalDiagnosis: '临床诊断',
|
||
otherDiagnosis: '其他诊断',
|
||
relatedResult: '相关结果',
|
||
attention: '注意事项',
|
||
applicationType: '申请类型',
|
||
specimenName: '标本类型',
|
||
executeTime: '执行时间',
|
||
};
|
||
|
||
/**
|
||
* 解析单据状态
|
||
* @param {string|number} status - 状态码
|
||
* @returns {string} 状态文本
|
||
*/
|
||
const getBillStatus = (row) => {
|
||
return row?.billStatus ?? row?.status ?? row?.statusEnum ?? row?.applyStatus;
|
||
};
|
||
|
||
const parseBillStatus = (status) => {
|
||
const statusMap = {
|
||
'0': '待签发',
|
||
'1': '已签发',
|
||
'2': '已采证',
|
||
'3': '已送检',
|
||
'4': '已采证',
|
||
'5': '已送检',
|
||
'6': '报告已出',
|
||
'8': '报告已出',
|
||
'7': '已作废',
|
||
};
|
||
return statusMap[String(status)] || '-';
|
||
};
|
||
|
||
const getBillStatusTagType = (row) => {
|
||
const typeMap = {
|
||
'0': 'info',
|
||
'1': 'primary',
|
||
'2': 'primary',
|
||
'3': 'warning',
|
||
'4': 'primary',
|
||
'5': 'warning',
|
||
'6': 'success',
|
||
'7': 'danger',
|
||
'8': 'success',
|
||
};
|
||
return typeMap[String(getBillStatus(row))] || 'info';
|
||
};
|
||
|
||
const isPendingStatus = (row) => {
|
||
const status = getBillStatus(row);
|
||
return status === undefined || status === null || status === '' || String(status) === '0';
|
||
};
|
||
|
||
const isWithdrawableStatus = (row) => String(getBillStatus(row)) === '1';
|
||
|
||
const isReportStatus = (row) => ['6', '8'].includes(String(getBillStatus(row)));
|
||
|
||
/**
|
||
* 是否可管理该申请单:申请者本人或管理员
|
||
*/
|
||
const canManageRow = (row) => {
|
||
if (auth.hasRole('admin')) {
|
||
return true;
|
||
}
|
||
const currentPractitionerId = userStore.practitionerId;
|
||
const requesterId = row?.requesterId;
|
||
if (!currentPractitionerId || !requesterId) {
|
||
return false;
|
||
}
|
||
return String(currentPractitionerId) === String(requesterId);
|
||
};
|
||
|
||
const sortByCreateTimeDesc = (a, b) => {
|
||
const aTime = a?.createTime ? new Date(a.createTime).getTime() : 0;
|
||
const bTime = b?.createTime ? new Date(b.createTime).getTime() : 0;
|
||
return bTime - aTime;
|
||
};
|
||
|
||
const handleStatusClick = (row) => {
|
||
if (isReportStatus(row)) {
|
||
handleViewReport(row);
|
||
}
|
||
};
|
||
|
||
const pickReportUrl = (data, row) => {
|
||
if (!data) return '';
|
||
if (typeof data === 'string') return data;
|
||
|
||
const raw = data.records || data;
|
||
const list = Array.isArray(raw) ? raw : [raw];
|
||
const matched =
|
||
list.find((item) => {
|
||
const reportNo = item.busNo || item.reportNo || item.applyNo || item.prescriptionNo;
|
||
return reportNo && row.prescriptionNo && String(reportNo) === String(row.prescriptionNo);
|
||
}) || list[0];
|
||
|
||
return matched?.requestUrl || matched?.pdfUrl || matched?.reportUrl || matched?.url || '';
|
||
};
|
||
|
||
const handleViewReport = async (row) => {
|
||
try {
|
||
const res = await getProofResult({
|
||
encounterId: row.encounterId || patientInfo.value?.encounterId,
|
||
prescriptionNo: row.prescriptionNo,
|
||
});
|
||
if (res?.code === 200) {
|
||
const url = pickReportUrl(res.data, row);
|
||
if (url) {
|
||
window.open(url, '_blank');
|
||
return;
|
||
}
|
||
}
|
||
proxy.$modal?.msgWarning?.('暂未获取到检验报告链接');
|
||
} catch (e) {
|
||
proxy.$modal?.msgError?.(e.message || '获取检验报告失败');
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 解析申请类型(优先级代码)
|
||
* @param {string} descJson - JSON字符串
|
||
* @returns {string} 申请类型文本
|
||
*/
|
||
const parsePriorityCode = (descJson) => {
|
||
if (!descJson) return '-';
|
||
try {
|
||
const obj = JSON.parse(descJson);
|
||
// applicationType: 0-普通, 1-急诊
|
||
return obj.applicationType === 1 ? '急' : '普通';
|
||
} catch (e) {
|
||
console.error('解析 descJson 失败:', e);
|
||
return '-';
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 解析标本类型
|
||
* @param {string} descJson - JSON字符串
|
||
* @returns {string} 标本类型名称
|
||
*/
|
||
const parseSpecimenType = (descJson) => {
|
||
if (!descJson) return '-';
|
||
try {
|
||
const obj = JSON.parse(descJson);
|
||
// 优先取标签字段(新格式),其次取码值字段,兼容旧数据 sampleType
|
||
return obj.specimenNameLabel || obj.specimenName || obj.sampleType || '-';
|
||
} catch (e) {
|
||
console.error('解析 descJson 失败:', e);
|
||
return '-';
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 根据申请单详情构建申请单名称
|
||
* 单一项目:直接显示项目全名(不拼接数量)
|
||
* 多个项目:显示"项目1 + 项目2 等n项"缩略格式
|
||
*/
|
||
const buildApplicationName = (row) => {
|
||
const details = row.requestFormDetailList;
|
||
if (!details || details.length === 0) {
|
||
return row.name || '-';
|
||
}
|
||
if (details.length === 1) {
|
||
// 单一项目:直接显示项目全名
|
||
return details[0].adviceName || row.name || '-';
|
||
}
|
||
// 多个项目:项目1 + 项目2 + ...
|
||
const names = details.map((d) => d.adviceName).filter(Boolean);
|
||
if (names.length === 0) return row.name || '-';
|
||
return names.join(' + ');
|
||
};
|
||
|
||
/**
|
||
* 获取申请单完整项目名称列表(用于 tooltip 展示)
|
||
*/
|
||
const buildFullName = (row) => {
|
||
const details = row.requestFormDetailList;
|
||
if (!details || details.length === 0) return row.name || '-';
|
||
return details.map((d) => d.adviceName).filter(Boolean).join(' + ') || row.name || '-';
|
||
};
|
||
|
||
const isFieldMatched = (key) => {
|
||
return key in labelMap;
|
||
};
|
||
|
||
const getFieldLabel = (key) => {
|
||
return labelMap[key] || key;
|
||
};
|
||
|
||
const hasMatchedFields = computed(() => {
|
||
if (!descJsonData.value) return false;
|
||
return Object.keys(descJsonData.value).some((key) => isFieldMatched(key));
|
||
});
|
||
|
||
/** 查询科室 */
|
||
const getLocationInfo = async () => {
|
||
try {
|
||
const res = await getDepartmentList();
|
||
orgOptions.value = Array.isArray(res.data) ? res.data : [];
|
||
} catch (e) {
|
||
console.warn('科室列表加载失败:', e.message);
|
||
orgOptions.value = [];
|
||
}
|
||
};
|
||
|
||
const recursionFun = (targetDepartment) => {
|
||
if (!targetDepartment) return '';
|
||
const findNode = (list, id) => {
|
||
if (!list || list.length === 0) return '';
|
||
for (const item of list) {
|
||
if (item.id == id) return item.name;
|
||
const found = findNode(item.children, id);
|
||
if (found) return found;
|
||
}
|
||
return '';
|
||
};
|
||
return findNode(orgOptions.value, targetDepartment);
|
||
};
|
||
|
||
const handleViewDetail = async (row) => {
|
||
// 确保科室数据已加载,以便将 ID 解析为名称
|
||
if (!orgOptions.value || orgOptions.value.length === 0) {
|
||
await getLocationInfo();
|
||
}
|
||
|
||
currentDetail.value = row;
|
||
// 解析 descJson
|
||
if (row.descJson) {
|
||
try {
|
||
const obj = JSON.parse(row.descJson);
|
||
// 将发往科室 ID 转换为名称
|
||
if (obj.targetDepartment) {
|
||
const deptName = recursionFun(obj.targetDepartment);
|
||
if (deptName) {
|
||
obj.targetDepartment = deptName;
|
||
}
|
||
}
|
||
// 转换申请类型编码为可读文本
|
||
if (obj.applicationType === 0) obj.applicationType = '普通';
|
||
else if (obj.applicationType === 1) obj.applicationType = '急诊';
|
||
descJsonData.value = obj;
|
||
} catch (e) {
|
||
console.error('解析 descJson 失败:', e);
|
||
descJsonData.value = null;
|
||
}
|
||
} else {
|
||
descJsonData.value = null;
|
||
}
|
||
detailDialogVisible.value = true;
|
||
};
|
||
|
||
/**
|
||
* 修改检验申请单(待签发状态)
|
||
*/
|
||
const handleEdit = async (row) => {
|
||
editRowData.value = row;
|
||
editDialogVisible.value = true;
|
||
await nextTick();
|
||
editFormRef.value?.getList?.();
|
||
editFormRef.value?.getLocationInfo?.();
|
||
editFormRef.value?.getDiagnosisList?.();
|
||
};
|
||
|
||
/**
|
||
* 编辑弹窗提交成功回调
|
||
*/
|
||
const handleEditSubmitOk = async () => {
|
||
editDialogVisible.value = false;
|
||
editRowData.value = null;
|
||
proxy.$modal?.msgSuccess?.('修改成功');
|
||
await fetchData();
|
||
};
|
||
|
||
/**
|
||
* 编辑弹窗提交按钮
|
||
*/
|
||
const submitEditForm = () => {
|
||
if (editFormRef.value?.submit) {
|
||
editFormRef.value.submit();
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 删除检验申请单(仅待签发状态可删除)
|
||
*/
|
||
const handleDelete = async (row) => {
|
||
try {
|
||
await proxy.$modal?.confirm?.('确认作废该申请单吗?作废后不可撤销');
|
||
} catch {
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const res = await deleteRequestForm({ requestFormId: row.requestFormId });
|
||
if (res?.code === 200) {
|
||
proxy.$modal?.msgSuccess?.('删除成功');
|
||
await fetchData();
|
||
} else {
|
||
proxy.$modal?.msgError?.(res?.msg || '删除失败');
|
||
}
|
||
} catch {
|
||
// 响应拦截器已处理错误提示,此处静默
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 撤回检验申请单(已签发且未采证状态可撤回)
|
||
*/
|
||
const handleWithdraw = async (row) => {
|
||
try {
|
||
await proxy.$modal?.confirm?.(
|
||
'确认撤回该申请单吗?撤回后申请单及关联医嘱将恢复为待签发状态,护士站将同步更新。'
|
||
);
|
||
} catch {
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const res = await withdrawRequestForm({ requestFormId: row.requestFormId });
|
||
if (res?.code === 200) {
|
||
proxy.$modal?.msgSuccess?.('撤回成功');
|
||
await fetchData();
|
||
} else {
|
||
proxy.$modal?.msgError?.(res?.msg || '撤回失败');
|
||
}
|
||
} catch {
|
||
// 响应拦截器已处理错误提示,此处静默
|
||
}
|
||
};
|
||
|
||
watch(
|
||
() => patientInfo.value?.encounterId,
|
||
async (val) => {
|
||
if (val) {
|
||
// 设置默认日期范围为近7天
|
||
const today = new Date();
|
||
const sevenDaysAgo = new Date(today);
|
||
sevenDaysAgo.setDate(today.getDate() - 6); // 包含今天共7天
|
||
|
||
// 格式化为 YYYY-MM-DD
|
||
const formatDate = (date) => {
|
||
const year = date.getFullYear();
|
||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||
const day = String(date.getDate()).padStart(2, '0');
|
||
return `${year}-${month}-${day}`;
|
||
};
|
||
|
||
filterForm.value.dateRange = [
|
||
formatDate(sevenDaysAgo),
|
||
formatDate(today)
|
||
];
|
||
|
||
await Promise.all([fetchData(), getLocationInfo()]);
|
||
} else {
|
||
tableData.value = [];
|
||
// 重置筛选条件
|
||
filterForm.value.dateRange = [];
|
||
filterForm.value.status = '';
|
||
filterForm.value.keyword = '';
|
||
}
|
||
},
|
||
{ immediate: true }
|
||
);
|
||
|
||
defineExpose({
|
||
refresh: fetchData,
|
||
});
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.report-container {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 12px;
|
||
padding: 8px 0;
|
||
height: 100%;
|
||
}
|
||
|
||
.report-section {
|
||
background: #fff;
|
||
flex: 1;
|
||
min-height: 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.report-title {
|
||
font-weight: 600;
|
||
margin-bottom: 8px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 0 8px;
|
||
}
|
||
|
||
.filter-form {
|
||
padding: 12px 8px;
|
||
border-bottom: 1px solid #ebeef5;
|
||
background-color: #fafafa;
|
||
}
|
||
|
||
.filter-form-content {
|
||
:deep(.el-form-item) {
|
||
margin-bottom: 0;
|
||
margin-right: 16px;
|
||
}
|
||
|
||
:deep(.el-form-item__label) {
|
||
font-weight: 500;
|
||
}
|
||
}
|
||
|
||
.report-table-wrapper {
|
||
flex: 1;
|
||
min-height: 0;
|
||
overflow: auto;
|
||
padding: 0 8px;
|
||
}
|
||
|
||
.empty-data {
|
||
padding: 40px 0;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
}
|
||
|
||
.report-refresh-icon {
|
||
cursor: pointer;
|
||
color: #64748B;
|
||
transition: color 0.2s;
|
||
font-size: 18px;
|
||
}
|
||
|
||
.report-refresh-icon:hover {
|
||
color: #3B82F6;
|
||
}
|
||
|
||
.report-refresh-icon.is-loading {
|
||
animation: rotating 2s linear infinite;
|
||
}
|
||
|
||
.report-status-tag {
|
||
cursor: pointer;
|
||
background-color: #f0f9eb !important;
|
||
border-color: #10B981 !important;
|
||
color: #529b2e !important;
|
||
font-weight: 600;
|
||
}
|
||
|
||
@keyframes rotating {
|
||
0% {
|
||
transform: rotate(0deg);
|
||
}
|
||
100% {
|
||
transform: rotate(360deg);
|
||
}
|
||
}
|
||
|
||
:deep(.el-dialog__body) {
|
||
padding-top: 0 !important;
|
||
}
|
||
|
||
.applicationShow-container {
|
||
display: flex;
|
||
flex-direction: column;
|
||
max-height: 70vh;
|
||
width: 100%;
|
||
overflow-y: auto;
|
||
|
||
.applicationShow-container-content {
|
||
flex-shrink: 0;
|
||
margin-bottom: 0px;
|
||
}
|
||
|
||
.applicationShow-container-table {
|
||
flex-shrink: 0;
|
||
max-height: 300px;
|
||
overflow: auto;
|
||
}
|
||
}
|
||
</style>
|