2025-11-25 18:05:18 +08:00

566 lines
19 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>
<div class="title">
<div>
<span>初报人:</span>{{ cbInfo?.confirmer }} &nbsp;&nbsp; <span>报告时间:</span>{{ cbInfo?.confirmdt }}&nbsp;&nbsp;
</div>
<div><span>{{ cbInfo?.jgbz == '2' ? '已初报' : '' }}</span></div>
</div>
<div>
<el-button class="btn_green btns_box" :size="autoSize" v-if="cbInfo?.jgbz != 2"
@click="handleCheck(1, 'cb')">初报审核</el-button>
<el-button class="btns_box" :size="autoSize" v-if="cbInfo?.jgbz == 2"
@click="handleCheck(2, 'cb')">取消审核</el-button>
<el-button class="btns_box" type="primary" :size="autoSize" plain :disabled="cbInfo?.jgbz == '2'"
@click="openItemDictDialog(1)">新增</el-button>
<el-button class="btns_box" type="danger" :size="autoSize" :disabled="cbInfo?.jgbz == '2'" plain
@click="handleBatchDelete(1)">删除</el-button>
<el-button class="btn_green btns_box" :size="autoSize" :disabled="cbInfo?.jgbz == '2'"
@click="zhHandel(1)">组合项目</el-button>
</div>
<CustomTable :data="tableData" :columns="columns" :config="tableConfig" :enable-column-drag="true"
@column-drag-end="handleColumnDragEnd">
<template #xmdh="{ column }">
细菌/结果({{ tableData.length }})项
</template>
<template #od="{ row }">
<el-input v-model="row.od" v-if="cbInfo?.jgbz != '2'" size="small" class="full-width-input foucs-input"
@change="handleCsjgEnter(row, 1)" />
<span v-else>{{ row.od }}</span>
</template>
<template #csjg="{ row }">
<el-input v-model="row.csjg" v-if="cbInfo?.jgbz != '2'" size="small" class="full-width-input"
@change="handleCsjgEnter(row, 1)" @dblclick="handleInputFocus(row, 1)" />
<span v-else>{{ row.csjg }}</span>
</template>
<template #jgbz="{ row }">
<el-select v-model="row.jgbz" class="full-width-input" v-if="cbInfo?.jgbz != '2'" placeholder=""
@change="handleCsjgEnter(row, 1)">
<el-option label="阳性" value="P" />
<el-option label="阴性" value="N" />
</el-select>
<span v-else> {{ formatJgbz(row.jgbz) }}</span>
</template>
<template #cutoff="{ row }">
<el-input v-model="row.cutoff" v-if="cbInfo?.jgbz != '2'" size="small" class="full-width-input"
@change="handleCsjgEnter(row, 1)" />
<span v-else>{{ row.cutoff }}</span>
</template>
<template #alarm_flag="{ row }">
<el-select v-model="row.alarm_flag" class="full-width-input" v-if="cbInfo?.jgbz != '2'" placeholder=""
@change="handleCsjgEnter(row, 1)">
<el-option label="危急值" value="H" />
<el-option label="无" value="" />
</el-select>
<span v-else> {{ row.alarm_flag == 'H' ? '危急值' : '' }}</span>
</template>
<template #germclass="{ row }">
{{ formatDict(row.germclass, 'germclass') }}
</template>
</CustomTable>
<div class="title ertext">
<div>
<span>二报人:</span>{{ erInfo?.confirmer }} &nbsp;&nbsp; <span>报告时间:</span>{{ erInfo?.confirmdt }}&nbsp;&nbsp;
</div>
<div><span>{{ erInfo?.jgbz == '2' ? '已二报' : '' }}</span></div>
</div>
<div>
<el-button class="btn_green btns_box" :size="autoSize" v-if="erInfo?.jgbz != 2"
@click="handleCheck(1, 'erb')">二报审核</el-button>
<el-button class="btns_box" :size="autoSize" v-if="erInfo?.jgbz == 2"
@click="handleCheck(2, 'erb')">取消审核</el-button>
<el-button class="btns_box" type="primary" :size="autoSize" plain :disabled="erInfo?.jgbz == '2'"
@click="openItemDictDialog(2)">新增</el-button>
<el-button class="btns_box" type="danger" :size="autoSize" :disabled="erInfo?.jgbz == '2'" plain
@click="handleBatchDelete(2)">删除</el-button>
<el-button class="btn_green btns_box" :size="autoSize" :disabled="erInfo?.jgbz == '2'"
@click="zhHandel(2)">组合项目</el-button>
</div>
<CustomTable :data="tableData2" :columns="columns" :config="tableConfig" :enable-column-drag="true"
@column-drag-end="handleColumnDragEnd">
<template #xmdh="{ column }">
细菌/结果({{ tableData2.length }})项
</template>
<template #od="{ row }">
<el-input v-model="row.od" v-if="erInfo?.jgbz != '2'" size="small" class="full-width-input foucs-input"
@change="handleCsjgEnter(row, 2)" />
<span v-else>{{ row.od }}</span>
</template>
<template #csjg="{ row }">
<el-input v-model="row.csjg" v-if="erInfo?.jgbz != '2'" size="small" class="full-width-input"
@change="handleCsjgEnter(row, 2)" @dblclick="handleInputFocus(row, 2)" />
<span v-else>{{ row.csjg }}</span>
</template>
<template #jgbz="{ row }">
<el-select v-model="row.jgbz" class="full-width-input" v-if="erInfo?.jgbz != '2'" placeholder=""
@change="handleCsjgEnter(row, 2)">
<el-option label="阳性" value="P" />
<el-option label="阴性" value="N" />
</el-select>
<span v-else> {{ formatJgbz(row.jgbz) }}</span>
</template>
<template #cutoff="{ row }">
<el-input v-model="row.cutoff" v-if="erInfo?.jgbz != '2'" size="small" class="full-width-input"
@change="handleCsjgEnter(row, 2)" />
<span v-else>{{ row.cutoff }}</span>
</template>
<template #alarm_flag="{ row }">
<el-select v-model="row.alarm_flag" class="full-width-input" v-if="erInfo?.jgbz != '2'" placeholder=""
@change="handleCsjgEnter(row, 2)">
<el-option label="危急值" value="H" />
<el-option label="无" value="" />
</el-select>
<span v-else> {{ row.alarm_flag == 'H' ? '危急值' : '' }}</span>
</template>
<template #germclass="{ row }">
{{ formatDict(row.germclass, 'germclass') }}
</template>
</CustomTable>
<!-- 新增明细 -->
<ProjectDetails ref="itemDictRef" :dialog-title="'选择检验项目'" :tableKey="labPatKey" @select="handleItemSelect" />
<!-- 测试结果项目常用结果选择 -->
<projectsJg ref="csjgRef" :tableData='csjgTableData' :dialog-title="'项目常用结果选择'" @selectItem="selectItem"
label="qz" />
<!-- 组合项目 -->
<Combined ref="combinedRef" :queryParams="labPatKey" @dbMbHandle="combinedHandel" />
</div>
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import { LabResultItem, ymTableDataItem } from '@/types/index';
import { changeresult, saveresult, newresult, sampleMedInfo } from '@/api/liswork/micro/index';
import {
check1, check2, uncheck2, unconfirmlog, checkuser, reglimit, deleteresult, allPatquery, emrquery, datalink, changeLinkList,
viewBackup, queryXmVal, printListwork, getresultchangelog, setinputmdl, lockSample, unLockSample, clearnotComplete, clearPrintflag,
noiteMresult, queryXmInfo, setitemInter, queryLabPat
} from "@/api/liswork/work/LisWork";
// @ts-ignore
import ProjectDetails from "@/components/projectDetails/index.vue";
import projectsJg from "@/components/projectsjg/index.vue";
// @ts-ignore
import Combined from "./components/combinedDialog.vue";
import emitter from '@/utils/mitt';
import { ElMessage } from 'element-plus';
import { useCommonStore } from "@/store/modules/commonStore";
import { classCom } from '@/utils/classCom';
const autoSize = classCom.useAutoSize();
const props = defineProps({
labPat: {
type: Object,
required: true
},
//结果主键
labPatKey: {
type: Object,
default: () => { }
},
// 主键仪器参数
instrdComOpt: {
type: Object,
required: true
},
dictData: {
type: Object,
default: () => { }
}
})
const { labPat, labPatKey, instrdComOpt } = toRefs(props);
const tableData = ref<LabResultItem[]>([])
const tableData2 = ref<LabResultItem[]>([])
const cbInfo = ref<any>({})
const erInfo = ref<any>({})
const mbStore = useCommonStore();
watch(labPat, (newVal: any) => {
//获取结果列表
getResultList()
// 获取病人信息
getLabPatInfo()
})
watch(() => tableData, (newValue) => {
// 模板数据
if (labPat.value.jgbz != null && labPat.value.jgbz != 0 && labPat.value.jgbz != 'C') return;
mbList(1)
})
watch(() => tableData2, (newValue) => {
// 模板数据
if (labPat.value.jgbz != null && labPat.value.jgbz != 0 && labPat.value.jgbz != 'C') return;
mbList(2)
})
const getLabPatInfo = () => {
queryLabPat({ jyrq: labPat.value.jyrq, yq: instrdComOpt.value.yq1, ybh: labPat.value.ybh, }).then((response: any) => {
cbInfo.value = response.data;
})
queryLabPat({ jyrq: labPat.value.jyrq, yq: instrdComOpt.value.yq2, ybh: labPat.value.ybh, }).then((response: any) => {
erInfo.value = response.data;
})
}
const getResultList = () => {
// 初级数据
sampleMedInfo({ jyrq: labPat.value.jyrq, yq: instrdComOpt.value.yq1, ybh: labPat.value.ybh, }).then((res: any) => {
if (res.code == 0) {
tableData.value = res.data.map((item: any) => {
return {
...item,
zhxmdh: item.xmdh + ' ' + item.xmmc,
}
})
}
});
// 二级数据
sampleMedInfo({ jyrq: labPat.value.jyrq, yq: instrdComOpt.value.yq2, ybh: labPat.value.ybh, }).then((res: any) => {
if (res.code == 0) {
tableData2.value = res.data.map((item: any) => {
return {
...item,
zhxmdh: item.xmdh + ' ' + item.xmmc,
}
})
}
});
}
const mbList = (type: number) => {
const targetTable = type === 1 ? tableData.value : tableData2.value;
if (mbStore.lxsrs.length > 0) {
mbStore.lxsrs.forEach((mbmc) => {
const data = {
...labPatKey.value,
mbmc: mbmc,
}
setinputmdl(data).then((res: any) => {
if (res.code == 0) {
const existingNames = new Set(targetTable.map((item: any) => item.xmdh))
res.data?.forEach((item: any) => {
if (!existingNames.has(item.xmdh)) {
targetTable.push({ ...item, jyrq: labPat.value.jyrq, zhxmdh: item.xmdh + ' ' + item.xmmc })
existingNames.add(item.xmdh)
}
})
emitter.emit('clearLxsrList')
}
});
});
}
}
// 事件定义
const emits = defineEmits([
'fetchLabResults',
'changeStatus',
'previewHandle'
]);
const columns = ref([
{ label: "细菌/结果", prop: "zhxmdh", align: 'center', visible: true, headerSlot: 'xmdh', width: 150 },
{ label: "菌落计数", prop: "od", align: 'center', visible: true, slot: 'od' },
{ label: "检验结果", prop: "csjg", align: 'center', visible: true, slot: 'csjg' },
{ label: "阴阳性", prop: "jgbz", align: 'center', visible: true, slot: 'jgbz', showOverflowTooltip: false },
{ label: "危急值", prop: "alarm_flag", align: 'center', visible: true, slot: 'alarm_flag', showOverflowTooltip: false },
{ label: "菌属", prop: "germclass", align: 'center', visible: true, slot: 'germclass' },
{ label: "鉴定率", prop: "cutoff", align: 'center', visible: true, slot: 'cutoff' },
{ label: "抗生素组", prop: "bz1", align: 'center', visible: true, width: 120 },
])
const CellStyleHd = ({ row, column, rowIndex, columnIndex }: {
row: any;
column: any;
rowIndex: number;
columnIndex: number;
}) => {
if (column.label == "细菌/结果" && (row.alarm_flag ?? "").trim().length > 0) {
return { background: '#f00 !important', color: '#FFF' };
}
if (column.label == "危急值" && (row.alarm_flag ?? "").trim().length > 0) {
return { background: '#f00 !important', color: '#FFF' };
}
if (column.label == "检验结果" && row.jgbz == "H") {
return { background: '#ffc0c0 !important', color: '#606266' };
}
if (column.label == "检验结果" && row.jgbz == "L") {
return { background: '#8080ff !important', color: '#fff' };
}
if (column.label == "检验结果" && row.jgbz == "P") {
return { background: '#ffc0c0 !important', color: '#606266' };
}
if (column.label == "检验结果" && row.jgbz == "Q") {
return { background: '#ffff80 !important', color: '#606266' };
}
if (column.label == "阴阳性" && row.jgbz == "H") {
return { background: '#ffc0c0 !important', color: '#606266' };
}
if (column.label == "阴阳性" && row.jgbz == "L") {
return { background: '#8080ff !important', color: '#fff' };
}
if (column.label == "阴阳性" && row.jgbz == "P") {
return { background: '#ffc0c0 !important', color: '#606266' };
}
if (column.label == "阴阳性" && row.jgbz == "Q") {
return { background: '#ffff80 !important', color: '#606266' };
}
};
const tableConfig = ref({
height: '32vh',
border: true,
// highlightCurrentRow: true,
cellStyle: CellStyleHd
});
const handleColumnDragEnd = (data: any) => {
columns.value = data.columns;
}
const shType = ref('') // 审核类型 cb初报 erb二报
const bgType = ref(1) // 报告类型 1初报 2二报
const handleCheck = (checkType: number, shtype: string) => {
shType.value = shtype
// yhdh = checkuserid.value
switch (checkType) {
// case 1: // 初审
// check1({ ...labPatKey.value, jyrq: labPat.value.jyrq, yhdh: props.labPat.yhdh }).then((res: any) => {
// emits("changeStatus", props.labPat);
// })
// break;
case 1: // 审核
labPatKey.value.problemId = 0
shHandleCheck()
break;
case 2: // 取消审核
labPatKey.value.problemId = 0
unShHandle()
break;
default:
break;
}
};
const unCheckshow = ref(false);
const reasonText = ref('');
const warningMsgdata = ref('');
const showuploadwarning = ref(false);
const shHandleCheck = () => {
check2({ ...labPatKey.value, jyrq: labPat.value.jyrq, yhdh: labPat.value.yhdh, yq: labPat.value.yq }).then((res: any) => {
if (res.code == "4" && res.problemId === 4) {
labPatKey.value.problemId = res.problemId;
warningMsgdata.value = res.msg;
showuploadwarning.value = true;
}
getLabPatInfo()
})
};
const unShHandle = () => {
uncheck2({ ...labPatKey.value, jyrq: labPat.value.jyrq, yhdh: labPat.value.yhdh, yq: labPat.value.yq }).then((res: any) => {
if (res.code == "4") {
labPatKey.value.problemId = res.problemId;
reasonText.value = res.msg;
unCheckshow.value = true;
}
getLabPatInfo()
})
};
const handleBatchDelete = (type: number) => {
bgType.value = type
}
// 项目结果保存
const handleCsjgEnter = async (row: any, type: number) => {
bgType.value = type
const yq = type === 1 ? instrdComOpt.value.yq1 : instrdComOpt.value.yq2
const targetTable = type === 1 ? tableData.value : tableData2.value;
// 判断数据中包含模板新增的数据 flag
if (targetTable.length == 0) return
const flag = targetTable.some((item: any) => item.changeflag == 2)
if (flag) {
saveresult(targetTable).then((res: any) => {
if (res.code == 0) {
getResultList()
}
})
} else {
if (!row) return
if (row && row.id) {
newresult({ ...row, ybh: labPat.value.ybh, jyrq: labPat.value.jyrq, yq }).then((response: any) => {
ElMessage.success("结果保存成功");
getResultList()
}).catch((error: any) => {
getResultList()
});
} else {
changeresult(row).then((response: any) => {
ElMessage.success("结果保存成功");
getResultList()
}).catch((error: any) => {
getResultList()
});
}
// nextTick(() => {
// const input = document.activeElement;
// if (input?.tagName === "INPUT") input?.blur();
// });
}
};
const itemDictRef = ref();
const openItemDictDialog = (type: number) => {
bgType.value = type
itemDictRef.value.openDictSelector();
};
const handleItemSelect = async (selectedItem: any) => {
const yq = bgType.value === 1 ? instrdComOpt.value.yq1 : instrdComOpt.value.yq2
const targetTable = bgType.value === 1 ? tableData.value : tableData2.value;
// 1. 构造新增行数据
const newRow = {
id: `temp_${Date.now()}_${Math.random().toString(36).substr(2, 8)}`,
xmdh: selectedItem.value,
xmmc: selectedItem.label,
dw: selectedItem.dw || "",
refs: selectedItem.refs || "",
jyrq: labPatKey.value.jyrq,
yq: yq,
ybh: labPatKey.value.ybh,
od: '',
csjg: "",
jgbz: "",
alarm_flag: '',
cutoff: '',
qz: '',
zhxmdh: selectedItem.value + ' ' + selectedItem.label,
};
const isDuplicate = targetTable.some((item: any) => item.xmdh === newRow.xmdh);
if (isDuplicate) return ElMessage.warning(`项目【${newRow.xmmc}】已存在`);
targetTable.push(newRow);
newresult({ ...newRow, ybh: labPat.value.ybh, jyrq: labPat.value.jyrq, yq })
// 5. 自动聚焦
// nextTick(() => {
// selectedRows.value = [newRow];
// tableRef.value.setCurrentRow(newRow);
// tableRef.value.setScrollTo(targetTable.length - 1)
// // 聚焦到新行的输入框
// const inputs = Array.from(document.querySelectorAll('.foucs-input .el-input__inner'))
// .filter(el => el instanceof HTMLElement) as HTMLElement[];
// if (inputs.length > 0) {
// inputs[inputs.length - 1].focus();
// }
// });
// ElMessage.success(`已新增项目:${newRow.xmmc}`);
};
const csjgRef = ref()
const csjgTableData = ref([])
const handleInputFocus = (row: any, type: number) => {
bgType.value = type
// dbRow.value = row
queryXmVal({ yq: labPatKey.value.yq, xmdh: row.xmdh }).then((res: any) => {
if (res.code == 0) {
csjgTableData.value = res.data
}
nextTick(() => {
csjgRef.value.open()
})
})
};
const selectItem = (row: any) => {
const targetTable = bgType.value === 1 ? tableData.value : tableData2.value;
// 查找修改行
const index = targetTable.findIndex((item: any) => item.xmdh == row.xmdh)
targetTable[index].csjg = row.qz
handleCsjgEnter(targetTable[index], bgType.value)
};
// 组合项目
const combinedRef = ref()
const zhHandel = (type: number) => {
bgType.value = type
combinedRef.value.open()
};
const combinedHandel = (row: any) => {
const targetTable = bgType.value === 1 ? tableData.value : tableData2.value;
const data = {
...labPatKey.value,
mbmc: row.mbmc,
}
setinputmdl(data).then((res: any) => {
if (res.code == 0) {
const existingNames = new Set(targetTable.map((item: any) => item.xmdh))
res.data?.forEach((item: any) => {
if (!existingNames.has(item.xmdh)) {
targetTable.push({ ...item, jyrq: labPat.value.jyrq, zhxmdh: item.xmdh + ' ' + item.xmmc })
existingNames.add(item.xmdh)
}
})
handleCsjgEnter(null, bgType.value)
emitter.emit('clearLxsrList')
}
});
};
const formatDict = (v: string, dictType: string) => {
return props.dictData[dictType]?.find((item: any) => item.value == v)?.label || v;
}
const formatJgbz = (v: string) => {
return v == 'H' ? '高' : v == 'L' ? '低' : v == 'N' ? '阴性' : v == 'P' ? '阳性' : v == 'Q' ? '弱阳性' : v == 'M' ? '正常' : ''
}
</script>
<style scoped lang="scss">
.title {
border-bottom: 1px solid #e8e8e8;
display: flex;
justify-content: space-between;
padding: 3px 0;
font-family: SourceHanSansCN, SourceHanSansCN;
span {
color: #057c34;
}
}
.ertext {
margin-top: 10px;
span {
color: #e2e20c;
}
}
</style>