2026-03-13 17:49:15 +08:00

436 lines
14 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.

/**
* @file index.vue 科内开单
* @author: w
* @since: 2026-03-09
*/
<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" :loading="saveLoading" @click="saveHandle">保存</el-button>
<el-button type="primary" size="small" @click="addHandle">新增</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%;">
<el-tabs v-model="activeName" type="card" class="tabs_box" @tab-click="handleTabClick">
<el-tab-pane v-for="item in xmdlList" :key="item.dictCode" :label="item.dictName" :name="item.dictCode">
</el-tab-pane>
</el-tabs>
<div style="height: calc(60% - 1.875rem)" class="mb5">
<CustomVxeTable :table-data="filterData" :columns="xmColumns" @cell-dblclick="dbRowclick"
keyField='applyid' :scrollYConfig="{ enabled: true, rSize: 30, height: '100%', }"
class="mytable-style">
</CustomVxeTable>
</div>
<div style="height: calc(40% - 30px)">
<CustomVxeTable :table-data="sqXmList" :columns="sqXmColumns" keyField='applyid'
:scrollYConfig="{ enabled: true, rSize: 30, height: '100%', }" class="mytable-style">
<template #classid="{ row }">
{{xmdlList.find((item) => item.dictCode == row.classid)?.dictName}}
</template>
<template #zt="{ row }">
{{ formatDict(labpat.status, 'ZT') }}
</template>
<template #action="{ row }">
<el-button type="danger" :text='true' size="small" @click="delItem(row)">删除</el-button>
</template>
</CustomVxeTable>
</div>
</el-col>
</el-row>
</div>
</el-col>
<el-col :span="8" style="height: 100%;">
<div class="box-shadow">
<el-form :model="searchForm" inline size="small">
<el-form-item label="" prop="brxm">
<el-input v-model="searchForm.brxm" clearable style="width: 9.5rem;" @change="handleQuery"
placeholder="请输入姓名" />
</el-form-item>
<el-form-item label="" prop="status">
<SelectTable v-model:data="searchForm.status" :tableData="dictData.ZT" clearable style="width: 9.5rem;"
placeholder="请选择状态" size="small" @getDataValue="handleQuery" />
</el-form-item>
<el-button type="primary" size="small" @click="printHandle">打印</el-button>
<el-button type="danger" size="small" @click="deleteHandle">作废</el-button>
<el-form-item label="" prop="begdate">
<div class="radio_box">
<el-radio-group v-model="searchForm.days" @change="changeDays">
<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="today" type="date" value-format="YYYY-MM-DD" style="width: 9rem;"
@change="dateHandle" /> &nbsp;
<!-- <el-tooltip class="box-item" effect="dark" content="打印" placement="top">
<el-button type="primary" circle size="small" icon="Memo" @click="printHandle"></el-button>
</el-tooltip>
<el-tooltip class="box-item" effect="dark" content="作废" placement="top">
<el-button type="danger" circle size="small" icon="Delete" @click="deleteHandle"></el-button>
</el-tooltip> -->
</div>
</el-form-item>
</el-form>
<div class="table-box">
<CustomVxeTable :table-data="labPatList" :loading="loading" :columns="tableColumns"
@current-change="handleRowClick" size="small" keyField='applyid'
:scrollYConfig="{ enabled: true, rSize: 30, height: '100%', }" :row-style="rowStyle"
:cell-style="cellStyle" class="mytable-style" ref="tableRef">
<template #status="{ row }">
{{ formatDict(row.status, '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 { getXmItemInfo, saveReqInfo, queryRegRequestInfo, queryReqDetail, reqPrint, cancelReq } from '@/api/liswork/order'
import dayjs from 'dayjs'
import { ElMessage, ElMessageBox } from 'element-plus'
import { getFirstLetter } from '@/utils/pinyin';
import { listregdict } from "@/api/regional/dict/regdict.ts";
import { checkPrintService } from '@/utils/printHelper.ts';
const { proxy } = getCurrentInstance();
const labpat = ref({})
const saveLoading = ref(false)
const searchKey = ref('')
const loading = ref(false)
const tableRef = useTemplateRef('tableRef')
const labPatList = ref([])
const xmdlList = ref([])
const activeName = ref('')
const today = ref(dayjs().format('YYYY-MM-DD'))
const searchForm = ref({
brxm: '',
status: '',
days: 0,
begdate: '',
enddate: '',
})
const tableColumns = ref([
{ field: 'patName', title: '姓名', width: 80, align: 'center', resizable: true, },
{ field: 'status', title: '状态', width: 80, align: 'center', slotName: 'status', resizable: true, },
{ field: 'orderTime', title: '登记时间', width: 80, align: 'center', resizable: true },
{ field: 'userName', title: '登记人', width: 80, align: 'center', resizable: true },
{ field: 'reqDetailName', title: '项目', align: 'center', resizable: true },
])
const rowStyle = ({ row }) => {
}
const cellStyle = ({ row, column }) => {
}
const rowInfo = ref({})
const handleRowClick = (row) => {
rowInfo.value = row
queryReqDetail({ applyId: row.applyid }).then(res => {
labpat.value = res.data.regApply
sqXmList.value = res.data.regApplyDetailList.map(item => ({
itemcode: item.orderItemCode,
itemname: item.orderItemName,
itemclass_yblx: item.sampleTypeName,
dj: item.amount,
applyid: item.applyid,
uid: item.uid,
classid: item.classid,
barcode: item.barcode,
}))
})
}
const changeDays = (val) => {
if (val == 3) {
searchForm.value.begdate = dayjs().subtract(3, 'day').format('YYYY-MM-DD') + ' 00:00:00'
searchForm.value.enddate = dayjs().format('YYYY-MM-DD') + ' 23:59:59'
} else if (val == 7) {
searchForm.value.begdate = dayjs().subtract(7, 'day').format('YYYY-MM-DD') + ' 00:00:00'
searchForm.value.enddate = dayjs().format('YYYY-MM-DD') + ' 23:59:59'
} else {
searchForm.value.begdate = dayjs(today.value).format('YYYY-MM-DD') + ' 00:00:00'
searchForm.value.enddate = dayjs(searchForm.value.begdate).format('YYYY-MM-DD') + ' 23:59:59'
}
handleQuery()
}
const dateHandle = (val) => {
searchForm.value.begdate = dayjs(val).format('YYYY-MM-DD') + ' 00:00:00'
searchForm.value.enddate = dayjs(searchForm.value.begdate).format('YYYY-MM-DD') + ' 23:59:59'
handleQuery()
}
const handleQuery = () => {
rowInfo.value = {}
queryRegRequestInfo(searchForm.value).then(res => {
labPatList.value = res.data
})
}
const saveHandle = () => {
if (!labpat.value.patId) return ElMessage.warning('病人代号不能为空!')
if (!labpat.value.patName) return ElMessage.warning('病人姓名不能为空!')
if (!labpat.value.patSex) return ElMessage.warning('病人性别不能为空!')
if (!labpat.value.patAge && !labpat.value.ageUnit) return ElMessage.warning('病人年龄不能为空!')
if (!sqXmList.value.length) return ElMessage.warning('请选择项目!')
labpat.value.status = labpat.value.status ? labpat.value.status : ''
const data = {
regApply: labpat.value,
regApplyDetailList: sqXmList.value.map(item => ({
orderItemCode: item.itemcode,
orderItemName: item.itemname,
sampleTypeCode: item.itemclass_yblx,
sampleTypeName: item.itemclass_yblx,
amount: item.dj,
applyid: labpat.value.applyid,
uid: item.uid
}))
}
saveLoading.value = true
saveReqInfo(data).then(res => {
if (res.code == 0) {
ElMessage.success('保存成功!')
labpat.value = {}
sqXmList.value = []
handleQuery()
}
}).finally(() => {
saveLoading.value = false
})
}
const addHandle = () => {
labpat.value = {}
sqXmList.value = []
}
const deleteHandle = () => {
if (!rowInfo.value.applyid) return ElMessage.warning('请选择要作废的申请单!')
ElMessageBox.confirm('确定要作废此申请单吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
cancelReq({ applyId: rowInfo.value.applyid }).then(res => {
if (res.code == 0) {
ElMessage.success(res.msg)
handleQuery()
}
})
}).catch(() => { })
}
const printHandle = () => {
if (!labpat.value.applyid) return ElMessage.warning('请选择要打印的申请单!')
checkPrintService().then((isConnected) => {
if (!isConnected) return
reqPrint({ applyId: labpat.value.applyid }).then(res => {
if (res.code == 0) {
ElMessage.success('正在打印中...')
}
})
})
}
const filterData = ref([])
const xmColumns = ref([
{ field: 'itemcode', title: '代号', align: 'center', resizable: true },
{ field: 'itemname', title: '简称', align: 'center', width: 250, resizable: true },
{ field: 'dj', title: '单价', align: 'center', resizable: true },
{ field: 'spec', title: '规格', align: 'center', resizable: true },
{ field: 'itemclass_yblx', title: '样本', align: 'center', resizable: true },
])
const searchList = ref([])
const handleTabClick = (tab) => {
const currentTab = xmdlList.value.find(item => item.dictCode === tab.paneName)
if (currentTab) {
searchList.value = processedTableData.value.filter(item => item.classid === currentTab.dictCode)
filterData.value = [...searchList.value]
}
}
const processedTableData = ref([])
const filterDictData = () => {
const key = searchKey.value.trim().toLowerCase();
if (!key) {
// 空搜索时显示全部预处理数据
filterData.value = [...searchList.value]
return;
}
filterData.value = searchList.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.itemname).toLowerCase();
return { ...item, ...pinyinMap };
});
};
const sqXmList = ref([])
const sqXmColumns = ref([
{ field: 'classid', title: '类别', align: 'center', width: 100, slotName: 'classid', resizable: true },
{ field: 'itemcode', title: '代号', align: 'center', resizable: true },
{ field: 'itemname', title: '简称', align: 'center', width: 150, resizable: true },
{ field: 'barcode', title: '条码号', align: 'center', width: 150, resizable: true },
{ field: 'dj', title: '单价', align: 'center', resizable: true },
{ field: 'spec', title: '规格', align: 'center', resizable: true },
{ field: 'itemclass_yblx', title: '样本', align: 'center', resizable: true },
{ field: 'zt', title: '状态', align: 'center', resizable: true, slotName: 'zt' },
])
const delItem = (row) => {
const index = sqXmList.value.findIndex(item => item.itemcode === row.itemcode)
if (index !== -1) {
sqXmList.value.splice(index, 1)
}
}
const dbRowclick = ({ row }) => {
const index = sqXmList.value.findIndex(item => item.itemcode == row.itemcode)
if (index > -1) {
ElMessage.warning('已存在该项目')
return
}
sqXmList.value.push(row)
}
const getXmList = () => {
getXmItemInfo().then(res => {
processedTableData.value = processTableData(res.data);
filterData.value = [...processedTableData.value]
})
}
onMounted(() => {
changeDays(0)
getXmList()
getDictData('PT', 'SX', 'AU', 'BT', 'DP', 'ZT', 'ZJLX')
listregdict({ dictType: 'CLASS' }).then(response => {
xmdlList.value = response.rows;
activeName.value = xmdlList.value.length > 0 ? xmdlList.value[0].dictCode : '';
handleTabClick({ paneName: activeName.value });
});
})
</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;
height: calc(100% - 65px);
}
.el-form-item {
margin-bottom: 5px;
}
.top-box {
border-bottom: 1px solid #E6E9ED;
padding-bottom: 2px;
}
.xmBoxs {
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;
}
.radio_box {
display: flex;
align-items: center;
margin: .125rem 0;
.el-radio {
margin-right: .3125rem;
}
}
</style>