当手术计费弹窗中点击"签发"耗材时,因耗材的locationId(发放库房)为空导致后端异常。 在DoctorStationAdviceAppServiceImpl.handDevice方法中,当locationId为null时,使用登录用户的科室ID作为默认值, 与NurseBillingAppService中的处理方式保持一致。
550 lines
16 KiB
Vue
Executable File
550 lines
16 KiB
Vue
Executable File
<template>
|
||
<div class="app-container">
|
||
<!-- 查询条件区域 -->
|
||
<div class="query-form">
|
||
<el-row :gutter="20">
|
||
<el-col :span="6">
|
||
<el-form-item label="审批状态">
|
||
<el-select
|
||
v-model="queryParams.statusEnum"
|
||
placeholder="请选择审批状态"
|
||
clearable
|
||
filterable
|
||
@focus="loadExamineStatusOptions"
|
||
>
|
||
<el-option
|
||
v-for="option in examineStatusOptions"
|
||
:key="option.value"
|
||
:label="option.label"
|
||
:value="option.value"
|
||
/>
|
||
</el-select>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="8">
|
||
<el-form-item label="申请日期">
|
||
<el-date-picker
|
||
v-model="queryParams.applicantTime"
|
||
type="date"
|
||
placeholder="请选择日期"
|
||
value-format="YYYY-MM-DD"
|
||
format="YYYY-MM-DD"
|
||
clearable
|
||
/>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="6">
|
||
<div class="query-buttons">
|
||
<el-button plain type="primary" @click="handleSearch">查询</el-button>
|
||
<el-button plain type="primary" @click="handleReset">重置</el-button>
|
||
</div>
|
||
</el-col>
|
||
</el-row>
|
||
</div>
|
||
|
||
<el-table
|
||
v-loading="loading"
|
||
:data="adjustmentList"
|
||
tooltip-effect="dark"
|
||
:show-overflow-tooltip="true"
|
||
style="width: 100%"
|
||
>
|
||
<el-table-column label="单据编号" align="center" prop="busNo" min-width="180" />
|
||
<el-table-column label="调价类型" align="center" prop="categoryEnum_enumText" min-width="120" />
|
||
<el-table-column label="审核状态" align="center" prop="statusEnum" min-width="100">
|
||
<template #default="scope">
|
||
<el-tag :type="getStatusTagType(scope.row.statusEnum)">
|
||
{{ scope.row.statusEnum_enumText || '-' }}
|
||
</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="制单人" align="center" prop="applicantId_dictText" min-width="120" />
|
||
<el-table-column label="申请日期" align="center" prop="applicantTime" min-width="180">
|
||
<template #default="scope">
|
||
{{ parseTime(scope.row.applicantTime) }}
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="审核人" align="center" prop="approverId_dictText" min-width="120" />
|
||
<el-table-column label="审核日期" align="center" prop="approvalTime" min-width="180">
|
||
<template #default="scope">
|
||
{{ scope.row.approvalTime ? parseTime(scope.row.approvalTime) : '-' }}
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="操作" align="center" min-width="180">
|
||
<template #default="scope">
|
||
<el-button size="small" type="primary" plain @click="handleDetail(scope.row)">
|
||
{{
|
||
['驳回', '同意'].includes(scope.row.statusEnum_enumText) ? '查看详情' : '查看并审核'
|
||
}}
|
||
</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
|
||
<Pagination
|
||
v-show="total > 0"
|
||
:total="total"
|
||
v-model:page="queryParams.pageNum"
|
||
v-model:limit="queryParams.pageSize"
|
||
@pagination="handlePagination"
|
||
/>
|
||
<!-- 详情弹窗组件 -->
|
||
<DetailDialog
|
||
v-model:visible="detailDialogVisible"
|
||
:detail-data="selectedRow"
|
||
:category-type="categoryType"
|
||
@close="handleDetailClose"
|
||
@approve="handleApprove"
|
||
@reject="handleReject"
|
||
/>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import {onMounted, reactive, ref} from 'vue';
|
||
import {ElMessage} from 'element-plus';
|
||
import {parseTime} from '@/utils/openhis';
|
||
import Pagination from '@/components/Pagination';
|
||
import request from '@/utils/request';
|
||
//import { getPriceAdjustmentPage, getPriceAdjustmentDetail, cancelPriceAdjustment } from './components/api';
|
||
import {
|
||
getExamineStatusOptions,
|
||
rejectPriceAdjustment,
|
||
searchSupplyRequestByActivity,
|
||
searchSupplyRequestByDevice,
|
||
searchSupplyRequestByHealth,
|
||
searchSupplyRequestByMed,
|
||
updateExamineByApproved,
|
||
} from './components/api';
|
||
|
||
import DetailDialog from './components/detailDialog.vue';
|
||
|
||
// 表格数据
|
||
const adjustmentList = ref([]);
|
||
const loading = ref(false);
|
||
const total = ref(0);
|
||
const activeName = ref('1'); // 当前激活的标签页
|
||
// 审核状态选项 - 初始为空数组,后续会通过API加载
|
||
const examineStatusOptions = ref([]);
|
||
const optionsLoading = ref(false);
|
||
|
||
// 查询参数
|
||
const queryParams = reactive({
|
||
pageNum: 1,
|
||
pageSize: 10,
|
||
statusEnum: undefined, // 审核状态
|
||
applicantTime: undefined, // 申请日期
|
||
});
|
||
|
||
// 详情弹窗相关
|
||
const detailDialogVisible = ref(false);
|
||
const selectedRow = ref({});
|
||
const categoryType = ref('');
|
||
|
||
// 状态标签类型
|
||
const getStatusTagType = (status) => {
|
||
const typeMap = {
|
||
1: 'warning', // 待审核
|
||
2: 'primary', // 审核中
|
||
3: 'success', // 同意
|
||
4: 'danger', // 驳回
|
||
};
|
||
return typeMap[status] || 'info';
|
||
};
|
||
|
||
// 处理分页事件
|
||
const handlePagination = (params) => {
|
||
// 将分页组件的参数映射到查询参数
|
||
queryParams.pageNum = params.page;
|
||
queryParams.pageSize = params.limit;
|
||
getList();
|
||
};
|
||
|
||
// 查询数据
|
||
const getList = async () => {
|
||
loading.value = true;
|
||
try {
|
||
// 构造符合后端要求的请求参数
|
||
const requestParams = {
|
||
statusEnum: queryParams.statusEnum,
|
||
pageNo: queryParams.pageNum,
|
||
pageSize: queryParams.pageSize,
|
||
};
|
||
|
||
// 根据后端要求的格式处理日期参数
|
||
if (queryParams.applicantTime) {
|
||
const dateStr = queryParams.applicantTime;
|
||
// requestParams.applicantTime = dateStr; // 原始日期值
|
||
requestParams.applicantTimeSTime = `${dateStr} 00:00:00`; // 当天开始时间
|
||
requestParams.applicantTimeETime = `${dateStr} 23:59:59`; // 当天结束时间
|
||
console.log('applicantTime', requestParams.applicantTime);
|
||
console.log('applicantTimeSTime', requestParams.applicantTimeSTime);
|
||
console.log('applicantTimeETime', requestParams.applicantTimeETime);
|
||
}
|
||
|
||
// 调用新的后端API接口
|
||
const response = await request({
|
||
url: '/inventory-examine-page/getPageByExamine',
|
||
method: 'get',
|
||
params: requestParams,
|
||
});
|
||
|
||
// 处理返回的数据
|
||
if (response && response.code === 200) {
|
||
// 直接从records字段获取数据
|
||
adjustmentList.value = response.data?.records || [];
|
||
// 检查total字段是否正确获取,增加更多调试日志
|
||
total.value = response.data?.total || response.data?.totalCount || 0;
|
||
} else {
|
||
ElMessage.error(response?.msg || '获取调价审核列表失败');
|
||
adjustmentList.value = [];
|
||
total.value = 0;
|
||
}
|
||
} catch (error) {
|
||
ElMessage.error('获取数据异常,请稍后重试');
|
||
adjustmentList.value = [];
|
||
total.value = 0;
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
};
|
||
|
||
// 操作按钮处理函数
|
||
const handleDetail = async (row) => {
|
||
// 保存当前行的调价类型
|
||
categoryType.value = row.categoryEnum_enumText || '';
|
||
|
||
// 调用详情API获取数据
|
||
try {
|
||
// 显示加载状态
|
||
loading.value = true;
|
||
|
||
// 准备API参数
|
||
const params = {
|
||
busNo: row.busNo,
|
||
};
|
||
|
||
// 根据itemCategoryEnum选择不同的API接口
|
||
let response;
|
||
if (row.itemCategoryEnum === 49) {
|
||
// 挂号
|
||
response = await searchSupplyRequestByHealth(params);
|
||
} else if (row.itemCategoryEnum === 48) {
|
||
// 诊疗
|
||
response = await searchSupplyRequestByActivity(params);
|
||
} else if (row.itemCategoryEnum === 47) {
|
||
// 耗材
|
||
response = await searchSupplyRequestByDevice(params);
|
||
} else if (row.itemCategoryEnum === 46) {
|
||
// 药品
|
||
response = await searchSupplyRequestByMed(params);
|
||
}
|
||
|
||
if (response && response.code === 200) {
|
||
// 日志记录原始返回数据
|
||
|
||
// 准备显示数据
|
||
let items = [];
|
||
|
||
// 根据API实际返回格式处理数据
|
||
if (typeof response.data === 'object' && response.data !== null) {
|
||
// 首先尝试获取data数组(根据截图API返回格式)
|
||
if (Array.isArray(response.data.data)) {
|
||
items = response.data.data;
|
||
} else if (Array.isArray(response.data.items)) {
|
||
items = response.data.items;
|
||
} else if (Array.isArray(response.data)) {
|
||
items = response.data;
|
||
} else {
|
||
// 如果只是单个对象,包装成数组
|
||
items = [response.data];
|
||
}
|
||
} else if (Array.isArray(response.data)) {
|
||
items = response.data;
|
||
}
|
||
|
||
// 转换数据格式以便显示
|
||
const formattedItems = items.map((item) => {
|
||
// 基础字段映射
|
||
const baseFields = {
|
||
targetId: item.targetId || item.busNo || item.itemId || item.code || item.id || '-',
|
||
chargeName: item.chargeName || item.itemName || item.name || '-',
|
||
volume: item.totalVolume || item.spec || item.specification || '-',
|
||
price: item.price || item.newprice || item.newPrice || item.afterPrice || '-',
|
||
reason: item.reason || item.sreason || item.adjustReason || item.remark || '-',
|
||
orgName: item.orgName || item.org || '-',
|
||
// 额外字段,用于挂号调价单显示
|
||
name: item.name || item.chargeName || item.itemName || '-',
|
||
originPrice: item.originPrice || '-',
|
||
retailPrice: item.retailPrice || '-',
|
||
originBuyingPrice: item.originBuyingPrice || '-',
|
||
newBuyingPrice: item.newBuyingPrice || '-',
|
||
originRetailPrice: item.originRetailPrice || '-',
|
||
newRetailPrice: item.newRetailPrice || '-',
|
||
};
|
||
return baseFields;
|
||
});
|
||
|
||
// 设置selectedRow,确保格式一致
|
||
selectedRow.value = {
|
||
items: formattedItems,
|
||
createName: row.applicantId_dictText || '-',
|
||
busNo: row.busNo, // 添加busNo字段,用于后续的审核和驳回操作
|
||
statusEnum_enumText: row.statusEnum_enumText, // 添加状态字段,用于控制按钮显示
|
||
};
|
||
|
||
// 显示弹窗
|
||
detailDialogVisible.value = true;
|
||
} else {
|
||
ElMessage.error(response?.msg || '获取详情数据失败');
|
||
}
|
||
} catch (error) {
|
||
ElMessage.error('获取详情数据失败');
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
};
|
||
|
||
// 关闭详情弹窗处理
|
||
const handleDetailClose = () => {
|
||
// 重置选中的行数据和类型
|
||
selectedRow.value = {};
|
||
categoryType.value = '';
|
||
};
|
||
|
||
// 处理审批通过事件
|
||
const handleApprove = async () => {
|
||
try {
|
||
// 获取当前选中行的业务编号
|
||
const busNo = selectedRow.value.busNo;
|
||
|
||
// 调用审核通过API
|
||
const response = await updateExamineByApproved(busNo);
|
||
|
||
if (response && response.code === 200) {
|
||
ElMessage.success('审核通过成功');
|
||
// 关闭详情弹窗
|
||
detailDialogVisible.value = false;
|
||
// 刷新页面数据
|
||
getList();
|
||
} else {
|
||
ElMessage.error(response?.msg || '审核通过失败');
|
||
}
|
||
} catch (error) {
|
||
ElMessage.error('审核通过失败');
|
||
}
|
||
};
|
||
|
||
// 处理驳回事件
|
||
const handleReject = async () => {
|
||
try {
|
||
// 获取当前选中行的业务编号
|
||
const busNo = selectedRow.value.busNo;
|
||
|
||
// 调用驳回API
|
||
const response = await rejectPriceAdjustment(busNo);
|
||
|
||
if (response && response.code === 200) {
|
||
ElMessage.success('驳回成功');
|
||
// 关闭详情弹窗
|
||
detailDialogVisible.value = false;
|
||
// 延迟一点时间再刷新,确保弹窗完全关闭
|
||
setTimeout(async () => {
|
||
await getList();
|
||
}, 300);
|
||
} else {
|
||
ElMessage.error(response?.msg || '驳回失败');
|
||
}
|
||
} catch (error) {
|
||
ElMessage.error('驳回失败');
|
||
}
|
||
};
|
||
|
||
// 处理查询
|
||
const handleSearch = () => {
|
||
queryParams.pageNum = 1; // 重置页码
|
||
getList();
|
||
};
|
||
|
||
// 加载审核状态选项
|
||
const loadExamineStatusOptions = async () => {
|
||
// 如果已经加载过,不再重复加载
|
||
if (examineStatusOptions.value.length > 0) {
|
||
return;
|
||
}
|
||
|
||
optionsLoading.value = true;
|
||
try {
|
||
const response = await getExamineStatusOptions();
|
||
// 先清空选项数组
|
||
examineStatusOptions.value = [];
|
||
|
||
if (response && response.code === 200 && response.data) {
|
||
// 1. 首先检查是否有supplyStatusOptions字段
|
||
if (response.data.supplyStatusOptions) {
|
||
if (Array.isArray(response.data.supplyStatusOptions)) {
|
||
// supplyStatusOptions是数组
|
||
examineStatusOptions.value = response.data.supplyStatusOptions.map((item) => ({
|
||
value: item.code || item.key || item.value,
|
||
label: item.name || item.label || item.value,
|
||
}));
|
||
} else if (typeof response.data.supplyStatusOptions === 'object') {
|
||
// supplyStatusOptions是对象
|
||
examineStatusOptions.value = Object.entries(response.data.supplyStatusOptions).map(
|
||
([key, value]) => ({
|
||
value: key,
|
||
label: value,
|
||
})
|
||
);
|
||
}
|
||
}
|
||
// 2. 如果没有supplyStatusOptions字段,但response.data本身是数组
|
||
else if (Array.isArray(response.data)) {
|
||
examineStatusOptions.value = response.data.map((item) => {
|
||
// 处理可能的JSON字符串格式
|
||
if (typeof item === 'string') {
|
||
try {
|
||
const parsed = JSON.parse(item);
|
||
return {
|
||
value: parsed.value || parsed.code || parsed.key,
|
||
label: parsed.label || parsed.name || parsed.value,
|
||
};
|
||
} catch (e) {
|
||
return {
|
||
value: item,
|
||
label: item,
|
||
};
|
||
}
|
||
}
|
||
return {
|
||
value: item.value || item.code || item.key,
|
||
label: item.label || item.name || item.value,
|
||
};
|
||
});
|
||
}
|
||
// 3. 如果response.data是对象
|
||
else if (typeof response.data === 'object') {
|
||
examineStatusOptions.value = Object.entries(response.data).map(([key, value]) => ({
|
||
value: key,
|
||
label: value,
|
||
}));
|
||
}
|
||
|
||
// 确保选项格式正确
|
||
if (examineStatusOptions.value.length === 0) {
|
||
// 如果没有数据,添加默认的选项
|
||
examineStatusOptions.value = [
|
||
{ value: '', label: '全部' },
|
||
{ value: '1', label: '待审核' },
|
||
{ value: '2', label: '已审核' },
|
||
{ value: '3', label: '已拒绝' },
|
||
];
|
||
} else {
|
||
// 在选项开头添加"全部"选项
|
||
examineStatusOptions.value.unshift({ value: '', label: '全部' });
|
||
}
|
||
} else {
|
||
// 如果API调用失败,使用默认选项
|
||
examineStatusOptions.value = [
|
||
{ value: '', label: '全部' },
|
||
{ value: '1', label: '待审核' },
|
||
{ value: '2', label: '已审核' },
|
||
{ value: '3', label: '已拒绝' },
|
||
];
|
||
}
|
||
} catch (error) {
|
||
// 错误情况下使用默认选项
|
||
examineStatusOptions.value = [
|
||
{ value: '', label: '全部' },
|
||
{ value: '1', label: '待审核' },
|
||
{ value: '2', label: '已审核' },
|
||
{ value: '3', label: '已拒绝' },
|
||
];
|
||
} finally {
|
||
optionsLoading.value = false;
|
||
}
|
||
};
|
||
|
||
// 处理重置
|
||
const handleReset = () => {
|
||
// 重置查询参数
|
||
queryParams.statusEnum = undefined;
|
||
queryParams.applicantTime = undefined;
|
||
queryParams.pageNum = 1;
|
||
getList();
|
||
};
|
||
|
||
// 生命周期 - 加载
|
||
onMounted(() => {
|
||
// 初始加载审核状态选项
|
||
loadExamineStatusOptions();
|
||
getList();
|
||
});
|
||
</script>
|
||
|
||
<style scoped>
|
||
.app-container {
|
||
padding: 20px;
|
||
}
|
||
|
||
.query-form {
|
||
background-color: #fff;
|
||
padding: 20px;
|
||
border-radius: 8px;
|
||
margin-bottom: 20px;
|
||
border: 1px solid #ebeef5;
|
||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
|
||
}
|
||
|
||
.query-buttons {
|
||
display: flex;
|
||
gap: 10px;
|
||
align-items: center;
|
||
height: 100%;
|
||
}
|
||
|
||
/* 确保表单元素垂直居中对齐 */
|
||
:deep(.el-form-item) {
|
||
margin-bottom: 0;
|
||
display: flex;
|
||
align-items: center;
|
||
height: 100%;
|
||
}
|
||
|
||
/* 确保标签和输入框垂直居中 */
|
||
:deep(.el-form-item__label-wrap) {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
:deep(.el-form-item__content) {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
:deep(.el-tabs__content) {
|
||
height: auto;
|
||
}
|
||
|
||
:deep(.demo-tabs > .el-tabs__content) {
|
||
color: #6b778c;
|
||
font-size: 14px;
|
||
}
|
||
|
||
:deep(.el-table) {
|
||
border: 1px solid #ebeef5;
|
||
border-radius: 8px;
|
||
overflow: hidden;
|
||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
|
||
}
|
||
|
||
:deep(.el-table__header-wrapper) {
|
||
border-radius: 8px 8px 0 0;
|
||
overflow: hidden;
|
||
}
|
||
|
||
:deep(.el-table__body-wrapper) {
|
||
border-radius: 0 0 8px 8px;
|
||
overflow: hidden;
|
||
}
|
||
</style> |