This commit is contained in:
tangw 2026-09-16 16:17:52 +08:00
parent 973b9e45bd
commit 1e42410b9e
8 changed files with 1014 additions and 42 deletions

View File

@ -0,0 +1,30 @@
// 抗菌药物字典 xm_med
// @ts-ignore
import request from '@/utils/request'
// 查询药物列表(后端全量返回,不分页)
export function listMed(params) {
return request({
url: '/xmMed/query',
method: 'get',
params
})
}
// 新增/修改药物(后端按 ywdh 存在即更新),入参为数组
export function addMed(data) {
return request({
url: '/xmMed/add',
method: 'post',
data
})
}
// 删除药物
export function delMed(ywdh) {
return request({
url: '/xmMed/del',
method: 'get',
params: { ywdh }
})
}

View File

@ -0,0 +1,39 @@
// 常用抗生素组 xm_medgroup
// @ts-ignore
import request from '@/utils/request'
// 查询(不传条件返回全部明细,前端去重得到组名)
export function listMedgroup(params) {
return request({
url: '/xmMedgroup/query',
method: 'get',
params
})
}
// 新增明细(无 @RequestBody,参数走 query)
export function addMedgroup(params) {
return request({
url: '/xmMedgroup/add',
method: 'post',
params
})
}
// 修改明细(无 @RequestBody,参数走 query)
export function updateMedgroup(params) {
return request({
url: '/xmMedgroup/update',
method: 'post',
params
})
}
// 删除明细
export function delMedgroup(params) {
return request({
url: '/xmMedgroup/del',
method: 'get',
params
})
}

View File

@ -0,0 +1,39 @@
// 抗生素通道号 xm_medinter
// @ts-ignore
import request from '@/utils/request'
// 查询某仪器的通道号列表
export function listMedinter(params) {
return request({
url: '/xmMedinter/query',
method: 'get',
params
})
}
// 新增通道号
export function addMedinter(data) {
return request({
url: '/xmMedinter/add',
method: 'post',
data
})
}
// 修改通道号(只改药物)
export function updateMedinter(data) {
return request({
url: '/xmMedinter/update',
method: 'post',
data
})
}
// 删除通道号
export function delMedinter(params) {
return request({
url: '/xmMedinter/del',
method: 'get',
params
})
}

View File

