质控批号查询

This commit is contained in:
wyuu 2026-01-13 11:45:42 +08:00
parent 98894a3582
commit a897319ef6
8 changed files with 181 additions and 55 deletions

View File

@ -41,10 +41,11 @@ export function queryQcSample(data?: Object) {
params: data
})
}
// 查询质控品数据
export function saveQcSample(data?: Object) {
return request({
url: '/qc/saveQcSample',
url: '/qc/saveQcFromSample',
method: 'post',
data
})
@ -52,7 +53,7 @@ export function saveQcSample(data?: Object) {
// -删除普通标本和质控标本对应关系
export function deleteQcSample(data?: Object) {
return request({
url: '/qc/deleteQcSample',
url: '/qc/deleteQcFromSample',
method: 'get',
params: data
})
@ -65,6 +66,30 @@ export function queryBatch(data?: Object) {
params: data
})
}
// 新增质控批号
export function addBatchno(data?: Object) {
return request({
url: '/qc/addBatchno',
method: 'post',
data
})
}
// 修改质控批号
export function updateBatchno(data?: Object) {
return request({
url: '/qc/updateBatchno',
method: 'post',
data
})
}
// 删除质控批号
export function delBatchno(data?: Object) {
return request({
url: '/qc/delBatchno',
method: 'delete',
params: data
})
}
// 查询质控批号 获取项目列表
export function queryBatchXm(data?: Object) {
return request({
@ -73,3 +98,12 @@ export function queryBatchXm(data?: Object) {
params: data
})
}
// 获取项目列表
export function queryValXmdh(data?: Object) {
return request({
url: '/qc/queryValXmdh',
method: 'get',
params: data
})
}

View File

@ -42,12 +42,14 @@
import { ref, nextTick, watch, onMounted } from 'vue'
// @ts-ignore
import Sortable from 'sortablejs'; // 引入sortablejs
import type { VxeComponentSizeType, VxeColumnPropTypes } from 'vxe-table'
// 定义列配置类型
interface TableColumn {
field: string
title: string
width?: number | string
align?: string
align?: string,
slotName?: string // 自定义插槽名称
[key: string]: any // 支持其他vxe-column属性
}
@ -101,7 +103,7 @@ const props = defineProps({
},
// 表格尺寸
size: {
type: String,
type: String as () => VxeComponentSizeType,
default: 'medium'
},
// 拖拽列

View File

@ -21,7 +21,7 @@ NProgress.configure({
showSpinner: false
});
const whiteList = ['/login', '/register', '/report', '/checkCode'];
const whiteList = ['/login', '/register', '/report', '/zycx/checkCode'];
router.beforeEach((to, from, next) => {
NProgress.start()

View File

@ -183,10 +183,10 @@ const route = useRoute()
const userStore = useUserStore()
const printStore = usePrintStore();
//@ts-ignore
const { proxy } = getCurrentInstance();
import { getDicts } from '@/api/system/dict/data'
const compactForm = ref<HTMLElement | null>(null);
const { lis_req_type } = proxy.useDict("lis_req_type"); //参数类别
const lisReqs: any = ref([])
const dialogVisible = ref(false)
const title = ref('采样登记')
@ -317,7 +317,7 @@ const cellStyleHd = ({ row, column, rowIndex, columnIndex }: {
};
}
if (column.title == "状态") {
const bgColor = lis_req_type.value.find((item: any) => item.value == row.zt.trim())?.elTagClass || '#FFF';
const bgColor = lisReqs.value.find((item: any) => item.value == row.zt.trim())?.elTagClass || '#FFF';
return {
backgroundColor: `${bgColor} !important`,
};
@ -589,16 +589,26 @@ onMounted(async () => {
// 计算前6天的日期(当天 + 前6天 = 7天)
const startOfWeek = today.subtract(6, 'day');
// const startDate = route.query.startdate ? String(route.query.startdate) : startOfWeek.format('YYYY-MM-DD HH:mm:ss');
// const endDate = route.query.endate ? String(route.query.endate) : today.format('YYYY-MM-DD HH:mm:ss');
const startDate = route.query.startdate ? String(route.query.startdate) : startOfWeek.format('YYYY-MM-DD HH:mm:ss');
const endDate = route.query.endate ? String(route.query.endate) : today.format('YYYY-MM-DD HH:mm:ss');
// queryParams.times = [startDate, endDate];
queryParams.times = [startDate, endDate];
queryParams.ksdh = (route.query.deptcode as string) ? (route.query.deptcode as string) : '';
queryParams.userid = (route.query.userid as string) ? (route.query.userid as string) : '';
queryParams.yljg = (route.query.yljg as string) ? (route.query.yljg as string) : '1';
// 进入页面单点登录
const result = await userStore.loginAnonymous({ name: queryParams.userid, yljg: queryParams.yljg })
if (result) {
// 获取状态字典
getDicts('lis_req_type').then((resp: any) => {
lisReqs.value = resp.data.map((p: any) => ({
label: p.dictLabel,
value: p.dictValue,
elTagType: p.listClass,
elTagClass: p.cssClass
}))
})
getList()
}

View File

@ -9,19 +9,24 @@
<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-button type="primary" plain @click="addHandle">新增</el-button>
<el-button type="warning" plain @click="editHandle">修改</el-button>
<el-button type="danger" plain @click="delBatch">删除</el-button>
</el-col>
<el-col :span="16">
<span class="tips">靶值列表</span> &nbsp;
<el-button type="primary" plain @click="dateClick">复制第一个开始日期到每个项目</el-button>
<el-button type="primary" plain @click="">复制靶值</el-button>
<el-button type="primary" plain @click="">新增靶值</el-button>
<el-button type="danger" plain @click="">删除靶值</el-button>
<el-button type="primary" plain @click="">计算</el-button>
</el-col>
</el-row>
</div>
<el-row :gutter="10" class="table-row">
<el-col :span="8" class="table-col left-table">
<CustomVxeTable ref="leftTableRef" class="mytable-style" :table-data="tableData" :columns="columns"
:row-config="{ isHover: true, keyField: 'batchno' }"
:row-config="{ isHover: true, keyField: 'batchno' }" @current-change="batchClick"
:scrollYConfig="{ enabled: true, rSize: 30, height: '100%', }">
<template #useflag="{ row }">
<el-checkbox :model-value="row.useflag == 1" readonly></el-checkbox>
@ -31,7 +36,8 @@
<el-col :span="16" class="table-col">
<div style="height:59%" class="mb8">
<CustomVxeTable ref="topTableRef" class="mytable-style" :table-data="topTableData" :columns="topColumns"
@current-change="rowClick" :row-config="{ isHover: true, keyField: 'xmdh' }"
:cell-render-delay="10" :loading="loading" @current-change="rowClick"
:row-config="{ isHover: true, keyField: 'xmdh' }"
:scrollYConfig="{ enabled: true, rSize: 30, height: '100%', }">
<template #xmdh="{ row }">
{{ row.xmdh }} {{ row.xmmc }}
@ -57,14 +63,10 @@
style="width:100%" />
</template>
<template #ff="{ row }">
<el-select v-model="row.ff" placeholder="请选择" class="full-width-input">
<!-- <el-option /> -->
</el-select>
<SelectTable v-model:data="row.ff" :tableData="dictData.MD" placeholder="" class="full-width-input" />
</template>
<template #sjph="{ row }">
<el-select v-model="row.sjph" placeholder="请选择" class="full-width-input">
<!-- <el-option /> -->
</el-select>
<SelectTable v-model:data="row.sjph" :tableData="dictData.TK" placeholder="" class="full-width-input" />
</template>
<template #qccv="{ row }">
<el-input v-model="row.qccv" class="full-width-input" />
@ -74,12 +76,21 @@
<div style="height:40%">
<CustomTable ref="rightTableRef" :data="bottomTableData" :columns="bottomColumns" :enableColumnDrag="true"
@column-drag-end="columnDragEnd" :config="{ border: true, highlightCurrentRow: true, height: '100%' }">
<template #xmdh="{ row }">
{{ row.xmdh }} {{ row.xmmc }}
</template>
<template #ff="{ row }">
{{ formatDict(row.ff, 'MD') }}
</template>
<template #sjph="{ row }">
{{ formatDict(row.sjph, 'TK') }}
</template>
</CustomTable>
</div>
</el-col>
</el-row>
<el-dialog title="批号" v-model="visible" width="30vw" :close-on-click-modal="false" :draggable="true"
<el-dialog :title="title" v-model="visible" width="30vw" :close-on-click-modal="false" :draggable="true"
@close="handleDialogClose">
<el-form :model="formData" ref="queryRef" :rules="rules" label-position="right" label-width="auto">
<el-form-item label="仪器" prop="yq">
@ -139,14 +150,15 @@
</template>
<script setup lang="ts">
import { queryBatch, queryQcSample, queryBatchXm } from '@/api/liswork/qualityControl'
import { queryBatch, queryValXmdh, queryBatchXm, delBatchno, addBatchno, updateBatchno } from '@/api/liswork/qualityControl'
import { templateRef } from '@vueuse/core'
import { ElMessage } from 'element-plus'
import { formatDict, getDictData, dictData } from '@/hooks';
import { ElMessage, ElMessageBox } from 'element-plus'
const yq = defineModel<string>()
const title = ref('新增批号')
const visible = ref(false)
const selectedRow = ref()
const selectedRow = ref(null)
const queryRef = templateRef('queryRef')
const formData = ref({
yq: yq,
@ -167,6 +179,7 @@ const rules = ref({
zkph: [{ required: true, message: '请选择水平', trigger: 'change' }],
ksrq: [{ required: true, message: '请选择启用日期', trigger: 'change' }],
})
const loading = ref(false)
const tableData = ref([])
const columns = ref([
{ title: '质控批号', field: 'zkpph', width: 80, resizable: true, align: 'center' },
@ -204,8 +217,8 @@ const bottomColumns = ref([
{ label: '开始日期', prop: 'ksrq', visible: true, align: 'center', },
{ label: '结束日期', prop: 'stopdate', visible: true, align: 'center', },
{ label: '波长', prop: 'bc', visible: true, align: 'center', },
{ label: '方法', prop: 'ff', visible: true, align: 'center', },
{ label: '试剂', prop: 'sjph', visible: true, align: 'center', },
{ label: '方法', prop: 'ff', visible: true, align: 'center', slot: 'ff', },
{ label: '试剂', prop: 'sjph', visible: true, align: 'center', slot: 'sjph', },
{ label: '目标CV(%)', prop: 'qccv', visible: true, align: 'center', },
])
@ -217,9 +230,11 @@ const rowClick = (row: any) => {
selectedRow.value = row
const data = {
xmdh: row.xmdh,
zkpph: row.zkpph,
zkph: row.zkph,
yq: yq.value,
}
queryQcSample(data).then((res: any) => {
queryValXmdh(data).then((res: any) => {
bottomTableData.value = res.data
})
}
@ -232,12 +247,48 @@ const dateClick = () => {
}
const addHandle = () => {
title.value = '新增批号'
visible.value = true
}
const editHandle = () => {
if (!batchInfo.value) {
ElMessage.error('请选择要修改的行')
return
}
formData.value = batchInfo.value
title.value = '修改批号'
visible.value = true
}
const delBatch = () => {
if (!batchInfo.value) return ElMessage.warning('请选择要删除的行')
ElMessageBox.confirm('是否确认删除选中数据?', '提示', {
type: 'warning'
}).then(() => {
delBatchno(batchInfo.value).then((res: any) => {
if (res.code == 0) {
ElMessage.success('删除成功')
getBatchList()
}
})
})
}
const submit = () => {
queryRef.value.validate((valid: boolean) => {
if (!valid) return false;
return
if (title.value == '修改批号') {
updateBatchno(formData.value).then((res: any) => {
})
} else {
addBatchno(formData.value).then((res: any) => {
})
}
})
}
@ -258,16 +309,24 @@ const handleDialogClose = () => {
bk: ''
}
}
const batchInfo: any = ref(null)
const batchClick = (row: any) => {
batchInfo.value = row
getXmList(row)
}
const getBatchList = () => {
batchInfo.value = null
loading.value = true
queryBatch({ yq: yq.value, pageNum: 1, pageSize: 9999 }).then((res: any) => {
tableData.value = res.rows || []
loading.value = false
tableData.value = res.data || []
getXmList(tableData.value[0])
})
}
const getXmList = () => {
queryBatchXm({ yq: yq.value, }).then((res: any) => {
const getXmList = (row: any) => {
queryBatchXm({ yq: yq.value, zkpph: row.zkpph, zkph: row.zkph }).then((res: any) => {
topTableData.value = res.data
// rowClick(topTableData.value[0])
rowClick(topTableData.value[0])
})
}
@ -276,7 +335,6 @@ const handleSave = () => { }
watch(yq, (val) => {
if (val) {
getBatchList()
getXmList()
}
}, { immediate: true })
</script>

View File

@ -17,10 +17,10 @@
<el-input v-model="row.ybh" class="full-width-input" />
</template>
<template #zkph="{ row }">
<el-input v-model="row.zkph" class="full-width-input" />
<el-input-number v-model="row.zkph" min="1" max="6" class="full-width-input" />
</template>
<template #cs="{ row }">
<el-input v-model="row.cs" class="full-width-input" />
<el-input-number v-model="row.cs" min="1" max="7" class="full-width-input" />
</template>
</CustomTable>
</div>
@ -59,8 +59,8 @@ const rowYbhClick = (row: ybhItem) => {
const addItem = () => {
tableData.value.push({
ybh: '',
zkph: '',
cs: '',
zkph: '1',
cs: '1',
yq: yq.value,
})
nextTick(() => {
@ -73,15 +73,17 @@ const delItem = () => {
deleteQcSample(ybhInfo.value).then((res: any) => {
if (res.code == 0) {
ElMessage.success('删除成功')
ybhInfo.value = null
const index = tableData.value.findIndex(item => item == ybhInfo.value)
tableData.value.splice(index, 1)
ybhInfo.value = null
}
})
}
const handleSave = () => {
saveQcSample({ qcFrmsmplList: tableData.value }).then((res: any) => {
const flag = tableData.value.every(item => item.ybh && item.zkph && item.cs)
if (!flag) return ElMessage.warning('请填写完整信息')
saveQcSample(tableData.value).then((res: any) => {
if (res.code == 0) {
ElMessage.success('保存成功')
getSampleList()
@ -90,6 +92,7 @@ const handleSave = () => {
}
const getSampleList = () => {
ybhInfo.value = null
queryDataFromSample({ yq: yq.value }).then((res: any) => {
tableData.value = res.data
})

View File

@ -57,8 +57,6 @@ import SetProject from './components/setProject/index.vue';
import SetParams from './components/setParams/index.vue';
import SetBatch from './components/setBatch/index.vue';
import SetSample from './components/setSample/index.vue';
import SetEnterResult from './components/setEnterResult/index.vue';
const mbStore = useCommonStore();
// ========== TypeScript 类型定义 ==========
@ -117,7 +115,6 @@ const tabList = [
{ key: 'SetParams', label: '质控品参数设置', component: SetParams },
{ key: 'SetSample', label: '质控品样本号对应', component: SetSample },
{ key: 'SetBatch', label: '质控品批号管理', component: SetBatch },
{ key: 'SetEnterResult', label: '质控结果手工录入', component: SetEnterResult },
]
const activeName = ref('SetBatch')
@ -253,6 +250,7 @@ const getDeptTree = async (): Promise<void> => {
onMounted(() => {
getDictData('MD', 'TK')
})
// ========== 初始化 ==========
getDeptTree()

View File

@ -7,11 +7,28 @@
<template>
<div class="app-container">
<div class="handle-box mb5">
<el-button type="primary" plain icon="Check" @click="handleSave">保存</el-button>
<el-form>
<el-row :gutter="20">
<el-col :span="4">
<el-form-item label="仪器:">
<YQSelectTable v-model:data="yq" width="200px" clearable @get-data-value="getXmList" />
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="日期:">
<el-date-picker v-model="jyrq" type="date" value-format="YYYY-MM-DD" style="width:100%" />
</el-form-item>
</el-col>
<el-col :span="5">
<span class="tips ml10">颜色说明:</span> <span class="color-red">大于3SD</span> <span
class="color-pink">大于2SD</span>
</el-col>
</el-row>
</el-form>
</div>
<div class="handle-box mb5">
<el-date-picker v-model="jyrq" type="date" value-format="YYYY-MM-DD" />
<span class="tips ml10">颜色说明:</span> <span class="color-red">大于3SD</span> <span class="color-pink">大于2SD</span>
<div class="mb5">
<el-button type="primary" plain icon="Check" @click="handleSave">保存</el-button>
</div>
<el-tabs v-model="activeName" type="card" class="tabs_box">
<el-tab-pane v-for="tab in tabList" :key="tab.key" :label="tab.label" :name="tab.key" />
@ -51,8 +68,12 @@
<script setup lang="ts">
import { queryOldxminfo } from '@/api/liswork/xtwh/xmReqItemVsApi'
import YQSelectTable from '@/components/SelectTable/YQSelectTable/index.vue';
import dayjs from 'dayjs'
const yq = defineModel<string>()
import { useCommonStore } from '@/store/modules/commonStore';
const mbStore = useCommonStore();
const yq = ref(mbStore.defaultConfig.defaultinstr || '46')
const activeName = ref('1')
const jyrq = ref(dayjs().format('YYYY-MM-DD'))
const tabList = [
@ -108,17 +129,13 @@ const getXmList = () => {
const handleSave = () => { }
watch(yq, (val) => {
if (val) {
getXmList()
}
}, { immediate: true })
</script>
<style scoped lang="scss">
.table-box {
margin-top: 5px;
height: calc(100% - 175px);
height: calc(100% - 125px);
}
.tips {
@ -139,4 +156,8 @@ watch(yq, (val) => {
color: #fff;
padding: 2px;
}
:deep(.el-form-item) {
margin-bottom: 5px;
}
</style>