387 lines
11 KiB
Vue
Raw Normal View History

2026-03-09 14:09:14 +08:00
/**
* @file index.vue 科内开单
* @author: w
* @since: 2026-03-02
*/
<template>
<div class="app-container">
<el-row :gutter="10" class="row-box">
<el-col :span="16" style="height: 100%;">
<div class="box-shadow">
<el-row class="top-box">
<el-col :span="7">
<el-button type="primary" size="small" @click="saveHandle">保存</el-button>
<el-button type="primary" size="small" @click="addHandle">新增</el-button>
<el-button type="danger" size="small" @click="deleteHandle">删除</el-button>
</el-col>
<el-col :span="17">
<div class="tips">
项目检索: <el-input v-model="searchKey" size="small" style="width: 150px;" @clear="filterDictData"
@input="filterDictData" /> &nbsp;
</div>
</el-col>
</el-row>
<el-row :gutter="5" style="height: 100%;">
<el-col :span="7">
<Info v-model:labPat="labpat" />
</el-col>
<el-col :span="17" style="height: 100%;">
<div class="xmBoxs">
<!-- <template v-for="item in filterData" :key="item.sflbmc">
<div class="title">{{ item.sflbmc }}</div>
<el-checkbox-group v-model="checkboxs" @change="handleChecksChange">
<el-row>
<el-col :span="12" v-for="v in item.children" :key="v.sfxmdh">
<el-checkbox :value="v.sfxmdh">
{{ v.sfxmmc }}
</el-checkbox>
</el-col>
</el-row>
</el-checkbox-group>
</template> -->
</div>
<div style="height: calc(40% - 30px)">
<CustomVxeTable :table-data="sqXmList" :columns="sqXmColumns" @cell-dblclick="dbRowclick"
:scrollYConfig="{ enabled: true, rSize: 30, height: '100%', }" class="mytable-style">
<template #zt="{ row }">
申请
</template>
</CustomVxeTable>
</div>
</el-col>
</el-row>
</div>
</el-col>
<el-col :span="8" style="height: 100%;">
<div class="box-shadow">
2026-03-09 15:04:59 +08:00
<el-form :model="searchForm" inline size="small">
<el-form-item label="姓名:" prop="brxm">
<el-input v-model="searchForm.brxm" clearable style="width: 9rem;" @change="handleQuery" />
</el-form-item>
<el-form-item label="状态:" prop="zt">
<SelectTable v-model:data="searchForm.zt" :tableData="lis_req_type" clearable style="width: 9rem;"
size="small" @getDataValue="handleQuery" />
</el-form-item>
<el-form-item label="" prop="begdate">
<div class="radio_box">
<el-radio-group v-model="searchForm.days" @change="handleQuery">
<el-radio :value="3">近3天</el-radio>
<el-radio :value="7">近7天</el-radio>
<el-radio :value="0">此日
<el-icon>
<Right />
</el-icon>
</el-radio>
</el-radio-group>
<el-date-picker v-model="searchForm.begdate" type="date" value-format="YYYY-MM-DD" style="width: 10rem;"
@change="handleQuery" />
</div>
</el-form-item>
</el-form>
2026-03-09 14:09:14 +08:00
<div class="table-box">
<CustomVxeTable :table-data="labPatList" :loading="loading" :columns="tableColumns"
@current-change="handleRowClick" size="small"
:scrollYConfig="{ enabled: true, rSize: 30, height: '100%', }" :row-style="rowStyle"
:cell-style="cellStyle" class="mytable-style" ref="tableRef" :enable-column-drag="true"
@column-drag-end="handleColumnDragEnd">
<template #brxb="{ row }">
{{ formatDict(row.brxb, 'SX') }}
</template>
<template #nldw="{ row }">
{{ formatDict(row.nldw, 'AU') }}
</template>
<template #yblx="{ row }">
{{ formatDict(row.yblx, 'BT') }}
</template>
<template #ksdh="{ row }">
{{ formatDict(row.ksdh, 'DP') }}
</template>
<template #brly="{ row }">
{{ formatDict(row.brly, 'PT') }}
</template>
<template #zt="{ row }">
{{ formatDictzt(row.zt) }}
</template>
</CustomVxeTable>
</div>
</div>
</el-col>
</el-row>
</div>
</template>
<script setup>
import Info from './components/info.vue'
import { getDictData, formatDict, dictData } from '@/hooks'
import { queryXmInfoList, saveReqInfo, queryPatList, queryPatDetail } from '@/api/liswork/order'
import dayjs from 'dayjs'
import { ElMessage } from 'element-plus'
import { getFirstLetter } from '@/utils/pinyin';
const { proxy } = getCurrentInstance();
const { lis_req_type } = proxy.useDict("lis_req_type");
const labpat = ref({
zt: '1'
})
const checkboxs = ref([])
const searchKey = ref('')
const loading = ref(false)
const tableRef = useTemplateRef('tableRef')
const labPatList = ref([])
2026-03-09 15:04:59 +08:00
const searchForm = ref({})
2026-03-09 14:09:14 +08:00
const tableColumns = ref([
{ field: 'brxm', title: '姓名', width: 40, align: 'center', resizable: true, },
{ field: 'zt', title: '状态', width: 40, align: 'center', slotName: 'zt', resizable: true, },
{ field: 'sqsj', title: '登记时间', width: 80, align: 'center', resizable: true },
{ field: 'sqr', title: '登记人', width: 80, align: 'center', resizable: true },
{ field: 'jymd', title: '项目', align: 'center', resizable: true },
])
const rowStyle = ({ row }) => {
}
const cellStyle = ({ row, column }) => {
}
const handleRowClick = (row) => {
queryPatDetail({ sqh: row.sqh }).then(res => {
labpat.value = res.data.labReqmain
labpat.value.zt = labpat.value.zt.trim()
sqXmList.value = res.data.reqInputLisWorkVOList
checkboxs.value = res.data.reqInputLisWorkVOList.map(item => item.sfxmdh)
})
}
2026-03-09 15:04:59 +08:00
const handleQuery = () => {
searchForm.value.begdate = dayjs(searchForm.value.begdate).format('YYYY-MM-DD') + ' 00:00:00'
searchForm.value.enddate = dayjs(searchForm.value.begdate).format('YYYY-MM-DD') + ' 23:59:59'
queryPatList(searchForm.value).then(res => {
2026-03-09 14:09:14 +08:00
labPatList.value = res.data
if (!res.data.length) {
labpat.value = {
zt: '1'
}
} else {
handleRowClick(res.data[0])
}
})
}
const saveHandle = () => {
if (!labpat.value.brdh) return ElMessage.warning('病人代号不能为空!')
if (!labpat.value.yblx) return ElMessage.warning('样本类型不能为空!')
if (!sqXmList.value.length) return ElMessage.warning('请选择项目!')
const data = {
labReqmain: labpat.value,
reqInputLisWorkVOList: sqXmList.value
}
saveReqInfo(data).then(res => {
handleQuery()
})
}
const addHandle = () => {
labpat.value = {
zt: '1'
}
}
const deleteHandle = () => {
}
// 更新列配置
const handleColumnDragEnd = (data) => {
tableColumns.value = [];
nextTick(() => {
tableColumns.value = [...data.columns];
});
}
const filterData = ref([])
const xmColumns = ref([
{ field: 'sflbmc', title: '类别', align: 'center', resizable: true },
{ field: 'sfxmdh', title: '代号', align: 'center', resizable: true },
{ field: 'sfxmmc', title: '简称', align: 'center', width: 150, resizable: true },
{ field: 'dj', title: '单价', align: 'center', resizable: true },
{ field: 'spec', title: '规格', align: 'center', resizable: true },
{ field: 'yblx', title: '样本', align: 'center', resizable: true },
])
const processedTableData = ref([])
const filterDictData = () => {
const key = searchKey.value.trim().toLowerCase();
if (!key) {
// 空搜索时显示全部预处理数据
filterData.value = resultList([...processedTableData.value])
return;
}
filterData.value = resultList(processedTableData.value.filter((item) => {
const matchLabel = item.pinyin.toString().toLowerCase().includes(key);
return matchLabel;
})
)
}
const processTableData = (data) => {
return data.map((item) => {
const pinyinMap = {};
pinyinMap['pinyin'] = getFirstLetter(item.sfxmmc).toLowerCase();
return { ...item, ...pinyinMap };
});
};
const sqXmList = ref([])
const sqXmColumns = ref([
{ field: 'sflbmc', title: '类别', align: 'center', resizable: true },
{ field: 'sfxmdh', title: '代号', align: 'center', resizable: true },
{ field: 'sfxmmc', title: '简称', align: 'center', width: 150, resizable: true },
{ field: 'dj', title: '单价', align: 'center', resizable: true },
{ field: 'spec', title: '规格', align: 'center', resizable: true },
{ field: 'yblx', title: '样本', align: 'center', resizable: true },
{ field: 'zt', title: '状态', align: 'center', resizable: true, slotName: 'zt' },
])
const handleChecksChange = (val) => {
console.log('val==>', val);
sqXmList.value = []
val.forEach(item => {
const existingItem = processedTableData.value.find((row) => row.sfxmdh == item)
if (existingItem) {
sqXmList.value.push(existingItem)
}
})
}
const dbRowclick = ({ row }) => {
const index = sqXmList.value.findIndex((item) => item.sfxmdh == row.sfxmdh)
if (index > -1) {
sqXmList.value.splice(index, 1)
}
}
const getXmList = () => {
queryXmInfoList().then(res => {
processedTableData.value = processTableData(res.data);
filterData.value = resultList([...processedTableData.value])
})
}
//数据分类
const resultList = (arr) => {
const categoryList = Array.from(new Set(arr.map(item => item.sflbmc))).map(v => {
return {
sflbmc: v,
children: []
}
})
categoryList.forEach(item => {
arr.forEach(v => {
if (item.sflbmc == v.sflbmc) {
item.children.push(v)
}
})
})
return categoryList
}
const formatDictzt = (value) => {
const item = lis_req_type.value.find(i => i.value === value.trim());
return item ? item.label : value;
}
onMounted(() => {
2026-03-09 15:04:59 +08:00
searchForm.value.begdate = dayjs().format('YYYY-MM-DD')
2026-03-09 14:09:14 +08:00
getXmList()
getDictData('PT', 'SX', 'AU', 'BT', 'DP', 'SRD', 'ZJLX')
})
</script>
<style scoped lang="scss">
.app-container {
background: #F0F3F8;
}
.box-shadow {
height: 100%;
box-shadow: 2px 2px 4px 0px rgba(206, 217, 234, 0.7);
border-radius: .75rem;
padding: .5rem;
background-color: #fff;
.flex-between {
margin-bottom: .5rem;
}
}
.row-box {
height: 100%;
}
.table-box {
margin-top: 2px;
2026-03-09 15:04:59 +08:00
height: calc(100% - 65px);
2026-03-09 14:09:14 +08:00
}
.el-form-item {
margin-bottom: 5px;
}
.top-box {
border-bottom: 1px solid #E6E9ED;
padding-bottom: 2px;
}
.xmBoxs {
:deep(.el-checkbox__label) {}
height: 60%;
overflow-y: auto;
&::-webkit-scrollbar {
width: 8px;
height: 8px;
}
&::-webkit-scrollbar-thumb {
background: #817e7e;
border-radius: 4px;
}
}
.tips {
font-style: 15px;
color: #123d64;
font-weight: 600;
}
.title {
font-size: 14px;
color: #000;
font-weight: 700;
}
2026-03-09 15:04:59 +08:00
.radio_box {
display: flex;
align-items: center;
margin: .125rem 0;
.el-radio {
margin-right: .3125rem;
}
}
2026-03-09 14:09:14 +08:00
</style>