@ -0,0 +1,268 @@
<template>
<div class="app-container med-group">
<el-row :gutter="12" class="main-row">
<!-- 左:药物组列表 -->
<el-col :span="6" class="left-col">
<div class="panel">
<div class="panel-title">抗生素组名称</div>
<div class="left-toolbar">
<el-input v-model="newGroupName" size="small" placeholder="新组名称" style="width: 110px" />
<el-button type="primary" size="small" icon="Plus" @click="addGroup">新增组</el-button>
<el-button type="danger" size="small" icon="Delete" @click="delGroup">删除组</el-button>
</div>
<el-table ref="groupTableRef" :data="groupList" height="100%" highlight-current-row
@current-change="onGroupChange">
<el-table-column prop="ywzmc" label="组名称" show-overflow-tooltip>
<template #default="{ row }">
<span>{{ row.ywzmc }}</span>
</template>
</el-table-column>
</el-table>
</div>
</el-col>
<!-- 右:组信息 + 明细 -->
<el-col :span="18" class="right-col">
<div class="panel">
<el-form :inline="true" class="head-form">
<el-form-item label="抗生素组名称">
<el-input v-model="rightForm.ywzmc" :disabled="!isNewGroup" placeholder="组名称" style="width: 220px" />
</el-form-item>
<el-form-item label="输入模式">
<el-radio-group v-model="rightForm.ismic">
<el-radio value="0">输入Rad</el-radio>
<el-radio value="1">输入Mic</el-radio>
<el-radio value="2">不输入</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<div class="detail-toolbar">
<el-button type="primary" plain icon="Plus" size="small" @click="addDetail">新增药物</el-button>
<el-button type="danger" plain icon="Delete" size="small" @click="delDetail">删除药物</el-button>
<el-button type="success" plain icon="Check" size="small" @click="saveDetail">保存</el-button>
</div>
<el-table ref="detailTableRef" :data="detailList" border height="100%" highlight-current-row
@row-click="onDetailRow">
<el-table-column label="抗生素" prop="ywdh" min-width="240">
<template #default="{ row }">
<SelectTable v-model:data="row.ywdh" :tableData="medList" class="full-width-input" />
</template>
</el-table-column>
<el-table-column label="中介下限(Mic/Rad)" prop="zjmic" width="150" align="center">
<template #default="{ row }">
<el-input-number v-model="row.zjmic" :precision="2" controls-position="right" class="num-input" />
</template>
</el-table-column>
<el-table-column label="中介上限(Mic/Rad)" prop="nymic" width="150" align="center">
<template #default="{ row }">
<el-input-number v-model="row.nymic" :precision="2" controls-position="right" class="num-input" />
</template>
</el-table-column>
<el-table-column label="备注" prop="bz" min-width="120">
<template #default="{ row }">
<el-input v-model="row.bz" />
</template>
</el-table-column>
<el-table-column label="序号" prop="xh" width="80" align="center" />
</el-table>
</div>
</el-col>
</el-row>
</div>
</template>
<script setup name="germMedGroup">
import { ElMessage, ElMessageBox } from 'element-plus'
import { listMed } from '@/api/liswork/germ/med'
import { listMedgroup, addMedgroup, updateMedgroup, delMedgroup } from '@/api/liswork/germ/medgroup'
const groupTableRef = ref()
const detailTableRef = ref()
const newGroupName = ref('')
const isNewGroup = ref(false)
const groupList = ref([])
const detailList = ref([])
const medList = ref([])
const selectedDetail = ref(null)
const rightForm = reactive({
ywzmc: '',
ismic: '0'
})
// 加载药物字典(下拉用)
const loadMedList = () => {
listMed({}).then(res => {
medList.value = (res.data || []).map(item => ({
label: `${item.ywmc}(${item.ywdh})`,
value: item.ywdh
}))
})
}
// 加载左侧组列表(全量明细按组名去重)
const loadGroupList = () => {
listMedgroup({}).then(res => {
const rows = res.data || []
const map = {}
rows.forEach(r => { map[r.ywzmc] = true })
groupList.value = Object.keys(map).sort().map(k => ({ ywzmc: k }))
})
}
// 选中某组 → 加载明细
const onGroupChange = (row) => {
if (!row) return
isNewGroup.value = false
rightForm.ywzmc = row.ywzmc
listMedgroup({ ywzmc: row.ywzmc }).then(res => {
const rows = res.data || []
detailList.value = rows.map(r => ({ ...r, _isNew: false }))
// ismic 取该组第一行
if (rows.length) rightForm.ismic = rows[0].ismic || '0'
})
}
// 新增组
const addGroup = () => {
const name = newGroupName.value.trim()
if (!name) return ElMessage.warning('请输入新组名称')
if (groupList.value.some(g => g.ywzmc === name)) return ElMessage.warning('该组已存在')
newGroupName.value = ''
isNewGroup.value = true
rightForm.ywzmc = name
rightForm.ismic = '0'
detailList.value = []
groupTableRef.value?.setCurrentRow(null)
}
// 删除组(删除该组全部明细)
const delGroup = () => {
const name = rightForm.ywzmc
if (!name) return ElMessage.warning('请先选择要删除的组')
ElMessageBox.confirm(`确认删除组"${name}"及其全部药物?`, '提示', { type: 'warning' }).then(() => {
const rows = detailList.value.filter(r => !r._isNew)
const tasks = rows.map(r => delMedgroup({ ywzmc: r.ywzmc, xh: r.xh }))
Promise.all(tasks).then(() => {
ElMessage.success('删除成功')
rightForm.ywzmc = ''
detailList.value = []
loadGroupList()
})
}).catch(() => {})
}
// 新增明细行
const addDetail = () => {
if (!rightForm.ywzmc) return ElMessage.warning('请先选择或新建组')
const maxXh = detailList.value.reduce((m, r) => Math.max(m, Number(r.xh) || 0), 0)
detailList.value.push({
ywzmc: rightForm.ywzmc,
xh: maxXh + 10,
ywdh: '',
bz: '',
zjmic: null,
nymic: null,
ismic: rightForm.ismic,
_isNew: true
})
}
const onDetailRow = (row) => { selectedDetail.value = row }
const delDetail = () => {
if (!selectedDetail.value) return ElMessage.error('请先选择要删除的行')
const row = selectedDetail.value
const doDel = () => {
if (row._isNew) {
detailList.value = detailList.value.filter(r => r !== row)
selectedDetail.value = null
return
}
delMedgroup({ ywzmc: row.ywzmc, xh: row.xh }).then(() => {
ElMessage.success('删除成功')
detailList.value = detailList.value.filter(r => r !== row)
selectedDetail.value = null
})
}
doDel()
}
// 保存:明细逐行 add/update;ismic 同步到每行
const saveDetail = () => {
if (!rightForm.ywzmc) return ElMessage.warning('请先选择或新建组')
for (let i = 0; i < detailList.value.length; i++) {
const r = detailList.value[i]
if (!r.ywdh) return ElMessage.error(`第${i + 1}行请选择抗生素`)
}
const tasks = detailList.value.map(r => {
const payload = {
ywzmc: rightForm.ywzmc,
xh: r.xh,
ywdh: r.ywdh,
bz: r.bz || '',
zjmic: r.zjmic,
nymic: r.nymic,
ismic: rightForm.ismic
}
return r._isNew ? addMedgroup(payload) : updateMedgroup(payload)
})
Promise.all(tasks).then(() => {
ElMessage.success('保存成功')
loadGroupList()
// 重新拉取明细
listMedgroup({ ywzmc: rightForm.ywzmc }).then(res => {
detailList.value = (res.data || []).map(r => ({ ...r, _isNew: false }))
})
})
}
loadMedList()
loadGroupList()
</script>
<style scoped>
.med-group {
height: calc(100vh - 120px);
}
.main-row {
height: 100%;
}
.left-col, .right-col {
height: 100%;
}
.panel {
height: 100%;
border: 1px solid #e6e6e6;
border-radius: 4px;
padding: 8px;
box-sizing: border-box;
display: flex;
flex-direction: column;
}
.panel-title {
font-weight: 600;
margin-bottom: 8px;
color: #409eff;
}
.left-toolbar {
margin-bottom: 8px;
display: flex;
gap: 6px;
}
.head-form {
margin-bottom: 8px;
}
.detail-toolbar {
margin-bottom: 8px;
}
.num-input {
width: 130px;
}
.full-width-input {
width: 100%;
}
</style>

