436 lines
14 KiB
Vue
Raw Normal View History

2026-03-09 14:09:14 +08:00
/**
* @file index.vue 科内开单
* @author: w
2026-03-09 18:04:16 +08:00
* @since: 2026-03-09
2026-03-09 14:09:14 +08:00
*/
<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">
2026-03-13 17:49:15 +08:00
<el-button type="primary" size="small" :loading="saveLoading" @click="saveHandle">保存</el-button>
2026-03-09 14:09:14 +08:00
<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%;">
2026-03-11 18:08:00 +08:00
<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"
2026-03-13 17:49:15 +08:00
keyField='applyid' :scrollYConfig="{ enabled: true, rSize: 30, height: '100%', }"
class="mytable-style">
2026-03-11 18:08:00 +08:00
</CustomVxeTable>
2026-03-09 14:09:14 +08:00
</div>
<div style="height: calc(40% - 30px)">
2026-03-13 17:49:15 +08:00
<CustomVxeTable :table-data="sqXmList" :columns="sqXmColumns" keyField='applyid'
2026-03-09 14:09:14 +08:00
:scrollYConfig="{ enabled: true, rSize: 30, height: '100%', }" class="mytable-style">
2026-03-11 18:08:00 +08:00
<template #classid="{ row }">
{{xmdlList.find((item) => item.dictCode == row.classid)?.dictName}}
</template>
2026-03-09 14:09:14 +08:00
<template #zt="{ row }">
2026-03-13 17:49:15 +08:00
{{ formatDict(labpat.status, 'ZT') }}
2026-03-09 14:09:14 +08:00
</template>
2026-03-11 18:08:00 +08:00
<template #action="{ row }">
2026-03-13 17:49:15 +08:00
<el-button type="danger" :text='true' size="small" @click="delItem(row)">删除</el-button>
2026-03-11 18:08:00 +08:00
</template>
2026-03-09 14:09:14 +08:00
</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">
2026-03-13 17:49:15 +08:00
<el-form-item label="" prop="brxm">
<el-input v-model="searchForm.brxm" clearable style="width: 9.5rem;" @change="handleQuery"
placeholder="请输入姓名" />
2026-03-09 15:04:59 +08:00
</el-form-item>
2026-03-13 17:49:15 +08:00
<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" />
2026-03-09 15:04:59 +08:00
</el-form-item>
2026-03-13 17:49:15 +08:00
<el-button type="primary" size="small" @click="printHandle">打印</el-button>
<el-button type="danger" size="small" @click="deleteHandle">作废</el-button>
2026-03-09 15:04:59 +08:00
<el-form-item label="" prop="begdate">
<div class="radio_box">
2026-03-13 17:49:15 +08:00
<el-radio-group v-model="searchForm.days" @change="changeDays">
2026-03-09 15:04:59 +08:00
<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>
2026-03-13 17:49:15 +08:00
<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> -->
2026-03-09 15:04:59 +08:00
</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"
2026-03-13 17:49:15 +08:00
@current-change="handleRowClick" size="small" keyField='applyid'
2026-03-09 14:09:14 +08:00
:scrollYConfig="{ enabled: true, rSize: 30, height: '100%', }" :row-style="rowStyle"
2026-03-11 18:08:00 +08:00
:cell-style="cellStyle" class="mytable-style" ref="tableRef">
2026-03-13 17:49:15 +08:00
<template #status="{ row }">
{{ formatDict(row.status, 'ZT') }}
2026-03-09 14:09:14 +08:00
</template>
</CustomVxeTable>
</div>
</div>
</el-col>
</el-row>
</div>
</template>
<script setup>
import Info from './components/info.vue'
import { getDictData, formatDict, dictData } from '@/hooks'
2026-03-13 17:49:15 +08:00
import { getXmItemInfo, saveReqInfo, queryRegRequestInfo, queryReqDetail, reqPrint, cancelReq } from '@/api/liswork/order'
2026-03-09 14:09:14 +08:00
import dayjs from 'dayjs'
2026-03-13 17:49:15 +08:00
import { ElMessage, ElMessageBox } from 'element-plus'
2026-03-09 14:09:14 +08:00
import { getFirstLetter } from '@/utils/pinyin';
2026-03-11 18:08:00 +08:00
import { listregdict } from "@/api/regional/dict/regdict.ts";
2026-03-13 17:49:15 +08:00
import { checkPrintService } from '@/utils/printHelper.ts';
2026-03-11 18:08:00 +08:00
2026-03-13 17:49:15 +08:00
const { proxy } = getCurrentInstance();
const labpat = ref({})
const saveLoading = ref(false)
2026-03-09 14:09:14 +08:00
const searchKey = ref('')
const loading = ref(false)
const tableRef = useTemplateRef('tableRef')
const labPatList = ref([])
2026-03-11 18:08:00 +08:00
const xmdlList = ref([])
const activeName = ref('')
2026-03-13 17:49:15 +08:00
const today = ref(dayjs().format('YYYY-MM-DD'))
2026-03-09 18:04:16 +08:00
const searchForm = ref({
brxm: '',
2026-03-13 17:49:15 +08:00
status: '',
2026-03-09 18:04:16 +08:00
days: 0,
2026-03-13 17:49:15 +08:00
begdate: '',
enddate: '',
2026-03-09 18:04:16 +08:00
})
2026-03-11 18:08:00 +08:00
2026-03-09 14:09:14 +08:00
const tableColumns = ref([
2026-03-13 17:49:15 +08:00
{ 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 },
2026-03-09 14:09:14 +08:00
])
const rowStyle = ({ row }) => {
}
const cellStyle = ({ row, column }) => {
}
2026-03-13 17:49:15 +08:00
const rowInfo = ref({})
2026-03-09 14:09:14 +08:00
const handleRowClick = (row) => {
2026-03-13 17:49:15 +08:00
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,
}))
2026-03-09 14:09:14 +08:00
})
}
2026-03-13 17:49:15 +08:00
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'
2026-03-09 15:04:59 +08:00
searchForm.value.enddate = dayjs(searchForm.value.begdate).format('YYYY-MM-DD') + ' 23:59:59'
2026-03-13 17:49:15 +08:00
handleQuery()
}
const handleQuery = () => {
rowInfo.value = {}
2026-03-11 18:08:00 +08:00
queryRegRequestInfo(searchForm.value).then(res => {
2026-03-09 14:09:14 +08:00
labPatList.value = res.data
})
}
const saveHandle = () => {
2026-03-13 17:49:15 +08:00
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('病人年龄不能为空!')
2026-03-09 14:09:14 +08:00
if (!sqXmList.value.length) return ElMessage.warning('请选择项目!')
2026-03-13 17:49:15 +08:00
labpat.value.status = labpat.value.status ? labpat.value.status : ''
2026-03-09 14:09:14 +08:00
const data = {
2026-03-13 17:49:15 +08:00
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
}))
2026-03-09 14:09:14 +08:00
}
2026-03-13 17:49:15 +08:00
saveLoading.value = true
2026-03-09 14:09:14 +08:00
saveReqInfo(data).then(res => {
2026-03-13 17:49:15 +08:00
if (res.code == 0) {
ElMessage.success('保存成功!')
labpat.value = {}
sqXmList.value = []
handleQuery()
}
}).finally(() => {
saveLoading.value = false
2026-03-09 14:09:14 +08:00
})
}
const addHandle = () => {
2026-03-13 17:49:15 +08:00
labpat.value = {}
sqXmList.value = []
2026-03-09 14:09:14 +08:00
}
const deleteHandle = () => {
2026-03-13 17:49:15 +08:00
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('正在打印中...')
}
})
})
2026-03-09 14:09:14 +08:00
}
const filterData = ref([])
const xmColumns = ref([
2026-03-11 18:08:00 +08:00
{ field: 'itemcode', title: '代号', align: 'center', resizable: true },
{ field: 'itemname', title: '简称', align: 'center', width: 250, resizable: true },
2026-03-09 14:09:14 +08:00
{ field: 'dj', title: '单价', align: 'center', resizable: true },
{ field: 'spec', title: '规格', align: 'center', resizable: true },
2026-03-13 17:49:15 +08:00
{ field: 'itemclass_yblx', title: '样本', align: 'center', resizable: true },
2026-03-09 14:09:14 +08:00
])
2026-03-11 18:08:00 +08:00
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]
}
}
2026-03-09 14:09:14 +08:00
const processedTableData = ref([])
const filterDictData = () => {
const key = searchKey.value.trim().toLowerCase();
if (!key) {
// 空搜索时显示全部预处理数据
2026-03-11 18:08:00 +08:00
filterData.value = [...searchList.value]
2026-03-09 14:09:14 +08:00
return;
}
2026-03-11 18:08:00 +08:00
filterData.value = searchList.value.filter((item) => {
2026-03-09 14:09:14 +08:00
const matchLabel = item.pinyin.toString().toLowerCase().includes(key);
return matchLabel;
})
2026-03-11 18:08:00 +08:00
2026-03-09 14:09:14 +08:00
}
const processTableData = (data) => {
return data.map((item) => {
const pinyinMap = {};
2026-03-11 18:08:00 +08:00
pinyinMap['pinyin'] = getFirstLetter(item.itemname).toLowerCase();
2026-03-09 14:09:14 +08:00
return { ...item, ...pinyinMap };
});
};
const sqXmList = ref([])
const sqXmColumns = ref([
2026-03-13 17:49:15 +08:00
{ field: 'classid', title: '类别', align: 'center', width: 100, slotName: 'classid', resizable: true },
2026-03-11 18:08:00 +08:00
{ field: 'itemcode', title: '代号', align: 'center', resizable: true },
{ field: 'itemname', title: '简称', align: 'center', width: 150, resizable: true },
2026-03-13 17:49:15 +08:00
{ field: 'barcode', title: '条码号', align: 'center', width: 150, resizable: true },
2026-03-09 14:09:14 +08:00
{ field: 'dj', title: '单价', align: 'center', resizable: true },
{ field: 'spec', title: '规格', align: 'center', resizable: true },
2026-03-13 17:49:15 +08:00
{ field: 'itemclass_yblx', title: '样本', align: 'center', resizable: true },
2026-03-09 14:09:14 +08:00
{ field: 'zt', title: '状态', align: 'center', resizable: true, slotName: 'zt' },
])
2026-03-11 18:08:00 +08:00
const delItem = (row) => {
const index = sqXmList.value.findIndex(item => item.itemcode === row.itemcode)
if (index !== -1) {
sqXmList.value.splice(index, 1)
}
}
2026-03-09 14:09:14 +08:00
const dbRowclick = ({ row }) => {
2026-03-13 17:49:15 +08:00
const index = sqXmList.value.findIndex(item => item.itemcode == row.itemcode)
if (index > -1) {
ElMessage.warning('已存在该项目')
return
}
2026-03-11 18:08:00 +08:00
sqXmList.value.push(row)
2026-03-09 14:09:14 +08:00
}
const getXmList = () => {
2026-03-11 18:08:00 +08:00
getXmItemInfo().then(res => {
2026-03-09 14:09:14 +08:00
processedTableData.value = processTableData(res.data);
2026-03-11 18:08:00 +08:00
filterData.value = [...processedTableData.value]
2026-03-09 14:09:14 +08:00
})
}
onMounted(() => {
2026-03-13 17:49:15 +08:00
changeDays(0)
2026-03-09 14:09:14 +08:00
getXmList()
2026-03-13 17:49:15 +08:00
getDictData('PT', 'SX', 'AU', 'BT', 'DP', 'ZT', 'ZJLX')
2026-03-11 18:08:00 +08:00
listregdict({ dictType: 'CLASS' }).then(response => {
xmdlList.value = response.rows;
activeName.value = xmdlList.value.length > 0 ? xmdlList.value[0].dictCode : '';
handleTabClick({ paneName: activeName.value });
});
2026-03-09 14:09:14 +08:00
})
</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 {
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>