308 lines
11 KiB
Vue
Raw Normal View History

2025-12-31 17:28:54 +08:00
/**
* @file index.vue 批号管理
* @author: w
* @since: 2025-12-31
*/
<template>
<div class="app-container">
<div class="table-toolbar mb5">
<el-row>
<el-col :span="8">
<el-button type="primary" plain icon="Check" @click="handleSave">保存</el-button>
<el-button type="primary" @click="addHandle">新增</el-button>
<el-button type="danger">删除</el-button>
</el-col>
<el-col :span="16">
<span class="tips">靶值列表</span> &nbsp;
2026-01-09 17:19:49 +08:00
<el-button type="primary" plain @click="dateClick">复制第一个开始日期到每个项目</el-button>
2025-12-31 17:28:54 +08:00
</el-col>
</el-row>
</div>
<el-row :gutter="10" class="table-row">
<el-col :span="8" class="table-col left-table">
2026-01-07 17:27:37 +08:00
<CustomVxeTable ref="leftTableRef" class="mytable-style" :table-data="tableData" :columns="columns"
:row-config="{ isHover: true, keyField: 'batchno' }"
:scrollYConfig="{ enabled: true, rSize: 30, height: '100%', }">
<template #useflag="{ row }">
<el-checkbox :model-value="row.useflag == 1" readonly></el-checkbox>
</template>
</CustomVxeTable>
2025-12-31 17:28:54 +08:00
</el-col>
<el-col :span="16" class="table-col">
<div style="height:59%" class="mb8">
2026-01-09 17:19:49 +08:00
<CustomVxeTable ref="topTableRef" class="mytable-style" :table-data="topTableData" :columns="topColumns"
@current-change="rowClick" :row-config="{ isHover: true, keyField: 'xmdh' }"
:scrollYConfig="{ enabled: true, rSize: 30, height: '100%', }">
2025-12-31 17:28:54 +08:00
<template #xmdh="{ row }">
{{ row.xmdh }} {{ row.xmmc }}
</template>
2026-01-09 17:19:49 +08:00
<template #zkbz="{ row }">
<el-input v-model="row.zkbz" class="full-width-input" />
2025-12-31 17:28:54 +08:00
</template>
2026-01-09 17:19:49 +08:00
<template #sd="{ row }">
<el-input v-model="row.sd" class="full-width-input" />
2025-12-31 17:28:54 +08:00
</template>
2026-01-09 17:19:49 +08:00
<template #cv="{ row }">
<el-input v-model="row.cv" class="full-width-input" />
</template>
<template #bc="{ row }">
<el-input v-model="row.bc" class="full-width-input" />
</template>
<template #ksrq="{ row }">
<el-date-picker v-model="row.ksrq" type="date" value-format="YYYY-MM-DD" class="full-width-input"
style="width:100%" />
</template>
<template #stopdate="{ row }">
<el-date-picker v-model="row.stopdate" type="date" value-format="YYYY-MM-DD" class="full-width-input"
style="width:100%" />
</template>
<template #ff="{ row }">
<el-select v-model="row.ff" placeholder="请选择" class="full-width-input">
<!-- <el-option /> -->
</el-select>
</template>
<template #sjph="{ row }">
<el-select v-model="row.sjph" placeholder="请选择" class="full-width-input">
<!-- <el-option /> -->
</el-select>
</template>
<template #qccv="{ row }">
<el-input v-model="row.qccv" class="full-width-input" />
</template>
</CustomVxeTable>
2025-12-31 17:28:54 +08:00
</div>
<div style="height:40%">
<CustomTable ref="rightTableRef" :data="bottomTableData" :columns="bottomColumns" :enableColumnDrag="true"
@column-drag-end="columnDragEnd" :config="{ border: true, highlightCurrentRow: true, height: '100%' }">
</CustomTable>
</div>
</el-col>
</el-row>
2026-01-07 17:27:37 +08:00
<el-dialog title="批号" v-model="visible" width="30vw" :close-on-click-modal="false" :draggable="true"
@close="handleDialogClose">
2025-12-31 17:28:54 +08:00
<el-form :model="formData" ref="queryRef" :rules="rules" label-position="right" label-width="auto">
2026-01-07 17:27:37 +08:00
<el-form-item label="仪器" prop="yq">
<span class="mr20"> {{ formData.yq }}</span>
<el-radio-group v-model="formData.useflag">
<el-radio value="1">在用</el-radio>
<el-radio value="0">停用</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="质控批号" prop="zkpph">
<el-input v-model="formData.zkpph" />
2025-12-31 17:28:54 +08:00
</el-form-item>
2026-01-07 17:27:37 +08:00
<el-form-item label="水平" prop="zkph">
<el-select v-model="formData.zkph" placeholder="请选择">
2025-12-31 17:28:54 +08:00
<el-option />
</el-select>
</el-form-item>
2026-01-07 17:27:37 +08:00
<el-form-item label="浓度" prop="conc">
<el-select v-model="formData.conc" placeholder="请选择">
2025-12-31 17:28:54 +08:00
<el-option />
</el-select>
</el-form-item>
2026-01-07 17:27:37 +08:00
<el-form-item label="批号(瓶子上的)" prop="batchno">
<el-input v-model="formData.batchno" />
2025-12-31 17:28:54 +08:00
</el-form-item>
2026-01-07 17:27:37 +08:00
<el-form-item label="有效期" prop="expiredt">
<el-date-picker v-model="formData.expiredt" type="date" value-format="YYYY-MM-DD" />
2025-12-31 17:28:54 +08:00
</el-form-item>
2026-01-07 17:27:37 +08:00
<el-form-item label="启用日期" prop="ksrq">
<el-date-picker v-model="formData.ksrq" type="date" value-format="YYYY-MM-DD" />
2025-12-31 17:28:54 +08:00
</el-form-item>
2026-01-07 17:27:37 +08:00
<el-form-item label="结束日期" prop="endda">
<el-date-picker v-model="formData.endda" type="date" value-format="YYYY-MM-DD" />
2025-12-31 17:28:54 +08:00
</el-form-item>
2026-01-07 17:27:37 +08:00
<el-form-item label="质控厂商" prop="qcsrc">
<el-select v-model="formData.qcsrc" placeholder="请选择">
2025-12-31 17:28:54 +08:00
<el-option />
</el-select>
</el-form-item>
2026-01-07 17:27:37 +08:00
<el-form-item label="校准品厂商" prop="standsrc">
<el-select v-model="formData.standsrc" placeholder="请选择">
2025-12-31 17:28:54 +08:00
<el-option />
</el-select>
</el-form-item>
2026-01-07 17:27:37 +08:00
<el-form-item label="备注" prop="bk">
<el-input v-model="formData.bk" type="textarea" :row="5" />
2025-12-31 17:28:54 +08:00
</el-form-item>
</el-form>
<template #footer>
<el-button @click="visible = false">取消</el-button>
2026-01-07 17:27:37 +08:00
<el-button type="primary" @click="submit">确定</el-button>
2025-12-31 17:28:54 +08:00
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
2026-01-07 17:27:37 +08:00
import { queryBatch, queryQcSample, queryBatchXm } from '@/api/liswork/qualityControl'
import { templateRef } from '@vueuse/core'
2026-01-09 17:19:49 +08:00
import { ElMessage } from 'element-plus'
2025-12-31 17:28:54 +08:00
const yq = defineModel<string>()
const visible = ref(false)
const selectedRow = ref()
2026-01-07 17:27:37 +08:00
const queryRef = templateRef('queryRef')
const formData = ref({
yq: yq,
zkpph: '',
zkph: '',
conc: '',
useflag: '1',
batchno: '',
expiredt: '',
ksrq: '',
endda: '',
qcsrc: '',
standsrc: '',
bk: ''
})
const rules = ref({
zkpph: [{ required: true, message: '请输入质控批号', trigger: 'blur' }],
zkph: [{ required: true, message: '请选择水平', trigger: 'change' }],
ksrq: [{ required: true, message: '请选择启用日期', trigger: 'change' }],
})
2025-12-31 17:28:54 +08:00
const tableData = ref([])
const columns = ref([
2026-01-07 17:27:37 +08:00
{ title: '质控批号', field: 'zkpph', width: 80, resizable: true, align: 'center' },
{ title: '水平', field: 'zkph', resizable: true, align: 'center' },
{ title: '浓度', field: 'conc', resizable: true, align: 'center' },
{ title: '在用', field: 'useflag', resizable: true, align: 'center', slotName: 'useflag' },
{ title: '启用日期', field: 'ksrq', width: 90, resizable: true, align: 'center' },
{ title: '停用日期', field: 'endda', width: 90, resizable: true, align: 'center' },
{ title: '批号(瓶子上的)', field: 'batchno', resizable: true, align: 'center', width: 100 },
{ title: '有效期', field: 'expiredt', width: 90, resizable: true, align: 'center' },
{ title: '质控来源', field: 'qcsrc', width: 80, resizable: true, align: 'center' },
{ title: '校准品厂商', field: 'standsrc', width: 80, resizable: true, align: 'center' },
{ title: '备注', field: 'bk', resizable: true, align: 'center', width: 100 },
{ title: '仪器', field: 'yq', resizable: true, align: 'center', },
2025-12-31 17:28:54 +08:00
])
2026-01-09 17:19:49 +08:00
const topTableData: any = ref([])
2025-12-31 17:28:54 +08:00
const topColumns = [
2026-01-09 17:19:49 +08:00
{ title: '项目代号', field: 'xmdh', resizable: true, slotName: 'xmdh', width: 150 },
{ title: '靶值', field: 'zkbz', resizable: true, align: 'center', slotName: 'zkbz' },
{ title: 'Sd', field: 'sd', resizable: true, align: 'center', slotName: 'sd' },
{ title: 'Cv', field: 'cv', resizable: true, align: 'center', slotName: 'cv' },
{ title: '开始日期', field: 'ksrq', resizable: true, align: 'center', slotName: 'ksrq', width: 100 },
{ title: '结束日期', field: 'stopdate', resizable: true, align: 'center', slotName: 'stopdate', width: 100 },
{ title: '波长', field: 'bc', resizable: true, align: 'center', slotName: 'bc', },
{ title: '方法', field: 'ff', resizable: true, align: 'center', slotName: 'ff', },
{ title: '试剂', field: 'sjph', resizable: true, align: 'center', slotName: 'sjph', },
{ title: '目标CV(%)', field: 'qccv', resizable: true, align: 'center', slotName: 'qccv', width: 80 },
2025-12-31 17:28:54 +08:00
]
const bottomTableData = ref([])
const bottomColumns = ref([
{ label: '项目代号', prop: 'xmdh', visible: true, slot: 'xmdh', width: 150 },
{ label: '靶值', prop: 'zkbz', visible: true, align: 'center', },
2026-01-07 17:27:37 +08:00
{ label: 'Sd', prop: 'sd', visible: true, align: 'center', },
2025-12-31 17:28:54 +08:00
{ label: 'Cv', prop: 'cv', visible: true, align: 'center', },
{ label: '开始日期', prop: 'ksrq', visible: true, align: 'center', },
2026-01-07 17:27:37 +08:00
{ label: '结束日期', prop: 'stopdate', visible: true, align: 'center', },
2025-12-31 17:28:54 +08:00
{ label: '波长', prop: 'bc', visible: true, align: 'center', },
{ label: '方法', prop: 'ff', visible: true, align: 'center', },
{ label: '试剂', prop: 'sjph', visible: true, align: 'center', },
{ label: '目标CV(%)', prop: 'qccv', visible: true, align: 'center', },
])
const columnDragEnd = (data: any) => {
bottomColumns.value = data.columns
}
const rowClick = (row: any) => {
selectedRow.value = row
const data = {
xmdh: row.xmdh,
yq: yq.value,
}
queryQcSample(data).then((res: any) => {
bottomTableData.value = res.data
})
}
2026-01-09 17:19:49 +08:00
const dateClick = () => {
if (!topTableData.value[0].ksrq) return
topTableData.value.forEach((item: any) => {
item.ksrq = topTableData.value[0].ksrq
})
}
2025-12-31 17:28:54 +08:00
const addHandle = () => {
visible.value = true
}
2026-01-07 17:27:37 +08:00
const submit = () => {
queryRef.value.validate((valid: boolean) => {
if (!valid) return false;
})
}
2025-12-31 17:28:54 +08:00
2026-01-07 17:27:37 +08:00
const handleDialogClose = () => {
queryRef.value.resetFields()
formData.value = {
yq: yq,
zkpph: '',
zkph: '',
conc: '',
useflag: '1',
batchno: '',
expiredt: '',
ksrq: '',
endda: '',
qcsrc: '',
standsrc: '',
bk: ''
}
}
const getBatchList = () => {
queryBatch({ yq: yq.value, pageNum: 1, pageSize: 9999 }).then((res: any) => {
tableData.value = res.rows || []
})
}
2025-12-31 17:28:54 +08:00
const getXmList = () => {
2026-01-07 17:27:37 +08:00
queryBatchXm({ yq: yq.value, }).then((res: any) => {
2025-12-31 17:28:54 +08:00
topTableData.value = res.data
2026-01-09 17:19:49 +08:00
// rowClick(topTableData.value[0])
2025-12-31 17:28:54 +08:00
})
}
const handleSave = () => { }
watch(yq, (val) => {
if (val) {
2026-01-07 17:27:37 +08:00
getBatchList()
2025-12-31 17:28:54 +08:00
getXmList()
}
}, { immediate: true })
</script>
<style scoped lang="scss">
.tips {
font-family: SourceHanSansCN, SourceHanSansCN;
font-size: 16px;
color: #409eff;
font-weight: 600;
height: 32px;
}
.table-row {
height: calc(100% - 105px);
.table-col {
height: 100%;
}
.left-table {
height: 100%;
}
}
2026-01-09 17:19:49 +08:00
:deep(.el-input__prefix) {
display: none;
}
2025-12-31 17:28:54 +08:00
</style>