View File

@ -0,0 +1,342 @@
<template>
<div class="app-container">
<!-- 查询条件 -->
<el-form :model="queryParams" ref="queryRef" inline v-show="showSearch" class="query-form">
<el-form-item label="药物代码" prop="ywdh">
<el-input v-model="queryParams.ywdh" placeholder="请输入药物代码" clearable style="width: 180px"
@keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="药物名称" prop="ywmc">
<el-input v-model="queryParams.ywmc" placeholder="请输入药物名称" clearable style="width: 180px"
@keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="助记符" prop="zjf">
<el-input v-model="queryParams.zjf" placeholder="简拼检索" clearable style="width: 180px"
@keyup.enter="handleQuery" />
</el-form-item>
</el-form>
<div class="mb5">
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
<el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
<el-button type="info" plain icon="Edit" :disabled="single" @click="handleUpdate">修改</el-button>
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete">删除</el-button>
</div>
<div class="table-container">
<el-table v-loading="loading" :data="pageList" border height="100%"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<el-table-column label="药物代码" align="center" prop="ywdh" width="90" show-overflow-tooltip />
<el-table-column label="药物名称" align="left" prop="ywmc" min-width="140" show-overflow-tooltip />
<el-table-column label="简码" align="center" prop="medno" width="90" show-overflow-tooltip />
<el-table-column label="英文代码" align="center" prop="yydh" width="110" show-overflow-tooltip />
<el-table-column label="助记符" align="center" prop="zjf" width="90" show-overflow-tooltip />
<el-table-column label="用法1" align="center" prop="yf" width="90" show-overflow-tooltip />
<el-table-column label="用法2" align="center" prop="yfim" width="90" show-overflow-tooltip />
<el-table-column label="用法3" align="center" prop="yfiv" width="90" show-overflow-tooltip />
<el-table-column label="中介下限" align="center" prop="zjmic" width="80" />
<el-table-column label="中介上限" align="center" prop="nymic" width="80" />
<el-table-column label="血药浓度" align="center" prop="xyfz" width="90" show-overflow-tooltip />
<el-table-column label="尿药浓度" align="center" prop="nyfz" width="90" show-overflow-tooltip />
<el-table-column label="序号" align="center" prop="seq" width="60" />
<el-table-column label="Whonet" align="center" prop="whonet" width="100" show-overflow-tooltip />
<el-table-column label="备注" align="left" prop="bz" min-width="120" show-overflow-tooltip />
<el-table-column label="操作" width="130" align="center" fixed="right" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)">修改</el-button>
<el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize" @pagination="getList" />
<!-- 新增/修改对话框 -->
<el-dialog :title="title" v-model="open" width="780px" append-to-body>
<el-form ref="medRef" :model="form" :rules="rules" label-width="100px">
<el-divider content-position="left">基本信息</el-divider>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="药物代码" prop="ywdh">
<el-input v-model="form.ywdh" placeholder="主键" :disabled="isEdit" maxlength="20" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="药物名称" prop="ywmc">
<el-input v-model="form.ywmc" placeholder="请输入名称" maxlength="50" @input="autoPinyin" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="助记符" prop="zjf">
<el-input v-model="form.zjf" placeholder="按名称自动生成" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="简码" prop="medno">
<el-input v-model="form.medno" placeholder="medno" maxlength="20" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="英文代码" prop="yydh">
<el-input v-model="form.yydh" placeholder="yydh" maxlength="30" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="序号" prop="seq">
<el-input-number v-model="form.seq" controls-position="right" :min="0" style="width: 100%" />
</el-form-item>
</el-col>
</el-row>
<el-divider content-position="left">用法 / 浓度</el-divider>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="用法1" prop="yf">
<el-input v-model="form.yf" maxlength="100" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="用法2" prop="yfim">
<el-input v-model="form.yfim" maxlength="100" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="用法3" prop="yfiv">
<el-input v-model="form.yfiv" maxlength="100" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="血药浓度" prop="xyfz">
<el-input v-model="form.xyfz" maxlength="100" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="尿药浓度" prop="nyfz">
<el-input v-model="form.nyfz" maxlength="100" />
</el-form-item>
</el-col>
</el-row>
<el-divider content-position="left">药敏阈值</el-divider>
<el-row :gutter="20">
<el-col :span="6">
<el-form-item label="中介下限" prop="zjmic">
<el-input-number v-model="form.zjmic" :precision="2" controls-position="right" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="中介上限" prop="nymic">
<el-input-number v-model="form.nymic" :precision="2" controls-position="right" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="抑菌圈下限" prop="zjkb">
<el-input-number v-model="form.zjkb" :precision="2" controls-position="right" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="抑菌圈上限" prop="nykb">
<el-input-number v-model="form.nykb" :precision="2" controls-position="right" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="Etest下限" prop="zjetest">
<el-input-number v-model="form.zjetest" :precision="2" controls-position="right" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="Etest上限" prop="nyetest">
<el-input-number v-model="form.nyetest" :precision="2" controls-position="right" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="多MIC" prop="multimic">
<el-input v-model="form.multimic" maxlength="1" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="IKB" prop="ikb">
<el-input v-model="form.ikb" maxlength="20" />
</el-form-item>
</el-col>
</el-row>
<el-divider content-position="left">Whonet</el-divider>
<el-row :gutter="20">
<el-col :span="6">
<el-form-item label="Whonet" prop="whonet">
<el-input v-model="form.whonet" maxlength="20" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="WhonetMic" prop="whonet_mic">
<el-input v-model="form.whonet_mic" maxlength="20" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="WhonetKb" prop="whonet_kb">
<el-input v-model="form.whonet_kb" maxlength="20" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="WhonetEtest" prop="whonet_etest">
<el-input v-model="form.whonet_etest" maxlength="20" />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="备注" prop="bz">
<el-input v-model="form.bz" type="textarea" :rows="2" maxlength="255" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="germMed">
import { pinyin } from 'pinyin-pro'
import { listMed, addMed, delMed } from '@/api/liswork/germ/med'
const { proxy } = getCurrentInstance()
const loading = ref(true)
const open = ref(false)
const showSearch = ref(true)
const single = ref(true)
const multiple = ref(true)
const title = ref('')
const isEdit = ref(false)
const total = ref(0)
const allList = ref([])
const data = reactive({
form: {},
queryParams: {
ywdh: undefined,
ywmc: undefined,
zjf: undefined,
pageNum: 1,
pageSize: 30
},
rules: {
ywdh: [{ required: true, message: '药物代码不能为空', trigger: 'blur' }],
ywmc: [{ required: true, message: '药物名称不能为空', trigger: 'blur' }]
}
})
const { queryParams, form, rules } = toRefs(data)
// 前端分页切片
const pageList = computed(() => {
const start = (queryParams.value.pageNum - 1) * queryParams.value.pageSize
return allList.value.slice(start, start + queryParams.value.pageSize)
})
// 名称变更自动生成首拼助记符(后端保存时也会再生成一次)
function autoPinyin() {
if (!form.value.ywmc) {
form.value.zjf = ''
return
}
try {
form.value.zjf = pinyin(form.value.ywmc, { pattern: 'first', toneType: 'none', type: 'array' }).join('').toUpperCase()
} catch (e) {
form.value.zjf = ''
}
}
function getList() {
loading.value = true
listMed(queryParams.value).then(res => {
allList.value = res.data || []
total.value = allList.value.length
loading.value = false
})
}
function cancel() {
open.value = false
reset()
}
function reset() {
form.value = {
ywdh: undefined, ywmc: undefined, medno: undefined, yydh: undefined, zjf: undefined,
seq: 0, yf: undefined, yfim: undefined, yfiv: undefined, xyfz: undefined, nyfz: undefined,
zjmic: undefined, nymic: undefined, zjkb: undefined, nykb: undefined,
zjetest: undefined, nyetest: undefined, multimic: undefined, ikb: undefined,
whonet: undefined, whonet_mic: undefined, whonet_kb: undefined, whonet_etest: undefined,
bz: undefined
}
proxy.resetForm('medRef')
}
function handleQuery() {
queryParams.value.pageNum = 1
getList()
}
function resetQuery() {
proxy.resetForm('queryRef')
handleQuery()
}
function handleSelectionChange(selection) {
single.value = selection.length !== 1
multiple.value = !selection.length
}
function handleAdd() {
reset()
isEdit.value = false
open.value = true
title.value = '新增抗菌药物'
}
function handleUpdate(row) {
reset()
isEdit.value = true
form.value = { ...row }
open.value = true
title.value = '修改抗菌药物'
}
function submitForm() {
proxy.$refs['medRef'].validate(valid => {
if (!valid) return
// 后端入参为数组,按 ywdh 存在即更新
addMed([form.value]).then(() => {
proxy.$modal.msgSuccess(isEdit.value ? '修改成功' : '新增成功')
open.value = false
getList()
})
})
}
function handleDelete(row) {
const ywdh = row.ywdh
proxy.$modal.confirm('是否确认删除药物"' + ywdh + '"?').then(() => {
return delMed(ywdh)
}).then(() => {
getList()
proxy.$modal.msgSuccess('删除成功')
}).catch(() => {})
}
getList()
</script>
<style scoped>
.table-container {
height: calc(100% - 150px);
}
</style>

