质控录入
This commit is contained in:
parent
b584460dd8
commit
be3703bd7a
@ -107,3 +107,11 @@ export function queryValXmdh(data?: Object) {
|
|||||||
params: data
|
params: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// 查询质控品录入
|
||||||
|
export function getqcval(data?: Object) {
|
||||||
|
return request({
|
||||||
|
url: '/qc/getqcval',
|
||||||
|
method: 'get',
|
||||||
|
params: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@ -30,11 +30,19 @@
|
|||||||
<el-empty v-if="filterData.length === 0" description="没有匹配的数据" :image-size="100" />
|
<el-empty v-if="filterData.length === 0" description="没有匹配的数据" :image-size="100" />
|
||||||
<div @keydown="handleKeydown" v-else tabindex="0" style="outline: none;">
|
<div @keydown="handleKeydown" v-else tabindex="0" style="outline: none;">
|
||||||
<!-- 数据存在时显示表格 -->
|
<!-- 数据存在时显示表格 -->
|
||||||
<el-table ref="tableRef" :data="filterData" :highlight-current-row="props.isHighlight" style="width: 100%"
|
<!-- <el-table ref="tableRef" :data="filterData" :highlight-current-row="props.isHighlight" style="width: 100%"
|
||||||
:border="props.border" @row-click="handleRowChange" max-height="350px" :row-style="{ height: '25px' }">
|
:border="props.border" @row-click="handleRowChange" max-height="350px" :row-style="{ height: '25px' }">
|
||||||
<el-table-column v-for="field in props.fields" :prop="field.prop" :label="field.label"
|
<el-table-column v-for="field in props.fields" :prop="field.prop" :label="field.label"
|
||||||
:width="field.width" show-overflow-tooltip align="center" />
|
:width="field.width" show-overflow-tooltip align="center" />
|
||||||
</el-table>
|
</el-table> -->
|
||||||
|
<vxe-table class="mytable-style" ref="tableRef" border resizable highlight-current-row max-height="350px"
|
||||||
|
:row-config="{ isHover: true, keyField: 'value', height: 30 }" :data="filterData"
|
||||||
|
:current-row="currentRow" @current-change="currentChange"
|
||||||
|
:tooltip-config="{ appendToBody: true, zIndex: 3000 }" :show-overflow="true"
|
||||||
|
:scroll-y="{ enabled: true, rSize: 30, height: '100%' }">
|
||||||
|
<vxe-table-column v-for="field in props.fields" :field="field.prop" :title="field.label" align="center"
|
||||||
|
:width="field.width" />
|
||||||
|
</vxe-table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -78,7 +86,7 @@ const filterData = ref<{ [key: string]: any; pinyinMap: Record<string, string> }
|
|||||||
// 存储预处理后的带拼音数据
|
// 存储预处理后的带拼音数据
|
||||||
const processedTableData = ref<{ [key: string]: any; pinyinMap: Record<string, string> }[]>([]);
|
const processedTableData = ref<{ [key: string]: any; pinyinMap: Record<string, string> }[]>([]);
|
||||||
const currentIndex = ref(-1);
|
const currentIndex = ref(-1);
|
||||||
|
const currentRow = ref<any>(null)
|
||||||
// 字典数据存储
|
// 字典数据存储
|
||||||
const dictData = ref<Record<string, any[]>>({});
|
const dictData = ref<Record<string, any[]>>({});
|
||||||
// 预处理数据:生成拼音信息
|
// 预处理数据:生成拼音信息
|
||||||
@ -113,8 +121,8 @@ const visibleChange = (val: any) => {
|
|||||||
|
|
||||||
currentIndex.value = filterData.value.findIndex(item => item[props.value!] === props.data);
|
currentIndex.value = filterData.value.findIndex(item => item[props.value!] === props.data);
|
||||||
if (currentIndex.value >= 0) {
|
if (currentIndex.value >= 0) {
|
||||||
tableRef.value.setCurrentRow(filterData.value[currentIndex.value]);
|
tableRef.value.setCurrentRow(filterData.value[currentIndex.value])
|
||||||
tableRef.value.setScrollTop(currentIndex.value * 30);
|
tableRef.value.scrollToRow(filterData.value[currentIndex.value])
|
||||||
}
|
}
|
||||||
}, 10);
|
}, 10);
|
||||||
}
|
}
|
||||||
@ -233,11 +241,8 @@ const handleKeydown = (e: any) => {
|
|||||||
currentIndex.value = Math.min(maxIndex, currentIndex.value + 1);
|
currentIndex.value = Math.min(maxIndex, currentIndex.value + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
tableRef.value.setCurrentRow(filterData.value[currentIndex.value]);
|
tableRef.value.setCurrentRow(filterData.value[currentIndex.value])
|
||||||
|
tableRef.value.scrollToRow(filterData.value[currentIndex.value])
|
||||||
// 滚动到当前行
|
|
||||||
tableRef.value.setScrollTop(currentIndex.value * 30);
|
|
||||||
|
|
||||||
// 回车确认
|
// 回车确认
|
||||||
if (e.key === "Enter") {
|
if (e.key === "Enter") {
|
||||||
const currentRow = filterData.value[currentIndex.value];
|
const currentRow = filterData.value[currentIndex.value];
|
||||||
@ -284,11 +289,18 @@ const filterDataHandle = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (filterData.value.length > 0) {
|
if (filterData.value.length > 0) {
|
||||||
tableRef.value.setScrollTop(0)
|
nextTick(() => {
|
||||||
tableRef.value.setCurrentRow(filterData.value[0]);
|
tableRef.value.setCurrentRow(filterData.value[0])
|
||||||
|
tableRef.value.scrollToRow(filterData.value[0])
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const currentChange = (params: { row: any }) => {
|
||||||
|
currentRow.value = params.row
|
||||||
|
handleRowChange(params.row)
|
||||||
|
}
|
||||||
|
|
||||||
const handleRowChange = (val: any) => {
|
const handleRowChange = (val: any) => {
|
||||||
emits("update:data", props.value ? val[props.value] : val);
|
emits("update:data", props.value ? val[props.value] : val);
|
||||||
setLabel(val);
|
setLabel(val);
|
||||||
@ -316,11 +328,44 @@ const clearHandle = () => {
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped lang="scss">
|
||||||
.select-table-container {
|
.select-table-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:deep(.vxe-header--row th) {
|
||||||
|
border-color: #1F6DD3;
|
||||||
|
background-color: #1F6DD3;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.vxe-body--row td) {
|
||||||
|
border-color: #1F6DD3;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.vxe-table--row-hover) {
|
||||||
|
background-color: #1F6DD3;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.vxe-table--current-row) {
|
||||||
|
background-color: #1F6DD3;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-table-header-cell) {
|
||||||
|
cursor: move;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 表格边框
|
||||||
|
:deep(.vxe-table--render-default.border--full .vxe-body--column) {
|
||||||
|
background-image: linear-gradient(#96B8D9, #96B8D9), linear-gradient(#96B8D9, #96B8D9) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 表头边框
|
||||||
|
:deep(.vxe-table--render-default.border--full .vxe-header--column) {
|
||||||
|
background-image: linear-gradient(#1F6DD3, #1F6DD3), linear-gradient(#1F6DD3, #1F6DD3) !important;
|
||||||
|
}
|
||||||
|
|
||||||
.select-table-dropdown {
|
.select-table-dropdown {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="app-container ">
|
<div class="app-container ">
|
||||||
<div class="tips">检验科条码打印科室:{{ formatDict(queryParams.ksdh, 'DP') }}</div>
|
<div class="tips">检验科条码打印 科室:{{ formatDict(queryParams.ksdh, 'DP') }} 登录人:{{ formatUser(queryParams.userid) }}</div>
|
||||||
<div ref="compactForm">
|
<div ref="compactForm">
|
||||||
<el-row :gutter="10" class="compact-form" v-show="showSearch">
|
<el-row :gutter="10" class="compact-form" v-show="showSearch">
|
||||||
<el-form :model="queryParams" ref="queryRef" :inline="true" :size="aotuSize" :rules="queryRules">
|
<el-form :model="queryParams" ref="queryRef" :inline="true" :size="aotuSize" :rules="queryRules">
|
||||||
@ -167,6 +167,8 @@ import CustomTable from '@/components/elTable/index.vue'
|
|||||||
import CustomVxeTable from '@/components/vxeTable/index.vue'
|
import CustomVxeTable from '@/components/vxeTable/index.vue'
|
||||||
import { useRouter, useRoute } from 'vue-router'
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
import { usePrintStore } from '@/store/modules/printStore'
|
import { usePrintStore } from '@/store/modules/printStore'
|
||||||
|
// @ts-ignore
|
||||||
|
import { listUser } from '@/api/system/user.js'
|
||||||
import { fetchCodeList, addObj, fetchCodeDetail, fetchCodeExec, fetchCodeReqmain, printSendSample } from '@/api/checkCode/index'
|
import { fetchCodeList, addObj, fetchCodeDetail, fetchCodeExec, fetchCodeReqmain, printSendSample } from '@/api/checkCode/index'
|
||||||
const aotuSize = classCom.useAutoSize();
|
const aotuSize = classCom.useAutoSize();
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
@ -580,7 +582,7 @@ const sendSampleHandle = () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
const userList = ref<{ userName: string, nickName: string }[]>([])
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
// 获取当前日期(当天)
|
// 获取当前日期(当天)
|
||||||
@ -612,6 +614,10 @@ onMounted(async () => {
|
|||||||
getList()
|
getList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
listUser({ status: 0, del_flag: 0, pageSize: 1000, pageNum: 1 }).then((res: any) => {
|
||||||
|
userList.value = res.rows;
|
||||||
|
});
|
||||||
|
|
||||||
// 加载病人来源字典
|
// 加载病人来源字典
|
||||||
const dictRefs = await comDict('PT', 'HOS', 'ST', 'DP');
|
const dictRefs = await comDict('PT', 'HOS', 'ST', 'DP');
|
||||||
|
|
||||||
@ -629,6 +635,10 @@ const formatDict = (v: string, dictType: string) => {
|
|||||||
return dictData.value[dictType]?.find((item: any) => item.value == v)?.label || v;
|
return dictData.value[dictType]?.find((item: any) => item.value == v)?.label || v;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const formatUser = (v: string) => {
|
||||||
|
return userList.value.find((item: any) => item.userName == v)?.nickName || v;
|
||||||
|
};
|
||||||
|
|
||||||
const handletime = (val: Array<string>) => {
|
const handletime = (val: Array<string>) => {
|
||||||
// console.log('时间', val);
|
// console.log('时间', val);
|
||||||
// 校验日期格式
|
// 校验日期格式
|
||||||
|
|||||||
@ -8,7 +8,6 @@
|
|||||||
<div class="table-toolbar mb5">
|
<div class="table-toolbar mb5">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-button type="primary" plain icon="Check" @click="handleSave">保存</el-button>
|
|
||||||
<el-button type="primary" plain @click="addHandle">新增</el-button>
|
<el-button type="primary" plain @click="addHandle">新增</el-button>
|
||||||
<el-button type="warning" plain @click="editHandle">修改</el-button>
|
<el-button type="warning" plain @click="editHandle">修改</el-button>
|
||||||
<el-button type="danger" plain @click="delBatch">删除</el-button>
|
<el-button type="danger" plain @click="delBatch">删除</el-button>
|
||||||
@ -16,6 +15,7 @@
|
|||||||
<el-col :span="16">
|
<el-col :span="16">
|
||||||
<span class="tips">靶值列表</span>
|
<span class="tips">靶值列表</span>
|
||||||
<el-button type="primary" plain @click="dateClick">复制第一个开始日期到每个项目</el-button>
|
<el-button type="primary" plain @click="dateClick">复制第一个开始日期到每个项目</el-button>
|
||||||
|
<el-button type="primary" plain icon="Check" @click="handleSave">保存</el-button>
|
||||||
<el-button type="primary" plain @click="">复制靶值</el-button>
|
<el-button type="primary" plain @click="">复制靶值</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="danger" plain @click="">删除靶值</el-button>
|
||||||
@ -28,6 +28,9 @@
|
|||||||
<CustomVxeTable ref="leftTableRef" class="mytable-style" :table-data="tableData" :columns="columns"
|
<CustomVxeTable ref="leftTableRef" class="mytable-style" :table-data="tableData" :columns="columns"
|
||||||
:row-config="{ isHover: true, keyField: 'batchno' }" @current-change="batchClick"
|
:row-config="{ isHover: true, keyField: 'batchno' }" @current-change="batchClick"
|
||||||
:scrollYConfig="{ enabled: true, rSize: 30, height: '100%', }">
|
:scrollYConfig="{ enabled: true, rSize: 30, height: '100%', }">
|
||||||
|
<template #conc="{ row }">
|
||||||
|
{{concList.find(item => item.value == row.conc)?.label || row.conc}}
|
||||||
|
</template>
|
||||||
<template #useflag="{ row }">
|
<template #useflag="{ row }">
|
||||||
<el-checkbox :model-value="row.useflag == 1" readonly></el-checkbox>
|
<el-checkbox :model-value="row.useflag == 1" readonly></el-checkbox>
|
||||||
</template>
|
</template>
|
||||||
@ -66,7 +69,8 @@
|
|||||||
<SelectTable v-model:data="row.ff" :tableData="dictData.MD" placeholder="" class="full-width-input" />
|
<SelectTable v-model:data="row.ff" :tableData="dictData.MD" placeholder="" class="full-width-input" />
|
||||||
</template>
|
</template>
|
||||||
<template #sjph="{ row }">
|
<template #sjph="{ row }">
|
||||||
<SelectTable v-model:data="row.sjph" :tableData="dictData.TK" placeholder="" class="full-width-input" />
|
<SelectTable v-model:data="row.sjph" :tableData="dictData.LOT" value="label" objKey="label" placeholder=""
|
||||||
|
class="full-width-input" />
|
||||||
</template>
|
</template>
|
||||||
<template #qccv="{ row }">
|
<template #qccv="{ row }">
|
||||||
<el-input v-model="row.qccv" class="full-width-input" />
|
<el-input v-model="row.qccv" class="full-width-input" />
|
||||||
@ -83,7 +87,7 @@
|
|||||||
{{ formatDict(row.ff, 'MD') }}
|
{{ formatDict(row.ff, 'MD') }}
|
||||||
</template>
|
</template>
|
||||||
<template #sjph="{ row }">
|
<template #sjph="{ row }">
|
||||||
{{ formatDict(row.sjph, 'TK') }}
|
{{ formatDict(row.sjph, 'LOT') }}
|
||||||
</template>
|
</template>
|
||||||
</CustomTable>
|
</CustomTable>
|
||||||
</div>
|
</div>
|
||||||
@ -106,12 +110,17 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="水平" prop="zkph">
|
<el-form-item label="水平" prop="zkph">
|
||||||
<el-select v-model="formData.zkph" placeholder="请选择">
|
<el-select v-model="formData.zkph" placeholder="请选择">
|
||||||
<el-option />
|
<el-option label="水平1" value="1" />
|
||||||
|
<el-option label="水平2" value="2" />
|
||||||
|
<el-option label="水平3" value="3" />
|
||||||
|
<el-option label="水平4" value="4" />
|
||||||
|
<el-option label="水平5" value="5" />
|
||||||
|
<el-option label="水平6" value="6" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="浓度" prop="conc">
|
<el-form-item label="浓度" prop="conc">
|
||||||
<el-select v-model="formData.conc" placeholder="请选择">
|
<el-select v-model="formData.conc" placeholder="请选择">
|
||||||
<el-option />
|
<el-option v-for="item in concList" :label="item.label" :value="item.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="批号(瓶子上的)" prop="batchno">
|
<el-form-item label="批号(瓶子上的)" prop="batchno">
|
||||||
@ -120,21 +129,19 @@
|
|||||||
<el-form-item label="有效期" prop="expiredt">
|
<el-form-item label="有效期" prop="expiredt">
|
||||||
<el-date-picker v-model="formData.expiredt" type="date" value-format="YYYY-MM-DD" />
|
<el-date-picker v-model="formData.expiredt" type="date" value-format="YYYY-MM-DD" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="启用日期" prop="ksrq">
|
<el-form-item label="启用日期" prop="startda">
|
||||||
<el-date-picker v-model="formData.ksrq" type="date" value-format="YYYY-MM-DD" />
|
<el-date-picker v-model="formData.startda" type="date" value-format="YYYY-MM-DD" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="结束日期" prop="endda">
|
<el-form-item label="结束日期" prop="endda">
|
||||||
<el-date-picker v-model="formData.endda" type="date" value-format="YYYY-MM-DD" />
|
<el-date-picker v-model="formData.endda" type="date" value-format="YYYY-MM-DD" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="质控厂商" prop="qcsrc">
|
<el-form-item label="质控厂商" prop="qcsrc">
|
||||||
<el-select v-model="formData.qcsrc" placeholder="请选择">
|
<SelectTable v-model:data="formData.qcsrc" :tableData="dictData.LOT" value="label" objKey="label"
|
||||||
<el-option />
|
placeholder="" :fields="fields" />
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="校准品厂商" prop="standsrc">
|
<el-form-item label="校准品厂商" prop="standsrc">
|
||||||
<el-select v-model="formData.standsrc" placeholder="请选择">
|
<SelectTable v-model:data="formData.standsrc" :tableData="dictData.LOT" value="label" objKey="label"
|
||||||
<el-option />
|
:fields="fields" placeholder="" />
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="备注" prop="bk">
|
<el-form-item label="备注" prop="bk">
|
||||||
<el-input v-model="formData.bk" type="textarea" :row="5" />
|
<el-input v-model="formData.bk" type="textarea" :row="5" />
|
||||||
@ -168,7 +175,7 @@ const formData = ref({
|
|||||||
useflag: '1',
|
useflag: '1',
|
||||||
batchno: '',
|
batchno: '',
|
||||||
expiredt: '',
|
expiredt: '',
|
||||||
ksrq: '',
|
startda: '',
|
||||||
endda: '',
|
endda: '',
|
||||||
qcsrc: '',
|
qcsrc: '',
|
||||||
standsrc: '',
|
standsrc: '',
|
||||||
@ -177,16 +184,29 @@ const formData = ref({
|
|||||||
const rules = ref({
|
const rules = ref({
|
||||||
zkpph: [{ required: true, message: '请输入质控批号', trigger: 'blur' }],
|
zkpph: [{ required: true, message: '请输入质控批号', trigger: 'blur' }],
|
||||||
zkph: [{ required: true, message: '请选择水平', trigger: 'change' }],
|
zkph: [{ required: true, message: '请选择水平', trigger: 'change' }],
|
||||||
ksrq: [{ required: true, message: '请选择启用日期', trigger: 'change' }],
|
startda: [{ required: true, message: '请选择启用日期', trigger: 'change' }],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const fields = ref(
|
||||||
|
[
|
||||||
|
{ prop: 'value', label: '代号', width: '40%', enablePinyinSearch: true },
|
||||||
|
{ prop: 'label', label: '名称', width: '60%', enablePinyinSearch: true },
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
const concList = ref([
|
||||||
|
{ label: '高', value: 'H' },
|
||||||
|
{ label: '低', value: 'L' },
|
||||||
|
{ label: '中', value: 'M' },
|
||||||
|
])
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const tableData = ref([])
|
const tableData = ref([])
|
||||||
const columns = ref([
|
const columns = ref([
|
||||||
{ title: '质控批号', field: 'zkpph', width: 80, resizable: true, align: 'center' },
|
{ title: '质控批号', field: 'zkpph', width: 80, resizable: true, align: 'center' },
|
||||||
{ title: '水平', field: 'zkph', resizable: true, align: 'center' },
|
{ title: '水平', field: 'zkph', resizable: true, align: 'center' },
|
||||||
{ title: '浓度', field: 'conc', resizable: true, align: 'center' },
|
{ title: '浓度', field: 'conc', resizable: true, align: 'center', slotName: 'conc' },
|
||||||
{ title: '在用', field: 'useflag', resizable: true, align: 'center', slotName: 'useflag' },
|
{ title: '在用', field: 'useflag', resizable: true, align: 'center', slotName: 'useflag' },
|
||||||
{ title: '启用日期', field: 'ksrq', width: 90, resizable: true, align: 'center' },
|
{ title: '启用日期', field: 'startda', width: 90, resizable: true, align: 'center' },
|
||||||
{ title: '停用日期', field: 'endda', 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: 'batchno', resizable: true, align: 'center', width: 100 },
|
||||||
{ title: '有效期', field: 'expiredt', width: 90, resizable: true, align: 'center' },
|
{ title: '有效期', field: 'expiredt', width: 90, resizable: true, align: 'center' },
|
||||||
@ -204,8 +224,8 @@ const topColumns = [
|
|||||||
{ title: '开始日期', field: 'ksrq', resizable: true, align: 'center', slotName: 'ksrq', width: 100 },
|
{ title: '开始日期', field: 'ksrq', resizable: true, align: 'center', slotName: 'ksrq', width: 100 },
|
||||||
{ title: '结束日期', field: 'stopdate', resizable: true, align: 'center', slotName: 'stopdate', width: 100 },
|
{ title: '结束日期', field: 'stopdate', resizable: true, align: 'center', slotName: 'stopdate', width: 100 },
|
||||||
{ title: '波长', field: 'bc', resizable: true, align: 'center', slotName: 'bc', },
|
{ title: '波长', field: 'bc', resizable: true, align: 'center', slotName: 'bc', },
|
||||||
{ title: '方法', field: 'ff', resizable: true, align: 'center', slotName: 'ff', },
|
{ title: '方法', field: 'ff', resizable: true, align: 'center', slotName: 'ff', width: 100 },
|
||||||
{ title: '试剂', field: 'sjph', resizable: true, align: 'center', slotName: 'sjph', },
|
{ title: '试剂', field: 'sjph', resizable: true, align: 'center', slotName: 'sjph', width: 100 },
|
||||||
{ title: '目标CV(%)', field: 'qccv', resizable: true, align: 'center', slotName: 'qccv', width: 80 },
|
{ title: '目标CV(%)', field: 'qccv', resizable: true, align: 'center', slotName: 'qccv', width: 80 },
|
||||||
]
|
]
|
||||||
const bottomTableData = ref([])
|
const bottomTableData = ref([])
|
||||||
@ -280,12 +300,21 @@ const delBatch = () => {
|
|||||||
const submit = () => {
|
const submit = () => {
|
||||||
queryRef.value.validate((valid: boolean) => {
|
queryRef.value.validate((valid: boolean) => {
|
||||||
if (!valid) return false;
|
if (!valid) return false;
|
||||||
return
|
|
||||||
if (title.value == '修改批号') {
|
if (title.value == '修改批号') {
|
||||||
updateBatchno(formData.value).then((res: any) => {
|
updateBatchno(formData.value).then((res: any) => {
|
||||||
|
if (res.code == 0) {
|
||||||
|
ElMessage.success('修改成功')
|
||||||
|
handleDialogClose()
|
||||||
|
getBatchList()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
addBatchno(formData.value).then((res: any) => {
|
addBatchno(formData.value).then((res: any) => {
|
||||||
|
if (res.code == 0) {
|
||||||
|
ElMessage.success('新增成功')
|
||||||
|
handleDialogClose()
|
||||||
|
getBatchList()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,12 +331,13 @@ const handleDialogClose = () => {
|
|||||||
useflag: '1',
|
useflag: '1',
|
||||||
batchno: '',
|
batchno: '',
|
||||||
expiredt: '',
|
expiredt: '',
|
||||||
ksrq: '',
|
startda: '',
|
||||||
endda: '',
|
endda: '',
|
||||||
qcsrc: '',
|
qcsrc: '',
|
||||||
standsrc: '',
|
standsrc: '',
|
||||||
bk: ''
|
bk: ''
|
||||||
}
|
}
|
||||||
|
visible.value = false
|
||||||
}
|
}
|
||||||
const batchInfo: any = ref(null)
|
const batchInfo: any = ref(null)
|
||||||
const batchClick = (row: any) => {
|
const batchClick = (row: any) => {
|
||||||
@ -317,7 +347,7 @@ const batchClick = (row: any) => {
|
|||||||
const getBatchList = () => {
|
const getBatchList = () => {
|
||||||
batchInfo.value = null
|
batchInfo.value = null
|
||||||
loading.value = true
|
loading.value = true
|
||||||
queryBatch({ yq: yq.value, pageNum: 1, pageSize: 9999 }).then((res: any) => {
|
queryBatch({ yq: yq.value }).then((res: any) => {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
tableData.value = res.data || []
|
tableData.value = res.data || []
|
||||||
getXmList(tableData.value[0])
|
getXmList(tableData.value[0])
|
||||||
@ -360,7 +390,9 @@ watch(yq, (val) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.el-input__prefix) {
|
.mytable-style {
|
||||||
display: none;
|
:deep(.el-input__prefix) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@ -250,7 +250,7 @@ const getDeptTree = async (): Promise<void> => {
|
|||||||
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getDictData('MD', 'TK')
|
getDictData('MD', 'LOT')
|
||||||
})
|
})
|
||||||
// ========== 初始化 ==========
|
// ========== 初始化 ==========
|
||||||
getDeptTree()
|
getDeptTree()
|
||||||
|
|||||||
@ -0,0 +1,172 @@
|
|||||||
|
/**
|
||||||
|
* @file dateTime.vue 日期录入
|
||||||
|
* @author: w
|
||||||
|
* @since: 2026-01-13
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<div class="handle-box mb5">
|
||||||
|
<el-form>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="4">
|
||||||
|
<el-form-item label="日期:">
|
||||||
|
<el-date-picker v-model="queryParams.zkrq" type="date" value-format="YYYY-MM-DD" style="width:100%" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="4">
|
||||||
|
<el-form-item label="项目:">
|
||||||
|
<el-select v-model="queryParams.xmdh" placeholder="请选择" style="width:100%">
|
||||||
|
<el-option />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="primary" plain icon="Check" @click="handleSave">保存</el-button>
|
||||||
|
</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>
|
||||||
|
|
||||||
|
<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" />
|
||||||
|
</el-tabs>
|
||||||
|
|
||||||
|
<div class="table-box">
|
||||||
|
<CustomVxeTable class="mytable-style" ref="tableRef" :table-data="tableData" :columns="columns"
|
||||||
|
:scrollYConfig="{ enabled: true, rSize: 30, height: '100%', }" :cell-style="cellStyleHd">
|
||||||
|
<template #xmdh="{ row }">
|
||||||
|
{{ row.xmdh }} {{ row.xmmc }}
|
||||||
|
</template>
|
||||||
|
<template #cs1="{ row }">
|
||||||
|
<el-input v-model="row.cs1" class="full-width-input" />
|
||||||
|
</template>
|
||||||
|
<template #cs2="{ row }">
|
||||||
|
<el-input v-model="row.cs2" class="full-width-input" />
|
||||||
|
</template>
|
||||||
|
<template #cs3="{ row }">
|
||||||
|
<el-input v-model="row.cs3" class="full-width-input" />
|
||||||
|
</template>
|
||||||
|
<template #cs4="{ row }">
|
||||||
|
<el-input v-model="row.cs4" class="full-width-input" />
|
||||||
|
</template>
|
||||||
|
<template #cs5="{ row }">
|
||||||
|
<el-input v-model="row.cs5" class="full-width-input" />
|
||||||
|
</template>
|
||||||
|
<template #cs6="{ row }">
|
||||||
|
<el-input v-model="row.cs6" class="full-width-input" />
|
||||||
|
</template>
|
||||||
|
<template #cs7="{ row }">
|
||||||
|
<el-input v-model="row.cs7" class="full-width-input" />
|
||||||
|
</template>
|
||||||
|
</CustomVxeTable>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { getqcval } from '@/api/liswork/qualityControl/index'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
|
||||||
|
|
||||||
|
const yq = defineModel<string>()
|
||||||
|
const activeName = ref('1')
|
||||||
|
const queryParams = ref({
|
||||||
|
xmdh: '',
|
||||||
|
zkrq: ref(dayjs().format('YYYY-MM-DD')),
|
||||||
|
})
|
||||||
|
|
||||||
|
const tabList = [
|
||||||
|
{ key: '1', label: '质控1' },
|
||||||
|
{ key: '2', label: '质控2' }
|
||||||
|
]
|
||||||
|
|
||||||
|
const tableData = ref([])
|
||||||
|
const columns = ref([
|
||||||
|
{ field: 'xmdh', title: '日期', resizable: true, width: 200 },
|
||||||
|
{ field: 'cs1', title: '次数1', resizable: true, slotName: 'cs1' },
|
||||||
|
{ field: 'cs2', title: '次数2', resizable: true, slotName: 'cs2' },
|
||||||
|
{ field: 'cs3', title: '次数3', resizable: true, slotName: 'cs3' },
|
||||||
|
{ field: 'cs4', title: '次数4', resizable: true, slotName: 'cs4' },
|
||||||
|
{ field: 'cs5', title: '次数5', resizable: true, slotName: 'cs5' },
|
||||||
|
{ field: 'cs6', title: '次数6', resizable: true, slotName: 'cs6' },
|
||||||
|
{ field: 'cs7', title: '次数7', resizable: true, slotName: 'cs7' },
|
||||||
|
{ field: 'zkbz', title: '靶数', resizable: true, align: 'center' },
|
||||||
|
{ field: 'qcusepos', title: 'SD', resizable: true, align: 'center' },
|
||||||
|
])
|
||||||
|
const cellStyleHd = ({ row, column }: {
|
||||||
|
row: any;
|
||||||
|
column: any;
|
||||||
|
}) => {
|
||||||
|
const styleRules: any = {
|
||||||
|
columnMap: { cs1: 'cs1', cs2: 'cs2', cs3: 'cs3', cs4: 'cs4', cs5: 'cs5', cs6: 'cs6', cs7: 'cs7' },
|
||||||
|
colorRules: [
|
||||||
|
{ min: 3, color: '#f00 !important' }, // 大于3:红色
|
||||||
|
{ min: 2, max: 3, color: '#ffc0c0 !important' } // 2~3:粉色
|
||||||
|
]
|
||||||
|
}
|
||||||
|
const targetField = styleRules.columnMap[column.title];
|
||||||
|
|
||||||
|
if (!targetField || row.qcusepos === 0) return {};
|
||||||
|
|
||||||
|
const deviation = Math.abs(row.zkbz - row[targetField]) / row.qcusepos;
|
||||||
|
|
||||||
|
for (const rule of styleRules.colorRules) {
|
||||||
|
if (deviation > rule.min && (!rule.max || deviation < rule.max)) {
|
||||||
|
return { background: rule.color };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const getXmList = () => {
|
||||||
|
getqcval({ yq: yq.value, ...queryParams.value }).then((res: any) => {
|
||||||
|
tableData.value = res.data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSave = () => { }
|
||||||
|
|
||||||
|
watch(yq, (val) => {
|
||||||
|
if (val) {
|
||||||
|
// getXmList()
|
||||||
|
}
|
||||||
|
}, { immediate: true })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.table-box {
|
||||||
|
margin-top: 5px;
|
||||||
|
height: calc(100% - 145px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tips {
|
||||||
|
font-family: SourceHanSansCN, SourceHanSansCN;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #409eff;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-red {
|
||||||
|
background-color: #f00;
|
||||||
|
color: #fff;
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-pink {
|
||||||
|
background-color: #ffc0c0;
|
||||||
|
color: #fff;
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-form-item) {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,161 @@
|
|||||||
|
/**
|
||||||
|
* @file index.vue 质控结果手工录入
|
||||||
|
* @author: w
|
||||||
|
* @since: 2026-01-05
|
||||||
|
*/
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<div class="handle-box mb5">
|
||||||
|
<el-form>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="4">
|
||||||
|
<el-form-item label="日期:">
|
||||||
|
<el-date-picker v-model="zkrq" type="date" value-format="YYYY-MM-DD" style="width:100%" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="primary" plain icon="Check" @click="handleSave">保存</el-button>
|
||||||
|
</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>
|
||||||
|
|
||||||
|
<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" />
|
||||||
|
</el-tabs>
|
||||||
|
|
||||||
|
<div class="table-box">
|
||||||
|
<CustomVxeTable class="mytable-style" ref="tableRef" :table-data="tableData" :columns="columns"
|
||||||
|
:scrollYConfig="{ enabled: true, rSize: 30, height: '100%', }" :cell-style="cellStyleHd">
|
||||||
|
<template #xmdh="{ row }">
|
||||||
|
{{ row.xmdh }} {{ row.xmmc }}
|
||||||
|
</template>
|
||||||
|
<template #cs1="{ row }">
|
||||||
|
<el-input v-model="row.cs1" class="full-width-input" />
|
||||||
|
</template>
|
||||||
|
<template #cs2="{ row }">
|
||||||
|
<el-input v-model="row.cs2" class="full-width-input" />
|
||||||
|
</template>
|
||||||
|
<template #cs3="{ row }">
|
||||||
|
<el-input v-model="row.cs3" class="full-width-input" />
|
||||||
|
</template>
|
||||||
|
<template #cs4="{ row }">
|
||||||
|
<el-input v-model="row.cs4" class="full-width-input" />
|
||||||
|
</template>
|
||||||
|
<template #cs5="{ row }">
|
||||||
|
<el-input v-model="row.cs5" class="full-width-input" />
|
||||||
|
</template>
|
||||||
|
<template #cs6="{ row }">
|
||||||
|
<el-input v-model="row.cs6" class="full-width-input" />
|
||||||
|
</template>
|
||||||
|
<template #cs7="{ row }">
|
||||||
|
<el-input v-model="row.cs7" class="full-width-input" />
|
||||||
|
</template>
|
||||||
|
</CustomVxeTable>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { getqcval } from '@/api/liswork/qualityControl/index'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
|
||||||
|
|
||||||
|
const yq = defineModel<string>()
|
||||||
|
const activeName = ref('1')
|
||||||
|
const zkrq = ref(dayjs().format('YYYY-MM-DD'))
|
||||||
|
const tabList = [
|
||||||
|
{ key: '1', label: '质控1' },
|
||||||
|
{ key: '2', label: '质控2' }
|
||||||
|
]
|
||||||
|
|
||||||
|
const tableData = ref([])
|
||||||
|
const columns = ref([
|
||||||
|
{ field: 'xmdh', title: '质控项目', resizable: true, slotName: 'xmdh', width: 200 },
|
||||||
|
{ field: 'cs1', title: '次数1', resizable: true, slotName: 'cs1' },
|
||||||
|
{ field: 'cs2', title: '次数2', resizable: true, slotName: 'cs2' },
|
||||||
|
{ field: 'cs3', title: '次数3', resizable: true, slotName: 'cs3' },
|
||||||
|
{ field: 'cs4', title: '次数4', resizable: true, slotName: 'cs4' },
|
||||||
|
{ field: 'cs5', title: '次数5', resizable: true, slotName: 'cs5' },
|
||||||
|
{ field: 'cs6', title: '次数6', resizable: true, slotName: 'cs6' },
|
||||||
|
{ field: 'cs7', title: '次数7', resizable: true, slotName: 'cs7' },
|
||||||
|
{ field: 'zkbz', title: '靶数', resizable: true, align: 'center' },
|
||||||
|
{ field: 'qcusepos', title: 'SD', resizable: true, align: 'center' },
|
||||||
|
])
|
||||||
|
const cellStyleHd = ({ row, column }: {
|
||||||
|
row: any;
|
||||||
|
column: any;
|
||||||
|
}) => {
|
||||||
|
const styleRules: any = {
|
||||||
|
columnMap: { cs1: 'cs1', cs2: 'cs2', cs3: 'cs3', cs4: 'cs4', cs5: 'cs5', cs6: 'cs6', cs7: 'cs7' },
|
||||||
|
colorRules: [
|
||||||
|
{ min: 3, color: '#f00 !important' }, // 大于3:红色
|
||||||
|
{ min: 2, max: 3, color: '#ffc0c0 !important' } // 2~3:粉色
|
||||||
|
]
|
||||||
|
}
|
||||||
|
const targetField = styleRules.columnMap[column.title];
|
||||||
|
|
||||||
|
if (!targetField || row.qcusepos === 0) return {};
|
||||||
|
|
||||||
|
const deviation = Math.abs(row.zkbz - row[targetField]) / row.qcusepos;
|
||||||
|
|
||||||
|
for (const rule of styleRules.colorRules) {
|
||||||
|
if (deviation > rule.min && (!rule.max || deviation < rule.max)) {
|
||||||
|
return { background: rule.color };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const getXmList = () => {
|
||||||
|
getqcval({ yq: yq.value, zkrq: zkrq.value }).then((res: any) => {
|
||||||
|
tableData.value = res.data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSave = () => { }
|
||||||
|
|
||||||
|
|
||||||
|
watch(yq, (val) => {
|
||||||
|
if (val) {
|
||||||
|
getXmList()
|
||||||
|
}
|
||||||
|
}, { immediate: true })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.table-box {
|
||||||
|
margin-top: 5px;
|
||||||
|
height: calc(100% - 145px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tips {
|
||||||
|
font-family: SourceHanSansCN, SourceHanSansCN;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #409eff;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-red {
|
||||||
|
background-color: #f00;
|
||||||
|
color: #fff;
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-pink {
|
||||||
|
background-color: #ffc0c0;
|
||||||
|
color: #fff;
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-form-item) {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1,163 +1,357 @@
|
|||||||
/**
|
/**
|
||||||
* @file index.vue 质控结果手工录入
|
* @file index.vue 质控
|
||||||
* @author: w
|
* @author: w
|
||||||
* @since: 2026-01-05
|
* @since: 2025-12-29
|
||||||
*/
|
*/
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<div class="handle-box mb5">
|
<el-row :gutter="20" class="main-row">
|
||||||
<el-form>
|
<!-- 左侧树区域 -->
|
||||||
<el-row :gutter="20">
|
<el-col :span="4" :xs="24" class="tree-col">
|
||||||
<el-col :span="4">
|
<el-input v-model="deptName" placeholder="请输入仪器名称" clearable prefix-icon="Search" class="tree-search-input" />
|
||||||
<el-form-item label="仪器:">
|
<el-radio-group v-model="radiotype" @change="radioChange">
|
||||||
<YQSelectTable v-model:data="yq" width="200px" clearable @get-data-value="getXmList" />
|
<el-radio value="1" size="large">仪器组</el-radio>
|
||||||
</el-form-item>
|
<el-radio value="2" size="large">所有仪器</el-radio>
|
||||||
</el-col>
|
</el-radio-group>
|
||||||
<el-col :span="4">
|
<div class="tree-container">
|
||||||
<el-form-item label="日期:">
|
<el-tree :data="deptOptions" :props="treeProps" expand-on-click-node :filter-node-method="filterNode"
|
||||||
<el-date-picker v-model="jyrq" type="date" value-format="YYYY-MM-DD" style="width:100%" />
|
ref="deptTreeRef" node-key="id" highlight-current :expanded-keys="expandedKeys"
|
||||||
</el-form-item>
|
@node-click="handleNodeClick">
|
||||||
</el-col>
|
<!-- 自定义树节点模板:新增newflag徽章 -->
|
||||||
<el-col :span="5">
|
<template #default="{ node, data }">
|
||||||
<span class="tips ml10">颜色说明:</span> <span class="color-red">大于3SD</span> <span
|
<span class="tree-node-content">
|
||||||
class="color-pink">大于2SD</span>
|
{{ node.label }}
|
||||||
</el-col>
|
<!-- 新节点徽章:newflag=1时显示黄色"新"标 -->
|
||||||
|
<el-badge v-if="data.newflag === '1'" value="new" class="new-node-badge" />
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-tree>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<!-- 右侧列表区域 -->
|
||||||
|
<el-col :span="20" :xs="24" class="table-col">
|
||||||
|
<el-row :gutter="10" class="yq-title-row">
|
||||||
|
<h1 class="yq-title">仪器: {{ yqmc }}</h1>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
<el-tabs v-model="activeName" type="card" class="tabs_box">
|
||||||
</el-form>
|
<el-tab-pane v-for="tab in tabList" :key="tab.key" :label="tab.label" :name="tab.key" />
|
||||||
</div>
|
</el-tabs>
|
||||||
<div class="mb5">
|
<!-- 动态组件渲染 -->
|
||||||
<el-button type="primary" plain icon="Check" @click="handleSave">保存</el-button>
|
<component :is="currentComponent" :key="activeName" v-model="queryParams.yq" @updateTree="getDeptTree" />
|
||||||
</div>
|
</el-col>
|
||||||
<el-tabs v-model="activeName" type="card" class="tabs_box">
|
</el-row>
|
||||||
<el-tab-pane v-for="tab in tabList" :key="tab.key" :label="tab.label" :name="tab.key" />
|
|
||||||
</el-tabs>
|
|
||||||
|
|
||||||
<div class="table-box">
|
|
||||||
<CustomVxeTable class="mytable-style" ref="tableRef" :table-data="tableData" :columns="columns"
|
|
||||||
:scrollYConfig="{ enabled: true, rSize: 30, height: '100%', }" :cell-style="cellStyleHd">
|
|
||||||
<template #xmdh="{ row }">
|
|
||||||
{{ row.xmdh }} {{ row.xmmc }}
|
|
||||||
</template>
|
|
||||||
<template #cs1="{ row }">
|
|
||||||
<el-input v-model="row.cs1" class="full-width-input" />
|
|
||||||
</template>
|
|
||||||
<template #cs2="{ row }">
|
|
||||||
<el-input v-model="row.cs2" class="full-width-input" />
|
|
||||||
</template>
|
|
||||||
<template #cs3="{ row }">
|
|
||||||
<el-input v-model="row.cs3" class="full-width-input" />
|
|
||||||
</template>
|
|
||||||
<template #cs4="{ row }">
|
|
||||||
<el-input v-model="row.cs4" class="full-width-input" />
|
|
||||||
</template>
|
|
||||||
<template #cs5="{ row }">
|
|
||||||
<el-input v-model="row.cs5" class="full-width-input" />
|
|
||||||
</template>
|
|
||||||
<template #cs6="{ row }">
|
|
||||||
<el-input v-model="row.cs6" class="full-width-input" />
|
|
||||||
</template>
|
|
||||||
<template #cs7="{ row }">
|
|
||||||
<el-input v-model="row.cs7" class="full-width-input" />
|
|
||||||
</template>
|
|
||||||
</CustomVxeTable>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { queryOldxminfo } from '@/api/liswork/xtwh/xmReqItemVsApi'
|
import { ref, watch, nextTick, computed } from 'vue'
|
||||||
import YQSelectTable from '@/components/SelectTable/YQSelectTable/index.vue';
|
import { ElMessage, ElTree, TreeNode, ElMessageBox, ElBadge } from 'element-plus'
|
||||||
import dayjs from 'dayjs'
|
import { paramList, paramTree, getdef, updateParam } from '@/api/liswork/xtwh/ComOpt'
|
||||||
|
import { getFirstLetter } from '@/utils/pinyin'
|
||||||
|
import { formatDict, getDictData, dictData } from '@/hooks';
|
||||||
import { useCommonStore } from '@/store/modules/commonStore';
|
import { useCommonStore } from '@/store/modules/commonStore';
|
||||||
|
import Project from './components/project.vue';
|
||||||
|
import DateTime from './components/dateTime.vue';
|
||||||
|
|
||||||
|
|
||||||
const mbStore = useCommonStore();
|
const mbStore = useCommonStore();
|
||||||
|
// ========== TypeScript 类型定义 ==========
|
||||||
|
interface InstrTreeNode {
|
||||||
|
id: string
|
||||||
|
label: string
|
||||||
|
lx: string
|
||||||
|
newflag: string // 新增newflag字段
|
||||||
|
children?: InstrTreeNode[]
|
||||||
|
}
|
||||||
|
|
||||||
const yq = ref(mbStore.defaultConfig.defaultinstr || '46')
|
interface ParamTreeResponse {
|
||||||
const activeName = ref('1')
|
code: string
|
||||||
const jyrq = ref(dayjs().format('YYYY-MM-DD'))
|
msg: string
|
||||||
const tabList = [
|
data: InstrTreeNode[]
|
||||||
{ key: '1', label: '质控1' },
|
url: null | string
|
||||||
{ key: '2', label: '质控2' }
|
method: null | string
|
||||||
]
|
params: null | any
|
||||||
|
problemId: null | string
|
||||||
|
}
|
||||||
|
|
||||||
const tableData = ref([])
|
interface QueryParams {
|
||||||
const columns = ref([
|
yq?: string | undefined
|
||||||
{ field: 'xmdh', title: '质控项目', resizable: true, slotName: 'xmdh', width: 200 },
|
xxdh?: string | undefined
|
||||||
{ field: 'cs1', title: '次数1', resizable: true, slotName: 'cs1' },
|
xxqz?: string | undefined
|
||||||
{ field: 'cs2', title: '次数2', resizable: true, slotName: 'cs2' },
|
groupId?: string | undefined
|
||||||
{ field: 'cs3', title: '次数3', resizable: true, slotName: 'cs3' },
|
|
||||||
{ field: 'cs4', title: '次数4', resizable: true, slotName: 'cs4' },
|
|
||||||
{ field: 'cs5', title: '次数5', resizable: true, slotName: 'cs5' },
|
|
||||||
{ field: 'cs6', title: '次数6', resizable: true, slotName: 'cs6' },
|
|
||||||
{ field: 'cs7', title: '次数7', resizable: true, slotName: 'cs7' },
|
|
||||||
{ field: 'zkbz', title: '靶数', resizable: true, align: 'center' },
|
|
||||||
{ field: 'qcusepos', title: 'SD', resizable: true, align: 'center' },
|
|
||||||
])
|
|
||||||
const cellStyleHd = ({ row, column }: {
|
|
||||||
row: any;
|
|
||||||
column: any;
|
|
||||||
}) => {
|
|
||||||
const styleRules: any = {
|
|
||||||
columnMap: { cs1: 'cs1', cs2: 'cs2', cs3: 'cs3', cs4: 'cs4', cs5: 'cs5', cs6: 'cs6', cs7: 'cs7' },
|
|
||||||
colorRules: [
|
|
||||||
{ min: 3, color: '#f00 !important' }, // 大于3:红色
|
|
||||||
{ min: 2, max: 3, color: '#ffc0c0 !important' } // 2~3:粉色
|
|
||||||
]
|
|
||||||
}
|
|
||||||
const targetField = styleRules.columnMap[column.title];
|
|
||||||
|
|
||||||
if (!targetField || row.qcusepos === 0) return {};
|
|
||||||
|
|
||||||
const deviation = Math.abs(row.zkbz - row[targetField]) / row.qcusepos;
|
|
||||||
|
|
||||||
for (const rule of styleRules.colorRules) {
|
|
||||||
if (deviation > rule.min && (!rule.max || deviation < rule.max)) {
|
|
||||||
return { background: rule.color };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const getXmList = () => {
|
const radiotype = ref<string>("1")
|
||||||
queryOldxminfo({ yq: yq.value, }).then((res: any) => {
|
// ========== 响应式变量 ==========
|
||||||
tableData.value = res.data
|
// 树相关
|
||||||
|
const deptTreeRef = ref<InstanceType<typeof ElTree>>()
|
||||||
|
const deptOptions = ref<InstrTreeNode[]>([])
|
||||||
|
const deptName = ref<string>("")
|
||||||
|
const yqmc = ref<string>("")
|
||||||
|
const expandedKeys = ref<string[]>([])
|
||||||
|
const isFiltering = ref<boolean>(false)
|
||||||
|
const treeProps = ref({
|
||||||
|
label: 'label',
|
||||||
|
children: 'children',
|
||||||
|
isLeaf: (data: Record<string, any>) => !data.children || data.children.length === 0
|
||||||
|
})
|
||||||
|
|
||||||
|
// 查询参数
|
||||||
|
const queryParams = ref<QueryParams>({
|
||||||
|
yq: undefined,
|
||||||
|
xxdh: undefined,
|
||||||
|
xxqz: undefined,
|
||||||
|
groupId: undefined
|
||||||
|
})
|
||||||
|
|
||||||
|
const tabList = [
|
||||||
|
{ key: 'Project', label: '按项目', component: Project },
|
||||||
|
{ key: 'DateTime', label: '按日期', component: DateTime },
|
||||||
|
|
||||||
|
]
|
||||||
|
const activeName = ref('Project')
|
||||||
|
|
||||||
|
// 计算当前要渲染的组件
|
||||||
|
const currentComponent = computed(() => {
|
||||||
|
return tabList.find(tab => tab.key === activeName.value)?.component || 'Project'
|
||||||
|
})
|
||||||
|
|
||||||
|
const result: any = ref([])
|
||||||
|
|
||||||
|
const treeData = ref<InstrTreeNode[]>([])
|
||||||
|
const radioChange = (val: string) => {
|
||||||
|
if (val == "1") {
|
||||||
|
deptOptions.value = treeData.value
|
||||||
|
} else {
|
||||||
|
deptOptions.value = result.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 树操作核心方法 ==========
|
||||||
|
const forceExpandSingleNode = (nodeId: string): void => {
|
||||||
|
expandedKeys.value = []
|
||||||
|
nextTick(() => {
|
||||||
|
expandedKeys.value = [nodeId]
|
||||||
|
// deptTreeRef.value?.expand(nodeId, false)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSave = () => { }
|
const handleNodeClick = (data: InstrTreeNode): void => {
|
||||||
|
if (isFiltering.value) {
|
||||||
|
queryParams.value.groupId = data.id === "-1" ? undefined : data.id
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
getXmList()
|
if (data.children && data.children.length > 0) {
|
||||||
|
const isExpanded = expandedKeys.value.includes(data.id)
|
||||||
|
expandedKeys.value = isExpanded ? [] : [data.id]
|
||||||
|
!isExpanded && forceExpandSingleNode(data.id)
|
||||||
|
} else {
|
||||||
|
queryParams.value.yq = data.id
|
||||||
|
yqmc.value = data.label
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ========== 检索过滤逻辑 ==========
|
||||||
|
const filterNode = (value: string, data: any, _node: TreeNode): boolean => {
|
||||||
|
if (!value) return true
|
||||||
|
|
||||||
|
const keyword = value.trim().toUpperCase()
|
||||||
|
const nodeLabel = data.label?.toLowerCase() || ''
|
||||||
|
const nodePinyinFirst = data.label ? getFirstLetter(data.label).toUpperCase() : ''
|
||||||
|
|
||||||
|
const currentMatch = nodeLabel.includes(keyword.toLowerCase()) || nodePinyinFirst.includes(keyword)
|
||||||
|
const childrenMatch = (data.children || []).some((child: any) => filterNode(value, child, _node))
|
||||||
|
return currentMatch || childrenMatch
|
||||||
|
}
|
||||||
|
|
||||||
|
const debounceFilter = (() => {
|
||||||
|
let timer: number | undefined
|
||||||
|
return (val: string): void => {
|
||||||
|
clearTimeout(timer)
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
isFiltering.value = true
|
||||||
|
deptTreeRef.value?.filter(val)
|
||||||
|
|
||||||
|
if (val) {
|
||||||
|
expandedKeys.value = []
|
||||||
|
const expandMatched = (nodes: InstrTreeNode[]) => {
|
||||||
|
nodes.forEach(node => {
|
||||||
|
if (filterNode(val, node, {} as TreeNode) && node.children?.length) {
|
||||||
|
expandedKeys.value.push(node.id)
|
||||||
|
}
|
||||||
|
node.children && expandMatched(node.children)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
expandMatched(deptOptions.value)
|
||||||
|
} else {
|
||||||
|
expandedKeys.value = []
|
||||||
|
}
|
||||||
|
isFiltering.value = false
|
||||||
|
}, 300)
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
|
||||||
|
watch(deptName, debounceFilter, { immediate: false })
|
||||||
|
|
||||||
|
// ========== 业务逻辑 ==========
|
||||||
|
const getDeptTree = async (): Promise<void> => {
|
||||||
|
try {
|
||||||
|
const response = await paramTree() as ParamTreeResponse
|
||||||
|
result.value = []
|
||||||
|
if (response.code === "0" && response.data) {
|
||||||
|
for (let i = 0; i < response.data.length; i++) {
|
||||||
|
const group = response.data[i];
|
||||||
|
if (group.children && Array.isArray(group.children)) {
|
||||||
|
for (let j = 0; j < group.children.length; j++) {
|
||||||
|
result.value.push(group.children[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
treeData.value = response.data
|
||||||
|
radioChange('1')
|
||||||
|
if (!expandedKeys.value.length) {
|
||||||
|
// 默认展开第一个一级节点的子级
|
||||||
|
nextTick(() => {
|
||||||
|
if (mbStore.defaultConfig.defaultinstr) {
|
||||||
|
queryParams.value.yq = mbStore.defaultConfig.defaultinstr
|
||||||
|
yqmc.value = result.value.find((item: any) => item.id === queryParams.value.yq)?.label
|
||||||
|
deptTreeRef.value?.setCurrentKey(queryParams.value.yq)
|
||||||
|
} else {
|
||||||
|
if (deptOptions.value.length > 0) {
|
||||||
|
const firstLevelNode = deptOptions.value[0]
|
||||||
|
if (firstLevelNode && firstLevelNode.children && firstLevelNode.children.length > 0) {
|
||||||
|
expandedKeys.value = [firstLevelNode.id]
|
||||||
|
const firstChildNode = firstLevelNode.children[0]
|
||||||
|
queryParams.value.yq = firstChildNode.id
|
||||||
|
yqmc.value = firstChildNode.label
|
||||||
|
deptTreeRef.value?.setCurrentKey(queryParams.value.yq)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ElMessage.warning(response.msg || "获取树数据失败")
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
ElMessage.error(`获取树数据异常:${(error as Error).message}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
})
|
||||||
|
// ========== 初始化 ==========
|
||||||
|
getDeptTree()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.table-box {
|
.app-container {
|
||||||
margin-top: 5px;
|
width: 100%;
|
||||||
height: calc(100% - 125px);
|
height: 90vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 8px;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tips {
|
.main-row {
|
||||||
font-family: SourceHanSansCN, SourceHanSansCN;
|
display: flex;
|
||||||
font-size: 16px;
|
flex: 1;
|
||||||
color: #409eff;
|
height: 100%;
|
||||||
font-weight: 600;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.color-red {
|
.tree-col {
|
||||||
background-color: #f00;
|
height: 100%;
|
||||||
color: #fff;
|
display: flex;
|
||||||
padding: 2px;
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
|
||||||
|
.tree-container {
|
||||||
|
flex: 1;
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #e6e6e6;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 8px;
|
||||||
|
|
||||||
|
// 核心:树选中节点样式
|
||||||
|
:deep(.el-tree) {
|
||||||
|
--el-tree-node-transition-duration: 0.2s;
|
||||||
|
|
||||||
|
.el-tree-node__children {
|
||||||
|
transition: all var(--el-tree-node-transition-duration) ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tree-node__expand-icon.is-leaf {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选中节点的背景色(蓝色)+ 文字白色
|
||||||
|
.el-tree-node.is-current>.el-tree-node__content {
|
||||||
|
background-color: #409eff !important;
|
||||||
|
color: #ffffff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选中节点hover样式(加深蓝色)
|
||||||
|
.el-tree-node.is-current>.el-tree-node__content:hover {
|
||||||
|
background-color: #1e88e5 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 树节点内容容器样式
|
||||||
|
.tree-node-content {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px; // 徽章和文字间距
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新节点徽章样式
|
||||||
|
.new-node-badge {
|
||||||
|
--el-badge-font-size: 10px !important;
|
||||||
|
--el-badge-height: 16px !important;
|
||||||
|
--el-badge-padding: 0 4px !important;
|
||||||
|
--el-badge-warning-color: #FFEC24 !important; // 黄色徽章
|
||||||
|
--el-badge-warning-bg-color: #fff7e6 !important; // 浅黄色背景
|
||||||
|
--el-badge-border-radius: 2px !important; // 圆角优化
|
||||||
|
|
||||||
|
// 徽章文字样式
|
||||||
|
.el-badge__content {
|
||||||
|
font-size: 10px !important;
|
||||||
|
line-height: 16px !important;
|
||||||
|
padding: 0 4px !important;
|
||||||
|
height: 16px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.color-pink {
|
.table-col {
|
||||||
background-color: #ffc0c0;
|
height: 100%;
|
||||||
color: #fff;
|
|
||||||
padding: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.el-form-item) {
|
// 仪器标题行样式
|
||||||
margin-bottom: 5px;
|
.yq-title-row {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
|
||||||
|
.yq-title {
|
||||||
|
font-family: SourceHanSansCN, SourceHanSansCN;
|
||||||
|
font-size: 16px; // 缩小h1字体(默认24px→16px)
|
||||||
|
color: #409eff; // 蓝色(Element Plus主题色)
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0; // 清除默认margin
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
Loading…
x
Reference in New Issue
Block a user