Merge branch 'main' of http://47.97.125.165:8902/jiangs/lis8.0-vue3
This commit is contained in:
commit
c728193842
@ -211,3 +211,19 @@ export function savemonthskzj(data?: Object) {
|
||||
data
|
||||
})
|
||||
}
|
||||
//查询质控数据
|
||||
export function qcgraphList(data?: Object) {
|
||||
return request({
|
||||
url: '/qcgraph/query',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
//查询质控参数列表
|
||||
export function querySample(data?: Object) {
|
||||
return request({
|
||||
url: '/qcgraph/querysample',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
|
||||
@ -279,7 +279,6 @@ const getEcharts = () => {
|
||||
yAxis: [{
|
||||
name: 'SD',
|
||||
type: 'value',
|
||||
inverse: false,
|
||||
splitLine: { show: true, lineStyle: { type: 'dashed' } },
|
||||
axisLabel: { formatter: '{value}', color: '#474747', fontSize: 14 },
|
||||
axisTick: { show: false },
|
||||
|
||||
638
src/views/liswork/qualityControl/westGard/index.vue
Normal file
638
src/views/liswork/qualityControl/westGard/index.vue
Normal file
@ -0,0 +1,638 @@
|
||||
/**
|
||||
* @file index.vue 质控图westGard
|
||||
* @author: w
|
||||
* @since: 2026-02-04
|
||||
*/
|
||||
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="5">
|
||||
<div class="mb5">
|
||||
<el-button type="primary" @click="getList">画图</el-button>
|
||||
<el-button type="warning">打印</el-button>
|
||||
</div>
|
||||
<el-form :model="queryParams" ref="queryRef" size="small">
|
||||
<el-form-item label="组别:" prop="instrGroup">
|
||||
<SelectTable v-model:data="queryParams.instrGroup" :tableData="instrGroupOptions" placeholder="请选择"
|
||||
@getDataValue="getYqConfig" size="small" />
|
||||
</el-form-item>
|
||||
<el-form-item label="仪器:" prop="yq">
|
||||
<SelectTable v-model:data="queryParams.yq" :tableData="instrOptions" placeholder="请选择仪器"
|
||||
@getDataValue="getXmList" size="small" />
|
||||
</el-form-item>
|
||||
<el-form-item label="月份:" prop="zkrq1">
|
||||
<el-date-picker v-model="queryParams.zkrq1" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
|
||||
style="width: 47%;" @change="handletime" /> -
|
||||
<el-date-picker v-model="queryParams.zkrq2" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
|
||||
@change="handletime" style="width: 47%;" />
|
||||
</el-form-item>
|
||||
<el-form-item label="次数:" prop="cs">
|
||||
<SelectTable v-model:data="queryParams.cs" :tableData="csData" placeholder="请选择"
|
||||
@getDataValue="() => { queryParams.zkph = '' }" size="small" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
<el-col :span="19">
|
||||
<CustomTable ref="tableRef" :data="tableData" :columns="columns" :config="tableConfig" @row-click="rowClick"
|
||||
@selection-change="selectChange">
|
||||
<template #action="scope">
|
||||
<el-button type="text" @click="handleEdit(scope.row, $event)">计算均值</el-button>
|
||||
<el-button type="text" @click="handlePj(scope.row, $event)">评价</el-button>
|
||||
</template>
|
||||
</CustomTable>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="10" class="table-row">
|
||||
<el-col :span="5" class="table-col">
|
||||
<div class="table-main">
|
||||
<el-table ref="xmRef" :data="xmList" height="100%" border highlightCurrentRow @row-click="xmHandle"
|
||||
show-overflow-tooltip>
|
||||
<el-table-column label="项目代号" prop="xmdh">
|
||||
<template #default="{ row }">
|
||||
{{ row.xmdh }} {{ row.xmmc }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="19" class="table-col2">
|
||||
<div ref="chartRef" style="width: 100%; height:300px"></div>
|
||||
|
||||
<div>
|
||||
<div class="tips">标准:</div>
|
||||
<el-table :data="zklist" height="150" border>
|
||||
<el-table-column label="质控品" prop="zkph" align="center">
|
||||
<template #default="{ row, $index }">
|
||||
{{ row.zkph }} <span class="radio" :style="{ backgroundColor: colorMap[$index] }"></span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="𝑋̄" prop="avg0" align="center" />
|
||||
<el-table-column label="SD" prop="sd0" align="center" />
|
||||
<el-table-column label="CV%" prop="cv0" align="center" />
|
||||
<el-table-column label="本月𝑋̄" prop="avg1" align="center" />
|
||||
<el-table-column label="本月SD" prop="sd1" align="center" />
|
||||
<el-table-column label="本月CV" prop="cv1" align="center" />
|
||||
<el-table-column label="批号" prop="zkpph" align="center" />
|
||||
<el-table-column label="累计𝑋̄" prop="avg3" align="center" />
|
||||
<el-table-column label="累计SD" prop="sd3" align="center" />
|
||||
<el-table-column label="累计CV" prop="cv3" align="center" />
|
||||
<el-table-column label="失控判断" prop="skpd" align="center" />
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="tips">当前图表数据:</div>
|
||||
|
||||
<div class="result-box">
|
||||
<div v-for="item in resultData" class="item">
|
||||
<div class="time">{{ item.zkrqMonth }}</div>
|
||||
<div v-for="v in zkKeys">
|
||||
<div :class="[item.flag == v ? 'red_title' : '']">{{ item['zkjg' + v] }}</div>
|
||||
</div>
|
||||
<div>{{ item.yhdh }}</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
|
||||
<!-- 质控值、SD计算 -->
|
||||
<el-dialog v-model="dialogVisible" title="质控靶值、SD计算" draggable :close-on-click-modal="false" width="500px">
|
||||
<el-form :model="form" ref="queryRef" label-width="90px">
|
||||
<el-form-item label="计算时间:" prop="xmdh">
|
||||
<el-date-picker v-model="form.sqsj1" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
|
||||
style="width: 47%;" @change="handletime" /> -
|
||||
<el-date-picker v-model="form.sqsj2" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
|
||||
@change="handletime" style="width: 47%;" />
|
||||
</el-form-item>
|
||||
<el-form-item label="质控项目:" prop="xmdh">
|
||||
<el-input v-model="form.xmdh" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="质控批号:" prop="zkph">
|
||||
<el-input v-model="form.zkph" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="计算靶值:" prop="zkbz">
|
||||
<el-input v-model="form.zkbz" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="SD:" prop="sd">
|
||||
<el-input v-model="form.sd" readonly />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="tips">
|
||||
提示:请选择计算起始和截止日期,系统自动计算出靶值和SD,计算完毕后可以按“确定”按钮返回计算值,也可以按“取消”按钮直接关闭窗口。
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="subHandle">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
|
||||
<el-dialog v-model="pjShow" title="本月质控评价" draggable :close-on-click-modal="false" width="500px">
|
||||
<el-form :model="pjForm" label-width="90px">
|
||||
<el-form-item label="质控批号:" prop="zkph">
|
||||
<el-input v-model="pjForm.zkph" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="评价:" prop="zkph">
|
||||
<el-input v-model="pjForm.bz1" type="textarea" :rows="10" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="pjShow = false">取消</el-button>
|
||||
<el-button type="primary" @click="pjHandle">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { getComDicts } from "@/api/liswork/dict/ComDict";
|
||||
import { getGroupInstrdList } from "@/api/liswork/work/LisWork";
|
||||
import { qcgraphList, querySample } from "@/api/liswork/qualityControl/index";
|
||||
import { classCom } from "@/utils/classCom";
|
||||
import { useCommonStore } from '@/store/modules/commonStore';
|
||||
import dayjs from 'dayjs';
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { queryBatch, queryBatchXm, } from '@/api/liswork/qualityControl'
|
||||
import * as echarts from 'echarts';
|
||||
import { use } from "vxe-pc-ui";
|
||||
|
||||
const mbStore = useCommonStore();
|
||||
|
||||
const pjShow = ref(false)
|
||||
|
||||
const pjForm = ref({
|
||||
zkph: '',
|
||||
bz1: '',
|
||||
})
|
||||
const dialogVisible = ref(false)
|
||||
const form = ref({
|
||||
xmdh: '',
|
||||
sqsj1: '',
|
||||
sqsj2: '',
|
||||
zkph: '',
|
||||
zkbz: '',
|
||||
sd: '',
|
||||
})
|
||||
const queryParams = ref({
|
||||
// instrGroup: mbStore.defaultConfig.lisgroupid || 'ALL',
|
||||
instrGroup: 'ALL',
|
||||
// yq: mbStore.defaultConfig.defaultinstr || '1',
|
||||
yq: '46',
|
||||
zkrq1: '',
|
||||
zkrq2: '',
|
||||
cs: '0',
|
||||
xmdh: '',
|
||||
zkph: '',
|
||||
})
|
||||
|
||||
const chartRef = useTemplateRef('chartRef')
|
||||
const tableRef = useTemplateRef('tableRef')
|
||||
const tableData = ref([])
|
||||
|
||||
const columns = ref([
|
||||
{ type: 'selection', label: '画图', width: 30, visible: true, align: 'center' },
|
||||
{ label: '质控品', prop: 'zkph', visible: true, align: 'center' },
|
||||
{ label: '起始日期', prop: 'ksrq', visible: true, align: 'center' },
|
||||
{ label: '质控批号', prop: 'zkpph', visible: true, align: 'center' },
|
||||
{ label: '浓度', prop: 'conc', visible: true, align: 'center' },
|
||||
{ label: '平均值', prop: 'zkbz', visible: true, align: 'center' },
|
||||
{ label: '试剂', prop: 'sjph', visible: true, align: 'center' },
|
||||
{ label: '波长', prop: 'bc', visible: true, align: 'center' },
|
||||
{ label: '方法', prop: 'ff', visible: true, align: 'center' },
|
||||
{ label: '备注', prop: 'bz1', visible: true, align: 'center' },
|
||||
])
|
||||
|
||||
const tableConfig = ref({
|
||||
border: true,
|
||||
height: '156px',
|
||||
actionWidth: 150,
|
||||
highlightCurrentRow: true,
|
||||
})
|
||||
const instrGroupOptions = ref([])
|
||||
const instrOptions = ref([])
|
||||
const csData = ref([
|
||||
{ value: '9', label: '最好1次' },
|
||||
{ value: '0', label: '平均值' },
|
||||
{ value: '8', label: '最后一次' },
|
||||
{ value: '10', label: '所有点' },
|
||||
{ value: '1', label: '第1次' },
|
||||
{ value: '2', label: '第2次' },
|
||||
{ value: '3', label: '第3次' },
|
||||
{ value: '4', label: '第4次' },
|
||||
{ value: '5', label: '第5次' },
|
||||
{ value: '6', label: '第6次' },
|
||||
{ value: '7', label: '第7次' },
|
||||
])
|
||||
|
||||
const zklist = ref([])
|
||||
const qcData = ref([])
|
||||
const resultData = ref([])
|
||||
const zkKeys = ref([])
|
||||
const xmList = ref([])
|
||||
const colorMap = ['#333', '#00b42a', '#ff9900', '#ff0', '#2f6dd1', '#a65']
|
||||
let mockRawDataMap = {};
|
||||
const loadinstrGroupOptions = () => {
|
||||
getComDicts({ zdlb: 'GROUP' }).then((res) => {
|
||||
instrGroupOptions.value = res.data.map((item) => ({
|
||||
value: item.zddh,
|
||||
label: item.zdmc
|
||||
}))
|
||||
instrGroupOptions.value.push({ value: 'ALL', label: '所有仪器' })
|
||||
getYqConfig()
|
||||
});
|
||||
}
|
||||
|
||||
// 仪器
|
||||
const getYqConfig = () => {
|
||||
queryParams.value.zkph = ''
|
||||
getGroupInstrdList({ lisgroup: queryParams.value.instrGroup })
|
||||
.then((res) => {
|
||||
if (res.code == 0) {
|
||||
instrOptions.value = res.data.map((item) => ({
|
||||
value: item.yq.trim(),
|
||||
label: item.yqmc
|
||||
}))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const handleEdit = (row, event) => {
|
||||
event.stopPropagation();
|
||||
form.value.xmdh = row.xmdh
|
||||
form.value.zkbz = row.zkbz
|
||||
form.value.zkph = row.zkph
|
||||
form.value.sd = row.sd
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
|
||||
const handlePj = (row, event) => {
|
||||
event.stopPropagation();
|
||||
pjForm.value = {
|
||||
zkph: row.zkph,
|
||||
bz1: row.bz1,
|
||||
}
|
||||
pjShow.value = true
|
||||
}
|
||||
|
||||
const pjHandle = () => {
|
||||
pjShow.value = false
|
||||
}
|
||||
|
||||
const subHandle = () => {
|
||||
}
|
||||
|
||||
const rowClick = (row) => {
|
||||
queryParams.value.zkph = row.zkph
|
||||
getList()
|
||||
}
|
||||
|
||||
const selectChange = (value) => {
|
||||
const arr = value.map(item => item.zkph)
|
||||
queryParams.value.zkph = arr.join(',')
|
||||
}
|
||||
const xmHandle = (row) => {
|
||||
queryParams.value.xmdh = row.xmdh
|
||||
queryParams.value.zkph = ''
|
||||
getSampleList()
|
||||
}
|
||||
const handletime = () => {
|
||||
queryParams.value.zkph = ''
|
||||
const dayFlag = classCom.getDayDiff(queryParams.value.zkrq1, queryParams.value.zkrq2)
|
||||
if (dayFlag === -1 || dayFlag === -2) return ElMessage.warning('请选择有效的日期范围')
|
||||
}
|
||||
const xmRef = useTemplateRef('xmRef')
|
||||
const getXmList = () => {
|
||||
queryParams.value.zkph = ''
|
||||
queryBatchXm({ yq: queryParams.value.yq }).then((res) => {
|
||||
xmList.value = res.data
|
||||
queryParams.value.xmdh = res.data[0].xmdh
|
||||
xmRef.value.setCurrentRow(res.data[0])
|
||||
getSampleList()
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
const getSampleList = () => {
|
||||
const data = {
|
||||
yq: queryParams.value.yq,
|
||||
xmdh: queryParams.value.xmdh,
|
||||
zkrq1: queryParams.value.zkrq1,
|
||||
zkrq2: queryParams.value.zkrq2,
|
||||
cs: queryParams.value.cs
|
||||
}
|
||||
querySample(data).then((res) => {
|
||||
tableData.value = res.data || []
|
||||
getList()
|
||||
nextTick(() => {
|
||||
tableRef.value.toggleAllSelection()
|
||||
})
|
||||
})
|
||||
};
|
||||
|
||||
let myChart = null
|
||||
// 初始化图表
|
||||
const initChart = () => {
|
||||
if (!chartRef.value) return;
|
||||
if (myChart) myChart.dispose();
|
||||
const el = chartRef.value;
|
||||
if (!el) return;
|
||||
myChart = echarts.init(el);
|
||||
|
||||
// 将原始值转换为SD映射值(-4~4)
|
||||
const handleDataToSD = (rawData, X, sd) => {
|
||||
const renderSDData = [];
|
||||
const originValue = [];
|
||||
rawData.forEach(val => {
|
||||
if (val === null) {
|
||||
// 无数据时,SD值也设为 null,折线跳过该点
|
||||
renderSDData.push(null);
|
||||
originValue.push(null);
|
||||
return;
|
||||
}
|
||||
originValue.push(val);
|
||||
const sdValue = (val - X) / sd;
|
||||
renderSDData.push(Math.max(-4, Math.min(4, sdValue)));
|
||||
});
|
||||
return { renderSDData, originValue };
|
||||
};
|
||||
|
||||
const series = [];
|
||||
// 存储所有系列的原始值(供tooltip使用)
|
||||
const originValueMap = {};
|
||||
|
||||
zklist.value.forEach((item, index) => {
|
||||
const { zkph, avg0, sd0 } = item;
|
||||
const rawData = mockRawDataMap[zkph] || []; // 获取当前质控品的原始数据
|
||||
const { renderSDData, originValue } = handleDataToSD(rawData, avg0, sd0);
|
||||
|
||||
// 存储原始值
|
||||
originValueMap[zkph] = originValue;
|
||||
|
||||
// 系列配置
|
||||
series.push({
|
||||
name: `质控品${zkph}`,
|
||||
type: 'line',
|
||||
data: renderSDData,
|
||||
smooth: true,
|
||||
symbol: 'circle',
|
||||
symbolSize: 6,
|
||||
lineWidth: 1.5,
|
||||
connectNulls: true, // 开启 null 点连接
|
||||
itemStyle: {
|
||||
// 按数据点数值动态设置转折点颜色
|
||||
color: (params) => getSymbolColor(params.value, colorMap[index]),
|
||||
shadowColor: colorMap[index],
|
||||
},
|
||||
lineStyle: { color: colorMap[index] || '#666' },
|
||||
z: 3,
|
||||
// 仅第一个系列显示SD参考线(避免重复)
|
||||
markLine: zkph === zklist.value[0].zkph ? {
|
||||
silent: true,
|
||||
symbol: ['none', 'none'],
|
||||
z: 2,
|
||||
lineStyle: { type: 'solid', width: 1.2 },
|
||||
data: [
|
||||
{ yAxis: 3, lineStyle: { color: '#f53f3f' }, label: { show: false } },
|
||||
{ yAxis: 2, lineStyle: { color: '#00b42a' }, label: { show: false } },
|
||||
{ yAxis: 1, lineStyle: { color: '#1890ff' }, label: { show: false } },
|
||||
{ yAxis: 0, lineStyle: { color: '#333' }, label: { show: false } },
|
||||
{ yAxis: -1, lineStyle: { color: '#1890ff' }, label: { show: false } },
|
||||
{ yAxis: -2, lineStyle: { color: '#00b42a' }, label: { show: false } },
|
||||
{ yAxis: -3, lineStyle: { color: '#f53f3f' }, label: { show: false } }
|
||||
]
|
||||
} : undefined
|
||||
});
|
||||
});
|
||||
|
||||
// X轴数据
|
||||
const xAxisData = Array.from(new Set(qcData.value.map(item => item.zkrqMonth))).splice(0, 31)
|
||||
// 核心配置
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
formatter: (params) => {
|
||||
// 过滤掉 null 值的系列
|
||||
const validParams = params.filter(p => p.data !== null);
|
||||
if (validParams.length === 0) return ''; // 无有效数据时不展示 tooltip
|
||||
|
||||
let res = `<div style="font-size:12px; font-weight:500;">${validParams[0].axisValue}</div>`;
|
||||
validParams.forEach((item, index) => {
|
||||
const zkph = item.seriesName.replace('质控品', '');
|
||||
const originVal = originValueMap[zkph][item.dataIndex];
|
||||
if (originVal === null) return; // 跳过 null 值
|
||||
const color = colorMap[index] || '#666';
|
||||
const currentItem = zklist.value.find(item => item.zkph === zkph);
|
||||
const originalSD = currentItem ? (originVal - currentItem.avg0) / currentItem.sd0 : 0;
|
||||
res += `<div style="margin-top:4px; font-size:12px;">
|
||||
<span style="display: inline-block; width: 10px; height: 10px; background: ${color};"></span>
|
||||
${item.seriesName}:<b>${originVal.toFixed(2)}</b>
|
||||
</div>`;
|
||||
});
|
||||
return res;
|
||||
}
|
||||
},
|
||||
grid: { left: '2%', right: '2%', bottom: '10%', top: '15%', containLabel: true },
|
||||
dataZoom: [
|
||||
{
|
||||
type: "slider",
|
||||
show: true,
|
||||
realtime: true,
|
||||
bottom: 20,
|
||||
height: 10,
|
||||
textStyle: { color: "transparent" },
|
||||
fillerColor: "#7ECFFF", // 浅蓝填充
|
||||
handleSize: "120%",
|
||||
handleStyle: {
|
||||
color: "#2DE2C4", // 滑块颜色与曲线主色一致
|
||||
borderWidth: 0,
|
||||
},
|
||||
backgroundColor: "#E5F3FF", // 滑条底色浅蓝
|
||||
borderColor: "transparent",
|
||||
},
|
||||
],
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: xAxisData,
|
||||
axisLabel: {
|
||||
fontSize: 12,
|
||||
// interval: 0, // 强制显示所有标签
|
||||
// width: 80, // 每个标签固定宽度80px(可根据需求调整)
|
||||
// align: 'center', // 标签居中
|
||||
// // rotate: 30, // 旋转避免文字重叠(可选)
|
||||
// overflow: 'truncate' // 文字过长时截断
|
||||
},
|
||||
axisLine: { lineStyle: { color: '#000' } },
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
min: -4,
|
||||
max: 4,
|
||||
axisLabel: {
|
||||
fontSize: 12,
|
||||
formatter: (v) => v === 0 ? '𝑋̄' : `${v}SD`
|
||||
},
|
||||
interval: 1,
|
||||
axisLine: { show: true, lineStyle: { color: '#000' } },
|
||||
splitLine: { lineStyle: { type: 'dashed', color: '#000' } }
|
||||
},
|
||||
series: series // 使用动态生成的系列
|
||||
};
|
||||
|
||||
myChart.setOption(option);
|
||||
};
|
||||
// 封装转折点颜色判断函数
|
||||
const getSymbolColor = (value, defaultColor) => {
|
||||
if (Math.abs(value) > 3) {
|
||||
return '#ff0000'; // 红色
|
||||
} else if (Math.abs(value) > 2) {
|
||||
return '#ffc0cb'; // 粉色
|
||||
}
|
||||
return defaultColor;
|
||||
};
|
||||
|
||||
const getList = () => {
|
||||
qcgraphList(queryParams.value).then((res) => {
|
||||
mockRawDataMap = {};
|
||||
if (res.data) {
|
||||
zklist.value = res.data.QcSamplelist;
|
||||
qcData.value = res.data.QcValList.map((item) => ({
|
||||
...item,
|
||||
zkrqMonth: dayjs(item.zkrq).format('YY/M/D')
|
||||
}));
|
||||
const xAxisData = Array.from(new Set(qcData.value.map(item => item.zkrqMonth))).splice(0, 31);
|
||||
const zkphs = Array.from(new Set(zklist.value.map(item => item.zkph)));
|
||||
const dateZkphValueMap = new Map();
|
||||
qcData.value.forEach((data) => {
|
||||
const key = `${data.zkrqMonth}_${data.zkph}`;
|
||||
dateZkphValueMap.set(key, data.zkjg ?? null); // 无值则存 null
|
||||
});
|
||||
zkphs.forEach((zkph) => {
|
||||
mockRawDataMap[zkph] = xAxisData.map((date) => {
|
||||
const key = `${date}_${zkph}`;
|
||||
return dateZkphValueMap.get(key) ?? null; // 无数据 = null
|
||||
});
|
||||
});
|
||||
|
||||
zkKeys.value = Object.keys(mockRawDataMap);
|
||||
|
||||
resultData.value = xAxisData.map((item, i) => {
|
||||
const obj = {};
|
||||
obj['zkrqMonth'] = item;
|
||||
zkKeys.value.map(v => {
|
||||
obj['zkjg' + v] = mockRawDataMap[v][i] ?? '';
|
||||
});
|
||||
return obj;
|
||||
}).splice(0, 31);
|
||||
|
||||
resultData.value.map(item => {
|
||||
qcData.value.map(v => {
|
||||
if (item.zkrqMonth == v.zkrqMonth) {
|
||||
item.yhdh = v.yhdh;
|
||||
// 判断是否为失控
|
||||
item.flag = Math.abs((v.zkbz - v.zkjg) / v.sd) > 3 ? v.zkph : '';
|
||||
}
|
||||
});
|
||||
});
|
||||
// console.log('resultData.value==>', resultData.value);
|
||||
nextTick(() => {
|
||||
initChart();
|
||||
});
|
||||
} else {
|
||||
qcData.value = [];
|
||||
zklist.value = [];
|
||||
zkKeys.value = [];
|
||||
resultData.value = [];
|
||||
initChart()
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const timeDate = () => {
|
||||
const today = dayjs();
|
||||
const startOfWeek = today.subtract(6, 'day');
|
||||
// queryParams.zkrq1 = startOfWeek.format('YYYY-MM-DD');
|
||||
// queryParams.zkrq2 = today.format('YYYY-MM-DD');
|
||||
queryParams.value.zkrq1 = '2025-02-01';
|
||||
queryParams.value.zkrq2 = today.format('YYYY-MM-DD');
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getXmList()
|
||||
timeDate()
|
||||
loadinstrGroupOptions()
|
||||
// getList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.el-form-item {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.table-row {
|
||||
height: 100%;
|
||||
|
||||
.table-col {
|
||||
height: 100%;
|
||||
|
||||
.table-main {
|
||||
height: calc(100% - 165px);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.table-col2 {
|
||||
height: calc(100% - 165px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.tips {
|
||||
font-family: SourceHanSansCN, SourceHanSansCN;
|
||||
font-size: 14px;
|
||||
color: #409eff;
|
||||
font-weight: 600;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.radio {
|
||||
display: inline-block;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.result-box {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.item {
|
||||
|
||||
&>div {
|
||||
width: 100px;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
text-align: center;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.time {
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.red_title {
|
||||
color: #f00;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
@ -8,8 +8,7 @@
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryRef" label-width="90px" inline>
|
||||
<el-form-item label="病人来源:" prop="brly">
|
||||
<SelectTable v-model:data="queryParams.brly" dictType='PT' placeholder="请选择病人来源" @getDataValue="handleQuery"
|
||||
style="width: 12rem;" />
|
||||
<SelectTable v-model:data="queryParams.brly" dictType='PT' placeholder="请选择病人来源" style="width: 12rem;" />
|
||||
</el-form-item>
|
||||
<el-form-item label="病人代号:" prop="brdh">
|
||||
<el-input v-model="queryParams.brdh" placeholder="请输入病人代号" />
|
||||
@ -26,8 +25,7 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="科室病区:" prop="ksdh">
|
||||
<SelectTable v-model:data="queryParams.ksdh" dictType='DP' placeholder="请选择科室" @getDataValue="handleQuery"
|
||||
style="width: 12rem;" />
|
||||
<SelectTable v-model:data="queryParams.ksdh" dictType='DP' placeholder="请选择科室" style="width: 12rem;" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="申请日期:" prop="sqsj1">
|
||||
@ -43,10 +41,11 @@
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">查询</el-button>
|
||||
<el-button type="default" icon="Refresh" @click="refresh">重置</el-button>
|
||||
<el-button type="warning" @click="printHandle">导出</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
|
||||
<!--更多查询条件 -->
|
||||
<el-drawer title="查询条件" v-model="isExpand" direction="rtl" size="28%" :with-header="true" :modal="false">
|
||||
<el-form :model="queryParams" label-width="120px">
|
||||
<el-form-item label="批准/联系人:" prop="powerman">
|
||||
@ -55,8 +54,8 @@
|
||||
<el-form-item label="录入人:" prop="inputman">
|
||||
<el-input v-model="queryParams.inputman" placeholder="请输入录入人" />
|
||||
</el-form-item>
|
||||
<el-form-item label="条码类别:" prop="updateBy">
|
||||
|
||||
<el-form-item label="条码类别:" prop="bgddh">
|
||||
<SelectTable v-model:data="queryParams.bgddh" :tableData="feeitemList" placeholder="请选择条码类别" />
|
||||
</el-form-item>
|
||||
<el-form-item label="单据计价:" prop="jjzt">
|
||||
<el-radio-group v-model="queryParams.jjzt">
|
||||
@ -73,11 +72,11 @@
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="类别对应仪器:" prop="yqdh">
|
||||
<YQSelectTable v-model:data="queryParams.yqdh" placeholder="请选择类别对应仪器" />
|
||||
<YQSelectTable v-model:data="queryParams.yqdh" placeholder="请选择类别对应仪器" :clearable="true" />
|
||||
</el-form-item>
|
||||
<el-form-item label="仪器分组:" prop="instrGroup">
|
||||
<SelectTable v-model:data="queryParams.instrGroup" :fields="instrGroupFields" :tableData="instrGroupOptions"
|
||||
label="zdmc" value="zddh" objKey="zddh" :border="true" placeholder="请选择部门" />
|
||||
label="zdmc" value="zddh" objKey="zddh" placeholder="请选择部门" />
|
||||
</el-form-item>
|
||||
<el-form-item label="签收人:" prop="qsr">
|
||||
<el-input v-model="queryParams.qsr" placeholder="请输入批准/联系人" />
|
||||
@ -89,7 +88,7 @@
|
||||
@change="handletime" style="width: 46%;" />
|
||||
</el-form-item>
|
||||
<el-form-item label="医疗机构:" prop="yljg">
|
||||
<SelectTable v-model:data="queryParams.yljg" dictType="HOS" placeholder="请选择" @getDataValue="handleQuery" />
|
||||
<SelectTable v-model:data="queryParams.yljg" dictType="HOS" placeholder="请选择" />
|
||||
</el-form-item>
|
||||
<el-form-item label="">
|
||||
<el-checkbox v-model="queryParams.jzbz" label="急诊" true-value="1" false-value="0" />
|
||||
@ -104,8 +103,8 @@
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="drawer-footer">
|
||||
<el-button type="primary" @click="isExpand = false"> 查询 </el-button>
|
||||
<el-button @click="isExpand = false">重置</el-button>
|
||||
<el-button type="primary" @click="handleQuery"> 查询 </el-button>
|
||||
<el-button @click="refresh">重置</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-drawer>
|
||||
@ -127,6 +126,9 @@
|
||||
<template #mxjjzt="{ row }">
|
||||
<el-checkbox :model-value="row.mxjjzt == '1'" readonly />
|
||||
</template>
|
||||
<template #refused="{ row }">
|
||||
<el-checkbox :model-value="row.refused == '1'" readonly />
|
||||
</template>
|
||||
<template #zt="{ row }">
|
||||
{{ formatDict(row.zt.trim(), 'ST') }}
|
||||
</template>
|
||||
@ -152,13 +154,13 @@ import YQSelectTable from '@/components/SelectTable/YQSelectTable'
|
||||
import dayjs from 'dayjs'
|
||||
import { getComDicts } from '@/api/liswork/dict/ComDict';
|
||||
import { wholeprocessList } from '@/api/liswork/work/LisWork'
|
||||
import { load } from '@fingerprintjs/fingerprintjs';
|
||||
import { feeitemclassList } from '@/api/mzcx/index';
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const { lis_reqzt_type } = proxy.useDict("lis_reqzt_type"); //参数类别
|
||||
|
||||
const isExpand = ref(false);
|
||||
let queryParams = reactive({
|
||||
const queryParams = ref({
|
||||
sqsj1: '',
|
||||
sqsj2: '',
|
||||
brdh: '',
|
||||
@ -166,6 +168,8 @@ let queryParams = reactive({
|
||||
sqh: '',
|
||||
mxjjzt: '',
|
||||
jjzt: '',
|
||||
jssj1: '',
|
||||
jssj2: '',
|
||||
pageNum: 1,
|
||||
pageSize: 500,
|
||||
})
|
||||
@ -173,7 +177,7 @@ let queryParams = reactive({
|
||||
const sumMoney = ref(0)
|
||||
|
||||
const total = ref(0)
|
||||
|
||||
const feeitemList = ref([])
|
||||
const loading = ref(false)
|
||||
// 数据源
|
||||
const tableData = ref([])
|
||||
@ -182,7 +186,7 @@ const columns = ref([
|
||||
{ field: 'yljg', title: '送检医院', align: 'center', resizable: true, slotName: 'yljg', width: 150 },
|
||||
{ field: 'brlyname', title: '病人来源', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'ksname', title: '申请科室', resizable: true, align: 'center', width: 100 },
|
||||
{ field: 'yblx', title: '标本', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'yblxname', title: '标本', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'ch', title: '床号', resizable: true, align: 'center', width: 40 },//sortable: true,
|
||||
{ field: 'brxm', title: '姓名', align: 'center', resizable: true, width: 50 },
|
||||
{ field: 'brxbname', title: '性别', align: 'center', resizable: true, width: 30 },
|
||||
@ -195,9 +199,9 @@ const columns = ref([
|
||||
{ field: 'dj', title: '单价', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'mxjjzt', title: '明细计价', align: 'center', resizable: true, width: 60, slotName: 'mxjjzt' },
|
||||
{ field: 'jzbz', title: '急', align: 'center', resizable: true, slotName: 'jzbz', width: 30 },
|
||||
{ field: 'zt', title: '当前状态', align: 'center', resizable: true, slotName: 'zt', width: 60 },
|
||||
{ field: 'refused', title: '拒收标记', align: 'center', resizable: true, slotName: 'bj', width: 60 },
|
||||
{ field: 'sqxmdh', title: '项目代号', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'ztname', title: '当前状态', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'refused', title: '拒收标记', align: 'center', resizable: true, slotName: 'refused', width: 60 },
|
||||
{ field: 'sqxmdh', title: '项目代号', align: 'center', resizable: true, width: 80 },
|
||||
{ field: 'sqysname', title: '申请医生', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'sqsj', title: '申请时间', align: 'center', resizable: true, width: 150 },
|
||||
{ field: 'zxysname', title: '执行医生', align: 'center', resizable: true, width: 60 },
|
||||
@ -206,47 +210,45 @@ const columns = ref([
|
||||
{ field: 'bbsjsj', title: '标本送出时间', align: 'center', resizable: true, width: 150 },
|
||||
{ field: 'jssj', title: '接收时间', align: 'center', resizable: true, width: 150 },
|
||||
{ field: 'sjsj', title: '上机时间', align: 'center', resizable: true, width: 150 },
|
||||
{ field: 'confirmer', title: '审核人', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'confirmername', title: '审核人', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'confirmtime', title: '审核时间', align: 'center', resizable: true, width: 150 },
|
||||
{ field: 'cyrname', title: '采样人', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'bbsjrname', title: '标本送出人', align: 'center', resizable: true, width: 80 },
|
||||
{ field: 'jsysname', title: '接收医生', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'zd', title: '诊断', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'inputman', title: '录入人', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'powerman', title: '批准人', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'contactman', title: '联系人', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'xh', title: '相关编号', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'inzt', title: '是否销毁', align: 'center', resizable: true, slotName: 'inzt', width: 60 },
|
||||
{ field: 'libpos', title: '存放位置', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'inlibtime', title: '存放时间', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'inlibman', title: '存放人', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'outlibtime', title: '销毁时间', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'outlibman', title: '销毁人', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'yqdh', title: '上机仪器', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'zd', title: '诊断', align: 'center', resizable: true, width: 120 },
|
||||
// { field: 'inputman', title: '录入人', align: 'center', resizable: true, width: 60 },
|
||||
// { field: 'powerman', title: '批准人', align: 'center', resizable: true, width: 60 },
|
||||
// { field: 'contactman', title: '联系人', align: 'center', resizable: true, width: 60 },
|
||||
// { field: 'inzt', title: '是否销毁', align: 'center', resizable: true, slotName: 'inzt', width: 60 },
|
||||
// { field: 'libpos', title: '存放位置', align: 'center', resizable: true, width: 60 },
|
||||
// { field: 'inlibtime', title: '存放时间', align: 'center', resizable: true, width: 60 },
|
||||
// { field: 'inlibman', title: '存放人', align: 'center', resizable: true, width: 60 },
|
||||
// { field: 'outlibtime', title: '销毁时间', align: 'center', resizable: true, width: 60 },
|
||||
// { field: 'outlibman', title: '销毁人', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'yqname', title: '上机仪器', align: 'center', resizable: true, width: 120 },
|
||||
{ field: 'phone', title: '病人联系电话', align: 'center', resizable: true, width: 100 },
|
||||
{ field: 'phone1', title: '家属联系电话', align: 'center', resizable: true, width: 100 },
|
||||
{ field: 'sfzh', title: '身份证号', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'cp_cytojs', title: '接收TAT', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'cp_jstobg', title: '报告TAT', align: 'center', resizable: true, width: 60 },
|
||||
{ field: 'sfzh', title: '身份证号', align: 'center', resizable: true, width: 100 },
|
||||
{ field: 'cp_cytojs', title: '接收TAT', align: 'center', resizable: true, width: 100 },
|
||||
{ field: 'cp_jstobg', title: '报告TAT', align: 'center', resizable: true, width: 100 },
|
||||
{ field: 'min1', title: '接收规定TAT', align: 'center', resizable: true, width: 100 },
|
||||
{ field: 'min2', title: '报告规定TAT', align: 'center', resizable: true, width: 100 },
|
||||
])
|
||||
|
||||
const handleColumnDragEnd = (data) => {
|
||||
console.log("🚀 ~ handleColumnDragEnd ~ data:", data)
|
||||
columns.value = [];
|
||||
nextTick(() => {
|
||||
columns.value = [...data.columns];
|
||||
});
|
||||
}
|
||||
const handletime = () => {
|
||||
const dayDiff = classCom.getDayDiff(queryParams.sqsj1, queryParams.sqsj2);
|
||||
const dayDiff = classCom.getDayDiff(queryParams.value.sqsj1, queryParams.value.sqsj2);
|
||||
if (dayDiff === -1 || dayDiff === -2) return ElMessage.warning('请选择有效的日期范围');
|
||||
}
|
||||
|
||||
const pagination = (val) => {
|
||||
queryParams.pageSize = val.limit;
|
||||
queryParams.pageNum = val.page;
|
||||
queryParams.value.pageSize = val.limit;
|
||||
queryParams.value.pageNum = val.page;
|
||||
handleQuery();
|
||||
}
|
||||
|
||||
@ -254,25 +256,37 @@ const pagination = (val) => {
|
||||
const handleQuery = () => {
|
||||
loading.value = true;
|
||||
// 查询数据
|
||||
wholeprocessList(queryParams).then((res) => {
|
||||
wholeprocessList(queryParams.value).then((res) => {
|
||||
loading.value = false;
|
||||
tableData.value = res.rows;
|
||||
total.value = res.total;
|
||||
sumMoney.value = (res.rows.reduce((acc, cur) => acc + cur.dj * cur.sl, 0)).toFixed(2);
|
||||
});
|
||||
|
||||
isExpand.value = false;
|
||||
}
|
||||
|
||||
const refresh = () => {
|
||||
queryParams = {
|
||||
st: '',
|
||||
et: '',
|
||||
queryParams.value = {
|
||||
sqsj1: '',
|
||||
sqsj2: '',
|
||||
brdh: '',
|
||||
brxm: '',
|
||||
sqh: '',
|
||||
mxjjzt: '',
|
||||
jjzt: '',
|
||||
jssj1: '',
|
||||
jssj2: '',
|
||||
pageNum: 1,
|
||||
pageSize: 500,
|
||||
}
|
||||
timeDate()
|
||||
handleQuery();
|
||||
}
|
||||
|
||||
const printHandle = () => {
|
||||
}
|
||||
|
||||
const instrGroupOptions = ref([])
|
||||
const instrGroupFields = ref([
|
||||
{ prop: 'zddh', label: '代号', width: 80, enablePinyinSearch: true },
|
||||
@ -297,8 +311,8 @@ const timeDate = () => {
|
||||
|
||||
// queryParams.sqsj1 = startOfWeek.format('YYYY-MM-DD');
|
||||
// queryParams.sqsj2 = today.format('YYYY-MM-DD');
|
||||
queryParams.sqsj1 = '2025-08-01';
|
||||
queryParams.sqsj2 = today.format('YYYY-MM-DD');
|
||||
queryParams.value.sqsj1 = '2025-08-01';
|
||||
queryParams.value.sqsj2 = today.format('YYYY-MM-DD');
|
||||
|
||||
}
|
||||
|
||||
@ -307,6 +321,17 @@ onMounted(() => {
|
||||
getinstrGroupOptions()
|
||||
getDictData('HOS', 'PT', 'ST');
|
||||
handleQuery()
|
||||
|
||||
|
||||
feeitemclassList().then((res) => {
|
||||
feeitemList.value = res.rows?.map(item => {
|
||||
return {
|
||||
...item,
|
||||
label: item.sflbmc,
|
||||
value: item.sflbdh
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user