View File

@ -0,0 +1,150 @@
<template>
<!-- 抗生素通道号设定 -->
<div class="table-container">
<el-row :gutter="10" class="table-toolbar">
<el-col :span="1.5">
<el-button type="success" plain icon="Check" @click="handleSave">保存</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="addItem">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" @click="delItem">删除</el-button>
</el-col>
</el-row>
<div class="table-row">
<CustomTable ref="tableRef" :data="tableData" :columns="columns" :config="tableConfig" :loading="loading"
@row-click="handleRowClick">
<template #tdh="{ row }">
<el-input v-model="row.tdh" placeholder="请输入通道号" :disabled="!row._isNew" class="full-width-input" />
</template>
<template #ywdh="{ row }">
<SelectTable v-model:data="row.ywdh" :tableData="medList" class="full-width-input" />
</template>
</CustomTable>
</div>
</div>
</template>
<script setup lang="ts">
import { listMed } from '@/api/liswork/germ/med'
import { listMedinter, addMedinter, updateMedinter, delMedinter } from '@/api/liswork/germ/medinter'
import { ElMessage } from 'element-plus'
const yq = defineModel<string>();
const loading = ref(false);
const tableRef = ref();
const tableData = ref<Array<any>>([]);
const medList = ref<Array<{ label: string, value: string }>>([]);
const columns = [
{ label: '序号', type: 'index', visible: true, width: 50, align: 'center' },
{ label: '通道号', prop: 'tdh', visible: true, align: 'center', slot: 'tdh', width: 160 },
{ label: '药物', prop: 'ywdh', visible: true, align: 'center', slot: 'ywdh', minWidth: 260 },
];
const tableConfig = {
border: true,
height: '100%',
highlightCurrentRow: true,
}
const selectedRow = ref<any>(null);
const handleRowClick = (row: any) => {
selectedRow.value = row;
};
// 药物字典:label 显示 名称(代码),value 为药物代码
const getMedList = () => {
listMed({}).then((res: any) => {
medList.value = (res.data || []).map((item: any) => ({
label: `${item.ywmc}(${item.ywdh})`,
value: item.ywdh,
}))
})
};
const getList = () => {
if (!yq.value) return;
loading.value = true;
listMedinter({ yq: yq.value }).then((res: any) => {
loading.value = false;
tableData.value = (res.data || []).map((r: any) => ({ ...r, _isNew: false }));
})
};
const addItem = () => {
if (!yq.value) return ElMessage.warning('请先在左侧选择仪器');
tableData.value.push({ yq: yq.value, tdh: '', ywdh: '', _isNew: true });
nextTick(() => {
tableRef.value?.setScrollTop(tableData.value.length);
});
};
const delItem = () => {
if (!selectedRow.value) return ElMessage.error('请先选择要删除的行!');
const row = selectedRow.value;
if (row._isNew) {
tableData.value = tableData.value.filter((r: any) => r !== row);
selectedRow.value = null;
return;
}
delMedinter({ yq: row.yq, tdh: row.tdh }).then(() => {
ElMessage.success('删除成功');
getList();
});
};
const handleSave = () => {
if (!yq.value) return ElMessage.warning('请先在左侧选择仪器');
// 校验
for (let i = 0; i < tableData.value.length; i++) {
const row = tableData.value[i];
if (!row.tdh || !row.tdh.trim()) return ElMessage.error(`第${i + 1}行通道号不能为空!`);
if (!row.ywdh) return ElMessage.error(`第${i + 1}行请选择药物!`);
}
// 通道号去重
const tdhSet = new Set();
for (const row of tableData.value) {
const k = row.tdh.trim().toUpperCase();
if (tdhSet.has(k)) return ElMessage.error(`通道号 ${row.tdh} 重复!`);
tdhSet.add(k);
}
const tasks: Promise<any>[] = [];
tableData.value.forEach((row: any) => {
const payload = { yq: yq.value, tdh: row.tdh.trim(), ywdh: row.ywdh };
if (row._isNew) {
tasks.push(addMedinter(payload));
} else {
tasks.push(updateMedinter(payload));
}
});
Promise.all(tasks).then(() => {
ElMessage.success('保存成功!');
getList();
});
};
watch(yq, (val) => {
if (val) getList();
}, { immediate: true });
getMedList();
</script>
<style scoped lang="scss">
.table-container {
height: calc(100% - 58px);
}
.table-toolbar {
margin-bottom: 8px;
height: 36px;
line-height: 36px;
}
.table-row {
height: calc(100% - 45px);
}
</style>

View File

@ -53,6 +53,7 @@ import SysDefaultParams from './components/sysDefaultParams/index.vue'
import SysParameter from './components/sysParameter/index.vue'
import SysChannel from './components/sysChannel/index.vue'
import SysSort from './components/sysSort/index.vue'
import SysMedinter from './components/sysMedinter/index.vue'
const mbStore = useCommonStore();
// ========== TypeScript 类型定义 ==========
interface InstrTreeNode {
@ -112,6 +113,7 @@ const tabList = [
{ key: 'SysDefaultParams', label: '默认界面参数', component: SysDefaultParams },
{ key: 'SysParameter', label: '参数', component: SysParameter },
{ key: 'SysChannel', label: '通道号', component: SysChannel },
{ key: 'SysMedinter', label: '抗生素通道号', component: SysMedinter },
{ key: 'SysSort', label: '项目排序', component: SysSort },
{ key: 'SysReport', label: '报告单设置', component: SysReport },
]

View File

@ -5,22 +5,23 @@
*/
<template>
<div class="app-container">
<div class="mb8">
<el-button type="primary" icon="Search" @click="search">查询</el-button>
<el-button type="warning" icon="Printer" plain @click="print">打印</el-button>
<el-button type="primary" icon="Download" plain @click="exportHandle">导出Excel</el-button>
</div>
<div class="unified-panel">
<div class="btn-bar">
<el-button type="primary" icon="Search" @click="search">查询</el-button>
<el-button type="warning" icon="Printer" plain @click="print">打印</el-button>
<el-button type="primary" icon="Download" plain @click="exportHandle">导出Excel</el-button>
</div>
<el-form ref="form" :model="queryParams" inline size="small" class="stats-form" label-width="auto">
<el-row :gutter="10" class="stats-form-row">
<el-col :span="checkBoxs.length ? 16 : 24">
<div class="form-panel">
<div class="divider-h"></div>
<el-form ref="form" :model="queryParams" inline size="small" class="stats-form" label-width="72px">
<el-row :gutter="0" class="stats-form-row">
<el-col :span="checkBoxs.length ? 16 : 24" class="panel-section">
<div class="tips">统计条件</div>
<div class="panel-content panel-content-left">
<template v-for="item in Parameter">
<el-form-item :label="item.paramOptiontype == '0' ? '' : item.paramName"
:class="{ 'checkbox-form-item': item.paramOptiontype == '0' }"
:label-width="item.paramName == '-' ? '0px' : 'auto'">
:class="{ 'checkbox-form-item': item.paramOptiontype == '0' }">
<template v-if="item.paramOptiontype == '0'">
<el-checkbox v-model="item.paramDefvalue" :label="item.paramName" true-value="1" false-value="0" />
</template>
@ -53,32 +54,30 @@
<!-- 特殊处理 -->
</template>
<template v-if="item.paramOptiontype == '5'">
<el-input v-model="item.paramDefvalue" placeholder="请输入" />
<el-input v-model="item.paramDefvalue" placeholder="请输入" style="width:150px" />
</template>
<template v-if="item.paramOptiontype == '6'">
<el-input v-model="item.paramDefvalue" type="number" placeholder="请输入" />
<el-input v-model="item.paramDefvalue" type="number" placeholder="请输入" style="width:150px" />
</template>
<template v-if="item.paramOptiontype == '7'">
<el-date-picker v-model="item.paramDefvalue" type="date" format="YYYY-MM-DD"
value-format="YYYY-MM-DD" @change="handletime" style="width:120px" />
value-format="YYYY-MM-DD" @change="handletime" style="width:150px" />
</template>
<template v-if="item.paramOptiontype == '8'">
<el-time-picker v-model="item.paramDefvalue" value-format="HH:mm:ss" format="HH:mm:ss"
style="width:100px" />
style="width:150px" />
</template>
<template v-if="item.paramOptiontype == '9'">
<el-time-picker v-model="item.paramDefvalue" type="datetime" value-format="YYYY-MM-DD HH:mm:ss"
format="YYYY-MM-DD HH:mm:ss" style="width:100px" />
format="YYYY-MM-DD HH:mm:ss" style="width:150px" />
</template>
</el-form-item>
</template>
</div>
</div>
</el-col>
<el-col :span="8">
<div class="form-panel" v-if="checkBoxs.length">
</el-col>
<el-col :span="8" class="panel-section" v-if="checkBoxs.length">
<div class="tips">统计项目</div>
<div class="panel-content panel-content-right">
<el-form-item label="" class="stats-items-form-item">
@ -89,17 +88,17 @@
</el-checkbox-group>
</el-form-item>
</div>
</div>
</el-col>
</el-row>
</el-form>
</el-col>
</el-row>
</el-form>
</div>
<!-- statsType==1 查询表格 0 统计 -->
<div class="print_box">
<div class="print_content" :style="{ width: Template.statsType == 1 ? '100%' : '70%' }">
<div class="title" v-if="statsTitle">{{ formatDict(userStore.sysLoginParam.loginYLJG, 'HOS') }}</div>
<div class="content">{{ statsTitle }}</div>
<div class="table-container bb_table" :style="{ height: `calc(100% - ${statsTitle ? '70px' : '15px'})` }">
<vxe-table :data="tableData" border v-loading="loading" height="100%"
<vxe-table :data="tableData" border v-loading="loading" height="100%" size="mini"
:tooltip-config="{ appendToBody: true, zIndex: 3000 }" show-footer :footer-method="getSummaries"
:scroll-y="{ enabled: true, rSize: 30, height: '100%', oSize: 20, gt: 30, }" show-footer-overflow
@cell-dblclick="cellDblclickEvent">
@ -452,31 +451,69 @@ onMounted(() => {
display: flex;
flex-direction: column;
overflow: auto;
background-color: #eee;
background-color: #d5d5d5;
}
.stats-form {
margin-bottom: 6px;
margin-bottom: 0;
}
.unified-panel {
background: #e6f7fa;
border-right: 1px solid #d9e8fb;
border-bottom: 1px solid #d9e8fb;
border-left: 1px solid #d9e8fb;
border-radius: 0 0 8px 8px;
box-sizing: border-box;
overflow: hidden;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15);
margin-top: -10px;
}
.btn-bar {
padding: 8px 12px 8px 12px;
}
.divider-h {
height: 3px;
background: #f8fbff;
border-top: 1px solid #a0b8d0;
border-bottom: 1px solid #fff;
margin: 0 12px;
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.08);
}
.stats-form-row {
align-items: stretch;
}
.form-panel {
height: 100%;
padding: 5px 12px;
background: #f8fbff;
border: 1px solid #d9e8fb;
border-radius: 8px;
.panel-section {
padding: 8px 12px;
box-sizing: border-box;
}
.panel-section + .panel-section {
position: relative;
&::before {
content: '';
position: absolute;
left: 0;
top: 8px;
bottom: 8px;
width: 3px;
background: #f8fbff;
border-left: 1px solid #a0b8d0;
border-right: 1px solid #fff;
box-shadow: inset 1px 0 2px rgba(0, 0, 0, 0.08);
}
}
.panel-content {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
gap: 4px 12px;
display: grid !important;
grid-template-columns: repeat(auto-fill, 230px);
gap: 4px 6px;
align-items: start;
}
.panel-content-left {
@ -485,16 +522,35 @@ onMounted(() => {
.panel-content-right {
min-height: 0;
display: flex !important;
}
.panel-content-right .stats-items-form-item {
width: 100% !important;
}
.stats-form :deep(.el-form-item) {
margin-right: 0;
margin-bottom: 2px;
display: flex !important;
width: 100% !important;
margin-right: 0 !important;
margin-bottom: 0 !important;
}
.stats-form :deep(.el-form-item__label) {
padding-right: 8px;
padding-right: 4px !important;
color: #4b5563;
text-align: left;
flex-shrink: 0;
}
.stats-form :deep(.el-form-item__content) {
flex: 1;
min-width: 0;
}
.stats-form :deep(.checkbox-form-item .el-form-item__content) {
display: flex;
justify-content: center;
}
@ -517,6 +573,7 @@ onMounted(() => {
font-size: 20px;
text-align: center;
font-weight: 600;
font-family: SimSun, "宋体", serif;
}
.content {
@ -524,18 +581,21 @@ onMounted(() => {
text-align: center;
margin-top: 10px;
font-weight: 600;
font-family: SimSun, "宋体", serif;
}
.print_box {
flex: 1;
display: flex;
justify-content: center;
margin-top: 12px;
.print_content {
width: 70%;
height: 100%;
background-color: #fff;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15);
}
}
@ -544,6 +604,48 @@ onMounted(() => {
min-height: 0;
}
.table-container :deep(.vxe-table) {
--vxe-table-row-height: 24px !important;
--vxe-table-header-row-height: 28px !important;
--vxe-table-footer-row-height: 24px !important;
}
.table-container :deep(.vxe-body--row),
.table-container :deep(.vxe-header--row),
.table-container :deep(.vxe-footer--row),
.table-container :deep(tr) {
height: 24px !important;
min-height: 24px !important;
max-height: 24px !important;
line-height: 24px !important;
}
.table-container :deep(.vxe-header--row),
.table-container :deep(thead tr) {
height: 28px !important;
min-height: 28px !important;
max-height: 28px !important;
}
.table-container :deep(.vxe-cell),
.table-container :deep(td),
.table-container :deep(.vxe-body--column .vxe-cell),
.table-container :deep(th) {
padding: 0 4px !important;
line-height: 24px !important;
height: 24px !important;
font-family: SimSun, "宋体", serif;
}
.table-container :deep(thead th) {
height: 28px !important;
line-height: 28px !important;
}
.table-container :deep(.vxe-header--column .vxe-cell) {
font-weight: 600;
}
.tips {
font-size: 15px;
font-weight: 600;
@ -566,8 +668,8 @@ onMounted(() => {
@media (max-width: 1400px) {
.checkbox-form-item {
min-width: 180px;
.panel-content {
grid-template-columns: repeat(auto-fill, 215px);
}
.stats-checkbox-group :deep(.el-checkbox) {