公共表格封装加列

拖拽功能
This commit is contained in:
wyuu 2025-10-10 17:35:28 +08:00
parent bf34cd1ed4
commit 2f56182ca9
15 changed files with 533 additions and 465 deletions

View File

@ -32,7 +32,7 @@
"pinyin-pro": "^3.26.0", "pinyin-pro": "^3.26.0",
"select2": "^4.1.0-rc.0", "select2": "^4.1.0-rc.0",
"socket.io-client": "^4.8.1", "socket.io-client": "^4.8.1",
"sortablejs": "^1.15.6", "sortablejs": "^1.14.0",
"vue": "3.4.0", "vue": "3.4.0",
"vue-cropper": "1.1.1", "vue-cropper": "1.1.1",
"vue-plugin-hiprint": "^0.0.60", "vue-plugin-hiprint": "^0.0.60",

View File

@ -188,13 +188,6 @@
} }
:deep(.el-input__wrapper) {
// border-color: #96B8D9 !important;
// border-color: #f00 !important;
}
.el-input__wrapper, .el-input__wrapper,
.el-select__wrapper { .el-select__wrapper {
box-shadow: 0 0 0 1px #96B8D9 inset; box-shadow: 0 0 0 1px #96B8D9 inset;

View File

@ -7,12 +7,12 @@
:header-cell-style="config.headerCellStyle" :cell-style="config.cellStyle" :max-height="config.maxHeight" :header-cell-style="config.headerCellStyle" :cell-style="config.cellStyle" :max-height="config.maxHeight"
:height="config.height" :size="config.size || 'default'" :empty-text="config.emptyText || '暂无数据'" :height="config.height" :size="config.size || 'default'" :empty-text="config.emptyText || '暂无数据'"
@selection-change="handleSelectionChange" @current-change="handleCurrentChange" @row-click="handleRowClick" @selection-change="handleSelectionChange" @current-change="handleCurrentChange" @row-click="handleRowClick"
header-cell-class-name="el-table-header-cell" @row-dblclick="handleRowDblclick" @sort-change="handleSortChange" :header-cell-class-name="enableColumnDrag ? 'el-table-header-cell' : ''" @row-dblclick="handleRowDblclick"
v-bind="$attrs"> @sort-change="handleSortChange" v-bind="$attrs">
<!-- 动态列 --> <!-- 动态列 -->
<template v-for="item in columns" :key="item.prop "> <template v-for="item in columns" :key="item.prop">
<!-- 多选列 --> <!-- 多选列 -->
<el-table-column v-if="item.type == 'selection' && item.visible" type="selection" :width="item.width || 55" <el-table-column v-if="item.type == 'selection' && item.visible" type="selection" :width="item.width || 55"
:fixed="item.fixed" :align="item.align || 'left'" /> :fixed="item.fixed" :align="item.align || 'left'" />
@ -255,7 +255,6 @@ watch(
const initColumnDrag = () => { const initColumnDrag = () => {
// 获取表头单元格 // 获取表头单元格
const tableHeader = tableRef.value.$el.querySelector('.el-table__header-wrapper thead tr'); const tableHeader = tableRef.value.$el.querySelector('.el-table__header-wrapper thead tr');
console.log('tableHeader==>', tableHeader);
if (!tableHeader) return; if (!tableHeader) return;
// 初始化拖拽 // 初始化拖拽
const sortable = new Sortable(tableHeader, { const sortable = new Sortable(tableHeader, {
@ -264,7 +263,7 @@ const initColumnDrag = () => {
ghostClass: 'sortable-ghost', // 拖拽时的占位符样式 ghostClass: 'sortable-ghost', // 拖拽时的占位符样式
// filter: '.el-table-column--selection, .el-table-column--index', // 排除选择列和序号列 // filter: '.el-table-column--selection, .el-table-column--index', // 排除选择列和序号列
onEnd: (evt: any) => { onEnd: (evt: any) => {
console.log('evt==>', evt); // console.log('evt==>', evt);
// 排除固定列和选择列、序号列 // 排除固定列和选择列、序号列
const visibleColumns = props.columns.filter(col => col.visible !== false); const visibleColumns = props.columns.filter(col => col.visible !== false);

View File

@ -0,0 +1,215 @@
<!--
* vxe-table 通用表格组件 适用数据量大
* @props columns: 表格列配置
* @props tableData: 表格数据
* @props loading: 加载状态
* @props rowConfig: 行配置
* @props showOverflow: 是否显示内容溢出省略
* @props highlightCurrentRow: 是否高亮当前行
* @props scrollYConfig: 纵向滚动配置
* scroll-y 纵向滚动 设置虚拟滚动
-->
<template>
<div class="common-table-container">
<vxe-table :data="tableData" :loading="loading" border height="auto" class="common-table" :row-config="rowConfig"
:show-overflow="showOverflow" @current-change="handleRowClick" ref="tableRef" :size="size"
:current-row="currentRow" :highlight-current-row="highlightCurrentRow" :scroll-y="scrollYConfig"
:header-cell-class-name="enableColumnDrag ? 'el-table-header-cell' : ''" v-bind="$attrs">
<!-- 动态渲染列 -->
<template v-for="(column, i) in columns" :key="`${column.field}-${i}`">
<vxe-column v-bind="column">
<!-- 自定义列模板 -->
<template v-if="column.slotName" #default="scope">
<slot :name="column.slotName" :row="scope.row"></slot>
</template>
</vxe-column>
</template>
</vxe-table>
</div>
</template>
<script setup lang="ts">
import { ref, nextTick, watch, onMounted } from 'vue'
// @ts-ignore
import Sortable from 'sortablejs'; // 引入sortablejs
// 定义列配置类型
interface TableColumn {
field: string
title: string
width?: number | string
align?: string
slotName?: string // 自定义插槽名称
[key: string]: any // 支持其他vxe-column属性
}
// 定义props类型
const props = defineProps({
// 表格数据
tableData: {
type: Array,
default: () => []
},
// 加载状态
loading: {
type: Boolean,
default: false
},
// 列配置
columns: {
type: Array as () => TableColumn[],
required: true
},
// 行配置
rowConfig: {
type: Object,
default: () => ({ isHover: true, height: 30 })
},
// 是否显示内容溢出省略
showOverflow: {
type: Boolean,
default: true
},
// 是否高亮当前行
highlightCurrentRow: {
type: Boolean,
default: true
},
// 纵向滚动配置
scrollYConfig: {
type: Object,
default: () => ({ enabled: true, rSize: 50, adaptive: true })
},
// 表格尺寸
size: {
type: String,
default: 'medium'
},
// 拖拽列
enableColumnDrag: {
type: Boolean,
default: false
}
})
const emits = defineEmits(['current-change', "column-drag-end",])
const tableRef = ref<any>(null)
const currentRow = ref<any>(null)
// 处理行点击
const handleRowClick = (params: { row: any }) => {
currentRow.value = params.row
emits('current-change', params.row)
}
// 设置当前行
const setCurrentRow = (row: any) => {
if (tableRef.value) {
tableRef.value.setCurrentRow(row)
nextTick(() => {
tableRef.value.scrollToRow(row)
})
}
}
// 初始化列拖拽功能
onMounted(() => {
if (props.enableColumnDrag && tableRef.value) {
initColumnDrag();
}
});
// 监听数据变化时重置当前行
watch(() => props.tableData, () => {
currentRow.value = null
})
// 初始化列拖拽
const initColumnDrag = () => {
// 获取表头单元格
const tableHeader = tableRef.value.$el.querySelector('.vxe-table--header thead tr');
if (!tableHeader) return;
// 初始化拖拽
const sortable = new Sortable(tableHeader, {
animation: 150, // 动画时间
handle: '.el-table-header-cell', // 拖拽手柄
ghostClass: 'sortable-ghost', // 拖拽时的占位符样式
onEnd: (evt: any) => {
// console.log('evt==>', evt);
// 过滤掉固定列
const draggableColumns = props.columns.filter(col => !col.fixed);
// 如果发生了位置变化
if (evt.oldIndex !== evt.newIndex && draggableColumns.length) {
// 复制原数组并调整顺序
const newColumns = [...draggableColumns];
const [movedItem] = newColumns.splice(evt.oldIndex, 1);
newColumns.splice(evt.newIndex, 0, movedItem);
// 更新原始columns数组中对应列的位置
const updatedColumns = [...props.columns];
// 先移除所有可拖拽列
const nonDraggableColumns = updatedColumns.filter(col => col.fixed);
// 合并固定列和新顺序的可拖拽列
const resultColumns = nonDraggableColumns.concat(newColumns);
// 触发事件,通知父组件列顺序已改变
emits('column-drag-end', {
oldIndex: evt.oldIndex,
newIndex: evt.newIndex,
columns: [...resultColumns]
});
}
}
});
};
// 暴露公共方法
defineExpose({
setCurrentRow,
tableRef,
})
</script>
<style scoped lang="scss">
.common-table-container {
height: 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);
}
// 表头边框
:deep(.vxe-table--render-default.border--full .vxe-header--column) {
background-image: linear-gradient(#1F6DD3, #1F6DD3), linear-gradient(#1F6DD3, #1F6DD3);
}
</style>

View File

@ -14,9 +14,9 @@ import 'vxe-table/lib/style.css'
import '@/assets/styles/index.scss' // global css import '@/assets/styles/index.scss' // global css
// 先导入 jQuery 并设置全局变量 // 先导入 jQuery 并设置全局变量
import * as $ from 'jquery'; // import * as $ from 'jquery';
window.jQuery = $; // window.jQuery = $;
window.$ = $; // window.$ = $;
import App from './App' import App from './App'
import store from './store' import store from './store'

View File

@ -148,7 +148,7 @@
import { ref, reactive, toRaw, computed, watch, nextTick, onMounted, } from 'vue'; import { ref, reactive, toRaw, computed, watch, nextTick, onMounted, } from 'vue';
import { HiprintPrinter } from '@/utils/hiprintPrinter'; import { HiprintPrinter } from '@/utils/hiprintPrinter';
import { classCom } from '@/utils/classCom'; import { classCom } from '@/utils/classCom';
import CustomTable from '@/components/tableCom/index.vue' import CustomTable from '@/components/elTable/index.vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { usePrintStore } from '@/store/modules/printStore' import { usePrintStore } from '@/store/modules/printStore'
import { fetchCodeList, addObj, fetchCodeDetail, fetchCodeExec, fetchCodeReqmain } from '@/api/checkCode/index' import { fetchCodeList, addObj, fetchCodeDetail, fetchCodeExec, fetchCodeReqmain } from '@/api/checkCode/index'
@ -313,7 +313,6 @@ const handleColumnDragEnd = (data: any) => {
const tableConfig = ref({ const tableConfig = ref({
// stripe: true, // 斑马纹 // stripe: true, // 斑马纹
border: true, // 边框 border: true, // 边框
index: true, // 序号 index: true, // 序号
height: '', // 高度 height: '', // 高度
highlightCurrentRow: true, // 高亮当前行 highlightCurrentRow: true, // 高亮当前行
@ -337,8 +336,6 @@ const rightColumns = ref([
const rightTableConfig = ref({ const rightTableConfig = ref({
// stripe: true, // 斑马纹 // stripe: true, // 斑马纹
border: false, // 边框 border: false, // 边框
//
height: '', // 高度 height: '', // 高度
highlightCurrentRow: true, // 高亮当前行 highlightCurrentRow: true, // 高亮当前行
}) })
@ -454,7 +451,7 @@ const getRightTable = (row: any) => {
const goReport = () => { const goReport = () => {
// 跳转到报告查询页面 // 跳转到报告查询页面
router.push('/report') router.push('/report?startdate=2025-08-19&endate=2025-08-19&deptcode=0210&userid=00910&brdh=')
}; };
const cancelHandle = () => { const cancelHandle = () => {

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<div ref="compactForm"> <div ref="compactForm">
<el-row :gutter="10" class="compact-form" v-show="showSearch"> <el-row :gutter="5" class="compact-form" v-show="showSearch">
<el-form :model="queryParams" ref="queryRef" label-width="100px" :rules="queryRules" style="width: 100%;"> <el-form :model="queryParams" ref="queryRef" label-width="100px" :rules="queryRules" style="width: 100%;">
<el-row> <el-row>
<el-col :span="5"> <el-col :span="5">
@ -12,7 +12,7 @@
</el-col> </el-col>
<el-col :span="5"> <el-col :span="5">
<el-form-item label="打印状态:" prop="dybz"> <el-form-item label="打印状态:" prop="dybz">
<el-select v-model="queryParams.dybz" placeholder="请选择" style=" "> <el-select v-model="queryParams.dybz" placeholder="请选择" clearable>
<el-option label="已打印" value="1" /> <el-option label="已打印" value="1" />
<el-option label="未打印" value="0" /> <el-option label="未打印" value="0" />
</el-select> </el-select>
@ -26,20 +26,21 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="5"> <el-col :span="5">
<el-form-item label="病人类型:" prop="brly"> <el-form-item label="病人类型:" prop="brlyname">
<el-select v-model="queryParams.brly" placeholder="请选择"> <el-select v-model="queryParams.brlyname" placeholder="请选择" clearable>
<el-option v-for="item in dictData.PT" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in dictData.PT" :key="item.value" :label="item.label" :value="item.label" />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="4">
<el-form-item label="" prop=""> </el-row>
<el-row>
<el-col :span="5">
<el-form-item label-width="50px">
<el-checkbox v-model="queryParams.alarmflag" label="仅危急值" @change="alarmHandle" size="large" /> <el-checkbox v-model="queryParams.alarmflag" label="仅危急值" @change="alarmHandle" size="large" />
<el-checkbox v-model="queryParams.jzbz" label="仅急诊" @change="jzbzHandle" size="large" /> <el-checkbox v-model="queryParams.jzbz" label="仅急诊" @change="jzbzHandle" size="large" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row>
<el-row>
<el-col :span="5"> <el-col :span="5">
<el-form-item label="姓名:" prop="brxm"> <el-form-item label="姓名:" prop="brxm">
<el-input v-model="queryParams.brxm" clearable placeholder="请输入姓名" @keyup.enter="handleQuery" <el-input v-model="queryParams.brxm" clearable placeholder="请输入姓名" @keyup.enter="handleQuery"
@ -58,12 +59,12 @@
@clear="handleQuery" /> @clear="handleQuery" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="5"> <el-col :span="4">
<el-form-item label=""> <el-form-item label-width="50px">
<el-button icon="search" type="primary" @click="handleQuery"> <el-button icon="search" type="primary" @click="handleQuery">
搜索 搜索
</el-button> </el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button> <!-- <el-button icon="Refresh" @click="resetQuery">重置</el-button> -->
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@ -72,7 +73,7 @@
</el-row> </el-row>
</div> </div>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="14" class="right-table"> <el-col :span="16" class="right-table">
<el-row :gutter="10" class="mb8 mt10"> <el-row :gutter="10" class="mb8 mt10">
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="primary" plain icon="Edit" @click="selectStatusRows">勾选所有未打印</el-button> <el-button type="primary" plain icon="Edit" @click="selectStatusRows">勾选所有未打印</el-button>
@ -93,18 +94,18 @@
{{ row.dybz == 1 ? '✅' : '❌' }} {{ row.dybz == 1 ? '✅' : '❌' }}
</template> </template>
<template #alarmflag="{ row }"> <template #alarmflag="{ row }">
{{ row.alarmflag == 1 ? '是' : '否' }} {{ row.alarmflag == 1 ? '危' : '' }}
</template> </template>
<template #jzbz="{ row }"> <template #jzbz="{ row }">
{{ row.jzbz == 1 ? '急诊' : '危急诊' }} {{ row.jzbz == 1 ? '急' : '' }}
</template> </template>
</CustomTable> </CustomTable>
</el-col> </el-col>
<el-col :span="10" class="right-table"> <el-col :span="8" class="right-table">
<!-- <div class="title">检验结果</div> --> <!-- <div class="title">检验结果</div> -->
<div class="mb8 mt10"> <div class="mb8 mt10">
<el-button type="primary" @click="openDB">对比历史</el-button> <el-button type="primary" plain @click="openDB">对比历史</el-button>
<el-select class="ml10" placeholder="请选择复制" style="width: 140px" @change="copyData"> <el-select class="ml10" placeholder="请选择复制" style="width: 140px" @change="copyData">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
</el-select> </el-select>
@ -113,6 +114,9 @@
<CustomTable :data="rightTableData" :columns="rightColumns" :config="rightTableConfig" :loading="loading" <CustomTable :data="rightTableData" :columns="rightColumns" :config="rightTableConfig" :loading="loading"
@row-click="xmrowHandle" ref="rightTableRef"> @row-click="xmrowHandle" ref="rightTableRef">
<template #jgbz="{ row }">
{{ formatJgbz(row.jgbz) }}
</template>
</CustomTable> </CustomTable>
<div class="mt10" v-if="bottomTableData.length > 0"></div> <div class="mt10" v-if="bottomTableData.length > 0"></div>
@ -144,7 +148,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, toRaw, computed, watch, nextTick, onMounted } from 'vue'; import { ref, reactive, toRaw, computed, watch, nextTick, onMounted } from 'vue';
import CustomTable from '@/components/tableCom/index.vue' import CustomTable from '@/components/elTable/index.vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { reportList, reportPrintPdf, reportResult, reportMedList, reportFsresult } from '@/api/checkCode/index' import { reportList, reportPrintPdf, reportResult, reportMedList, reportFsresult } from '@/api/checkCode/index'
import dayjs from 'dayjs'; import dayjs from 'dayjs';
@ -157,6 +161,9 @@ import { comDict } from '@/utils/dict'
import { usePrintStore } from '@/store/modules/printStore' import { usePrintStore } from '@/store/modules/printStore'
//@ts-ignore //@ts-ignore
import useUserStore from '@/store/modules/user' import useUserStore from '@/store/modules/user'
import { useRoute } from 'vue-router'
const route = useRoute()
const userStore = useUserStore() const userStore = useUserStore()
const compactForm = ref<HTMLElement | null>(null); const compactForm = ref<HTMLElement | null>(null);
@ -176,12 +183,13 @@ interface QueryParams {
alarmflag: boolean, alarmflag: boolean,
jzbz: boolean, jzbz: boolean,
ksdh: string, ksdh: string,
brly: string, brlyname: string,
brxm: string, brxm: string,
brdh: string, brdh: string,
ch: string, ch: string,
dybz: string, dybz: string,
sqh: string, sqh: string,
userid: string
} }
// 提交表单数据 // 提交表单数据
@ -189,7 +197,7 @@ const queryParams = reactive<QueryParams>({
times: ['2025-08-19', '2025-08-19'], times: ['2025-08-19', '2025-08-19'],
// ksdh: '0203', // ksdh: '0203',
ksdh: '0210', ksdh: '0210',
brly: '', brlyname: '',
sqh: '25080109476', sqh: '25080109476',
alarmflag: false, alarmflag: false,
jzbz: false, jzbz: false,
@ -197,7 +205,18 @@ const queryParams = reactive<QueryParams>({
brdh: '', brdh: '',
ch: '', ch: '',
dybz: '', dybz: '',
userid: ''
}); });
const startDate = typeof route.query.startdate === 'string' ? route.query.startdate : '';
const endDate = typeof route.query.endate === 'string' ? route.query.endate : '';
queryParams.times = [startDate, endDate];
queryParams.ksdh = (route.query.deptcode as string) || '';
queryParams.userid = (route.query.userid as string) || '';
queryParams.brdh = (route.query.brdh as string) || '';
console.log('queryParams==>', queryParams);
const single = ref(true); const single = ref(true);
const multiple = ref(true); const multiple = ref(true);
const alarmflag = ref() const alarmflag = ref()
@ -235,22 +254,23 @@ const rows = ref<any[]>([])
// 数据源 // 数据源
const tableData = ref([]) const tableData = ref([])
// 配置项 // 配置项
const columns = ref<ColumnItem[]>([ const columns = ref([
{ prop: 'dybz', label: '打印', align: 'center', visible: true, key: 0, slot: 'dybz', width: '60px' }, { type: 'selection', visible: true, align: 'center', width: 55, label: '多选框' },
{ prop: 'dybz', label: '打印', align: 'center', visible: true, key: 0, slot: 'dybz', width: 60 },
{ prop: 'jzbz', label: '急诊', align: 'center', visible: true, key: 1, slot: 'jzbz', }, { prop: 'jzbz', label: '急诊', align: 'center', visible: true, key: 1, slot: 'jzbz', },
{ prop: 'alarmflag', label: '危急值', align: 'center', visible: true, key: 2, slot: 'alarmflag' }, { prop: 'alarmflag', label: '危急值', align: 'center', visible: true, key: 2, slot: 'alarmflag' },
{ prop: 'jyrq', label: '检验日期', align: 'center', visible: true, key: 3, sortable: true, width: '150px' }, { prop: 'jyrq', label: '检验日期', align: 'center', visible: true, key: 3, sortable: true, width: 150 },
{ prop: 'brdh', label: '病人代号', align: 'center', visible: true, key: 4, width: '110px' }, { prop: 'brdh', label: '病人代号', align: 'center', visible: true, key: 4, width: 110 },
{ prop: 'brxm', label: '病人姓名', align: 'center', visible: true, key: 4, }, { prop: 'brxm', label: '病人姓名', align: 'center', visible: true, key: 4, },
{ prop: 'brxbname', label: '性别', align: 'center', visible: true, key: 11, }, { prop: 'brxbname', label: '性别', align: 'center', visible: true, key: 11, },
{ prop: 'ch', label: '床号', align: 'center', visible: true, key: 5, }, { prop: 'ch', label: '床号', align: 'center', visible: true, key: 5, },
{ prop: 'yqdl', label: '仪器', align: 'center', visible: true, key: 6, width: '110px' }, { prop: 'yqdl', label: '仪器', align: 'center', visible: true, key: 6, width: 110 },
{ prop: 'ybh', label: '样本号', align: 'center', visible: true, key: 7, }, { prop: 'ybh', label: '样本号', align: 'center', visible: true, key: 7, },
{ prop: 'yblxname', label: '样本类型', align: 'center', visible: true, key: 8, }, { prop: 'yblxname', label: '样本类型', align: 'center', visible: true, key: 8, },
{ prop: 'jymd', label: '检验目的', align: 'center', visible: true, key: 9, width: '110px' }, { prop: 'jymd', label: '检验目的', align: 'center', visible: true, key: 9, width: 110 },
{ prop: 'brlyname', label: '病人类型', align: 'center', visible: true, key: 10, }, { prop: 'brlyname', label: '病人类型', align: 'center', visible: true, key: 10, },
{ prop: 'yqmc', label: '仪器名称', align: 'center', visible: true, key: 12, width: '150px' }, { prop: 'yqmc', label: '仪器名称', align: 'center', visible: true, key: 12, width: 150 },
{ prop: 'yljg', label: '医疗机构', align: 'center', visible: true, key: 13, width: '150px' }, { prop: 'yljg', label: '医疗机构', align: 'center', visible: true, key: 13, width: 150 },
]) ])
const selectionChange = (selection: any) => { const selectionChange = (selection: any) => {
@ -287,6 +307,7 @@ const printPdf = () => {
// ] // ]
reportPrintPdf(merge).then((res: any) => { reportPrintPdf(merge).then((res: any) => {
if (res.code == 0) { if (res.code == 0) {
if (!res.data) return ElMessage.warning('未找到打印文件')
classCom.printBase64PDF(res.data) classCom.printBase64PDF(res.data)
// if (printStore.isConnected) { // if (printStore.isConnected) {
// HiprintPrinter.silentPrint([res.data]) // HiprintPrinter.silentPrint([res.data])
@ -311,8 +332,6 @@ const cellStyleHd = ({ row, column, rowIndex, columnIndex }: {
if (column.label == "危急值" && row.alarmflag == "1") { if (column.label == "危急值" && row.alarmflag == "1") {
return { background: '#f00 !important', color: '#fff' }; return { background: '#f00 !important', color: '#fff' };
} }
}; };
// 表格配置 // 表格配置
@ -320,8 +339,6 @@ const tableConfig = ref(
{ {
// stripe: true, // 斑马纹 // stripe: true, // 斑马纹
border: true, // 边框 border: true, // 边框
height: '', // 高度 height: '', // 高度
highlightCurrentRow: true, // 高亮当前行 highlightCurrentRow: true, // 高亮当前行
fit: true, fit: true,
@ -366,11 +383,12 @@ interface ColumnItem {
key: number; key: number;
align?: string; align?: string;
slot?: string; slot?: string;
width?: string; width?: string | number;
sortable?: boolean; sortable?: boolean;
type?: string;
} }
// 更新列 // 更新列
const updateColumns = (arr: Array<ColumnItem>) => { const updateColumns = (arr: any[]) => {
columns.value = arr columns.value = arr
}; };
@ -381,22 +399,65 @@ const rightTableData = ref([])
const rightColumns = ref([ const rightColumns = ref([
{ prop: 'xmdh', label: '项目代号', align: 'center', visible: true, key: 0, }, { prop: 'xmdh', label: '项目代号', align: 'center', visible: true, key: 0, },
{ prop: 'xmmc', label: '项目名称', align: 'center', visible: true, key: 1 }, { prop: 'xmmc', label: '项目名称', align: 'center', visible: true, key: 1 },
{ prop: 'csjg', label: '结果', align: 'center', visible: true, key: 2 }, { prop: 'csjg', label: '检验结果', align: 'center', visible: true, key: 2 },
{ prop: 'refs', label: '参考值', align: 'center', visible: true, key: 3 }, { prop: 'refs', label: '参考值', align: 'center', visible: true, key: 3 },
{ prop: 'dw', label: '单位', align: 'center', visible: true, key: 4 }, { prop: 'dw', label: '单位', align: 'center', visible: true, key: 4 },
{ prop: 'jgbz', label: '结果标志', align: 'center', visible: true, key: 5 }, { prop: 'jgbz', label: '结果标志', align: 'center', visible: true, key: 5, slot: 'jgbz' },
]) ])
const rightCellStyleHd = ({ row, column, rowIndex, columnIndex }: {
row: any;
column: any;
rowIndex: number;
columnIndex: number;
}) => {
if (column.label == "检验结果" && (row.alarm_flag ?? "").trim().length > 0) {
return { background: '#f00 !important', color: '#FFF' };
}
if (column.label == "结果标志" && (row.alarm_flag ?? "").trim().length > 0) {
return { background: '#f00 !important', color: '#FFF' };
}
if (column.label == "结果标志" && row.jgbz == "H") {
return { background: '#ffc0c0 !important', color: '#606266' };
}
if (column.label == "结果标志" && row.jgbz == "L") {
return { background: '#8080ff !important', color: '#fff' };
}
if (column.label == "结果标志" && row.jgbz == "P") {
return { background: '#ffc0c0 !important', color: '#606266' };
}
if (column.label == "结果标志" && row.jgbz == "Q") {
return { background: '#ffff80 !important', color: '#606266' };
}
if (column.label == "检验结果" && row.jgbz == "H") {
return { background: '#ffc0c0 !important', color: '#606266' };
}
if (column.label == "检验结果" && row.jgbz == "L") {
return { background: '#8080ff !important', color: '#fff' };
}
if (column.label == "检验结果" && row.jgbz == "P") {
return { background: '#ffc0c0 !important', color: '#606266' };
}
if (column.label == "检验结果" && row.jgbz == "Q") {
return { background: '#ffff80 !important', color: '#606266' };
}
};
// 表格配置 // 表格配置
const rightTableConfig = ref( const rightTableConfig = ref(
{ {
// stripe: true, // 斑马纹 // stripe: true, // 斑马纹
border: true, // 边框 border: true, // 边框
selection: false, // 多选框
height: '40vh', // 高度 height: '40vh', // 高度
highlightCurrentRow: true, // 高亮当前行 highlightCurrentRow: true, // 高亮当前行
cellStyle: rightCellStyleHd
} }
) )
const formatJgbz = (v: string) => {
return v == 'H' ? '高' : v == 'L' ? '低' : v == 'N' ? '阴性' : v == 'P' ? '阳性' : v == 'Q' ? '弱阳性' : v == 'M' ? '正常' : ''
}
const xmRow = ref<any>({}) const xmRow = ref<any>({})
// 查询抗生素 // 查询抗生素
const xmrowHandle = (row: any) => { const xmrowHandle = (row: any) => {
@ -636,20 +697,32 @@ const getEcharts = (data: any) => {
const bottomTableData = ref([]) const bottomTableData = ref([])
// 配置项 // 配置项
const bottomColumns = ref([ const bottomColumns = ref([
{ prop: 'ywdh', label: '抗生素编号', align: 'center', visible: true, key: 0 }, { prop: 'ywdh', label: '抗生素编号', align: 'center', visible: true, },
{ prop: 'ywmc', label: '抗生素名称', align: 'center', visible: true, key: 1 }, { prop: 'ywmc', label: '抗生素名称', align: 'center', visible: true, },
{ prop: 'csjg', label: '测试结果', align: 'center', visible: true, key: 2 }, { prop: 'csjg', label: '测试结果', align: 'center', visible: true },
{ prop: 'jgbz', label: '结果标志', align: 'center', visible: true, key: 3 }, // { prop: 'jgbz', label: '结果标志', align: 'center', visible: true },
]) ])
const botCellStyleHd = ({ row, column, rowIndex, columnIndex }: {
row: any;
column: any;
rowIndex: number;
columnIndex: number;
}) => {
if (column.label == '测试结果' && row.jgbz == 'R') {
return { background: '#ffc0c0 !important', color: '#606266' };
}
if (column.label == '测试结果' && row.jgbz.trim() == "") {
return { background: '#ffff80 !important', color: '#606266' };
}
}
// 表格配置 // 表格配置
const bottomTableConfig = ref( const bottomTableConfig = ref(
{ {
// stripe: true, // 斑马纹 // stripe: true, // 斑马纹
border: true, // 边框 border: true, // 边框
selection: false, // 多选框
height: '37vh', // 高度 height: '37vh', // 高度
highlightCurrentRow: true, // 高亮当前行 highlightCurrentRow: true, // 高亮当前行
cellStyle: botCellStyleHd
} }
) )
interface DictData { interface DictData {
@ -686,22 +759,27 @@ onMounted(async () => {
const getList = () => { const getList = () => {
if (!queryParams.ksdh) return ElMessage.error('科室代号不能为空'); if (!queryParams.ksdh) return ElMessage.error('科室代号不能为空');
if (!queryParams.userid) return ElMessage.error('用户userid不能为空');
const data = { const data = {
alarmflag: alarmflag.value, alarmflag: alarmflag.value,
jzbz: jzbz.value, jzbz: jzbz.value,
dybz: queryParams.dybz, dybz: queryParams.dybz,
ksdh: queryParams.ksdh, ksdh: queryParams.ksdh,
brly: queryParams.brly, brlyname: queryParams.brlyname,
brxm: queryParams.brxm, brxm: queryParams.brxm,
brdh: queryParams.brdh, brdh: queryParams.brdh,
ch: queryParams.ch, ch: queryParams.ch,
userid: queryParams.userid,
st: '', st: '',
et: '', et: '',
yljg: 1 yljg: 1,
} }
if (queryParams.times && queryParams.times.length) { if (queryParams.times && queryParams.times.length) {
data.st = queryParams.times[0] data.st = queryParams.times[0]
data.et = queryParams.times[1] data.et = queryParams.times[1]
} else {
return ElMessage.error('日期时间段不能为空');
} }
reportList(data).then((res: any) => { reportList(data).then((res: any) => {
if (res.code == 0) { if (res.code == 0) {
@ -734,12 +812,12 @@ function adjustTableHeight() {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.right-table { .compact-form {
// border: 1px solid #dcdfe6; border-bottom: 1px solid #E1E9F7;
} }
.title { .title {
border-bottom: 1px solid #dcdfe6; border-bottom: 1px solid #E1E9F7;
margin-bottom: 10px; margin-bottom: 10px;
padding: 10px; padding: 10px;
font-weight: 700; font-weight: 700;

View File

@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<SelectTable v-model:data="query" :fields="fields" :tableData="tableData" label="name" objKey="id" :border="true" <!-- <SelectTable v-model:data="query" :fields="fields" :tableData="tableData" label="name" objKey="id" :border="true"
:width="'300px'" placeholder="请选择指定项" @getDataValue="getDataValue" /> :width="'300px'" placeholder="请选择指定项" @getDataValue="getDataValue" /> -->
</div> </div>
</template> </template>

View File

@ -19,7 +19,7 @@
<el-input v-model="searchKey" placeholder="搜索(支持名称、编码、简拼)..." class="mb10" clearable @clear="filterDictData" <el-input v-model="searchKey" placeholder="搜索(支持名称、编码、简拼)..." class="mb10" clearable @clear="filterDictData"
@input="filterDictData" /> @input="filterDictData" />
<el-table :data="filteredDictData" height="300px" border @row-click="selectItem" @row-dblclick="selectItem"> <el-table :data="filteredDictData" height="300px" border @row-click="selectItem">
<el-table-column prop="value" label="编码" align="center" width="150" /> <el-table-column prop="value" label="编码" align="center" width="150" />
<el-table-column prop="label" label="名称" align="center" show-overflow-tooltip /> <el-table-column prop="label" label="名称" align="center" show-overflow-tooltip />
<el-table-column prop="pinyin" label="简拼" align="center" width="100" /> <!-- 显示简拼便于调试 --> <el-table-column prop="pinyin" label="简拼" align="center" width="100" /> <!-- 显示简拼便于调试 -->

View File

@ -17,7 +17,7 @@
</el-select> </el-select>
</el-col> </el-col>
<el-col :span="10"> <el-col :span="10">
<el-switch v-model="jzbzSwitch" active-text="急诊" active-color="#FD0101" <el-switch v-model="labPat.jzbz" active-text="急诊" active-color="#FD0101" active-value="1" inactive-value="0"
@change="handleFieldChange"></el-switch> @change="handleFieldChange"></el-switch>
</el-col> </el-col>
</el-form-item> </el-form-item>
@ -95,12 +95,22 @@
size="small" /> size="small" />
</el-form-item> </el-form-item>
<el-form-item label="检验医生"> <el-form-item label="检验医生">
<el-input v-model="labPat.yhdh" placeholder="请输入检验医生" @blur="handleFieldChange" @keyup.enter="handleFieldChange" <!-- <el-input v-model="labPat.yhdh" placeholder="请输入检验医生" @blur="handleFieldChange" @keyup.enter="handleFieldChange"
size="small" /> size="small" /> -->
<el-select v-model="labPat.yhdh" placeholder="请选择" style="width: 100%;" @change="handleFieldChange" filterable
size="small">
<el-option v-for="item in dictData.SRD" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="审核医生"> <el-form-item label="审核医生">
<el-input v-model="labPat.hdys" placeholder="请输入审核医生" @blur="handleFieldChange" @keyup.enter="handleFieldChange" <!-- <el-input v-model="labPat.hdys" placeholder="请输入审核医生" @blur="handleFieldChange" @keyup.enter="handleFieldChange"
size="small" /> size="small" /> -->
<el-select v-model="labPat.hdys" placeholder="请选择" style="width: 100%;" @change="handleFieldChange" filterable
size="small">
<el-option v-for="item in dictData.SRD" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="审核状态"> <el-form-item label="审核状态">
<el-radio-group v-model="labPat.jgbz"> <el-radio-group v-model="labPat.jgbz">
@ -140,8 +150,7 @@ watch(() => props.labPat, (newVal) => {
lastValue.value = JSON.stringify(newVal); lastValue.value = JSON.stringify(newVal);
lastJgbz.value = newVal.jgbz; lastJgbz.value = newVal.jgbz;
}) })
// 计算属性:将布尔值转换为 0/1 绑定到 labPat.jzbz
const jzbzSwitch = ref(0);
const emit = defineEmits(['update:labPat']); const emit = defineEmits(['update:labPat']);
const lastValue = ref(''); const lastValue = ref('');
/** /**
@ -156,8 +165,6 @@ const handleFieldChange = async () => {
const oldObj = JSON.parse(lastValue.value); const oldObj = JSON.parse(lastValue.value);
const newObj = props.labPat; const newObj = props.labPat;
const changedField = getChangedField(oldObj, newObj); const changedField = getChangedField(oldObj, newObj);
console.log('changedField==>', changedField);
console.log('oldObj, newObj==>', oldObj, newObj);
if (changedField) { if (changedField) {
// 这里可以添加实际的更新逻辑,比如调用接口 // 这里可以添加实际的更新逻辑,比如调用接口
try { try {
@ -255,7 +262,7 @@ const resetMain = () => {
brxbLabel: '', brxbLabel: '',
nldw: '', nldw: '',
nldwLabel: '', nldwLabel: '',
jzbz: 0, jzbz: '0',
jgbz: 0 jgbz: 0
}; };
emit('update:labPat', resetData); emit('update:labPat', resetData);

View File

@ -1,144 +1,139 @@
<template> <template>
<div class="table-container"> <div class="table-container">
<vxe-table :data="labPatList" :loading="loading" border height="auto" class="mytable-style" <CommonTable :table-data="labPatList" :loading="loading" :columns="tableColumns" :dict-data="dictData"
:row-config="{ isHover: true, height: 30 }" show-overflow @current-change="handleRowClick" ref="tableRef" :row-config="{ isHover: true, height: 30, keyField: 'ybh' }" @current-change="handleRowClick" size="small"
:current-row="currentRow" highlight-current-row round row-id="ybh"> class="mytable-style" ref="tableRef" :enable-column-drag="true" @column-drag-end="handleColumnDragEnd">
<vxe-column field="finish" title="完成" width="60" align="center"> <!-- 完成状态列 -->
<template #default="scope"> <template #finish="{ row }">
<span>{{ scope.row.finish == 1 ? '✅' : '❌' }}</span> <span>{{ row.finish == 1 ? '✅' : '❌' }}</span>
</template> </template>
</vxe-column> <template #jgbz="{ row }">
<vxe-column field="jgbz" title="审核" width="60" align="center"> <el-checkbox v-model="row.jgbz" true-value="2" disabled />
<template #default="scope"> </template>
<el-checkbox v-model="scope.row.jgbz" true-value="2" disabled /> <template #alarmflag="{ row }">
</template> <el-checkbox :model-value="row.alarmflag == '1'" disabled />
</vxe-column> </template>
<vxe-column field="alarmflag" title="报警" width="60" align="center">
<template #default="scope">
<el-checkbox :model-value="scope.row.alarmflag == '1'" disabled />
</template>
</vxe-column>
<vxe-column field="brly" title="类型" width="60" align="center">
<template #default="scope">
{{ formatDict(scope.row.brly, 'PT') }}
</template>
</vxe-column>
<vxe-column field="autojgbz" title="自审" width="60" align="center">
<template #default="scope">
<el-checkbox :model-value="scope.row.autojgbz === '1'" disabled>
</el-checkbox>
</template>
</vxe-column>
<vxe-column field="ybh" title="样本号" width="120" align="center" />
<vxe-column field="brxm" title="病人姓名" width="120" align="center" />
<vxe-column field="brdh" title="病历号" width="120" align="center" />
<vxe-column field="ch" title="床号" width="60" align="center" />
<vxe-column field="brxb" title="病人性别" width="100" align="center" />
<vxe-column field="nl" title="年" width="60" align="center" />
<vxe-column field="nldw" title="龄" width="60" align="center" />
<vxe-column field="ksdh" title="科室" width="60" align="center" />
<vxe-column field="yblx" title="标本" width="60" align="center" />
<vxe-column field="dybz" title="打印" width="60" show-overflow align="center">
<template #default="scope">
<el-checkbox :model-value="scope.row.dybz === '1'" disabled>
</el-checkbox>
</template>
</vxe-column>
<vxe-column field="fslx" title="发送" width="60" align="center">
<template #default="scope">
<el-checkbox :model-value="scope.row.dybz === '1'" disabled>
</el-checkbox>
</template>
</vxe-column>
<vxe-column field="shcs" title="次数" show-overflow width="60" align="center" />
<vxe-column field="sqh" title="申请号/条码" width="150" show-overflow align="center" />
<vxe-column field="jymd" title="检验目的" show-overflow width="120" align="center" />
<vxe-column field="yhdh" title="检验医生" show-overflow width="120" align="center" />
<vxe-column field="yljg" title="送检医院" show-overflow width="120" align="center" />
</vxe-table> <template #brly="{ row }">
{{ formatDict(row.brly, 'PT') }}
</template>
<template #brxb="{ row }">
{{ formatDict(row.brxb, 'SX') }}
</template>
<template #nldw="{ row }">
{{ formatDict(row.nldw, 'AU') }}
</template>
<template #autojgbz="{ row }">
<el-checkbox :model-value="row.autojgbz === '1'" disabled />
</template>
<template #dybz="{ row }">
<el-checkbox :model-value="row.dybz === '1'" disabled />
</template>
<template #fslx="{ row }">
<el-checkbox :model-value="row.dybz === '1'" disabled />
</template>
<template #yljg="{ row }">
{{ formatDict(row.yljg, 'HOS') }}
</template>
</CommonTable>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, nextTick } from 'vue' import { ref, nextTick } from 'vue'
import CommonTable from '@/components/vxeTable/index.vue'
const props = defineProps({ const props = defineProps({
labPatList: { labPatList: {
type: Array, type: Array,
default: () => [] default: () => []
}, },
total: {
type: Number,
default: 0
},
loading: { loading: {
type: Boolean, type: Boolean,
default: true default: true
}, },
dictData: { dictData: {
type: Object, type: Object,
default: () => { } default: () => ({})
} }
}) })
const tableRef = ref<any>(); const emits = defineEmits(['select'])
const emits = defineEmits(['select', 'search',])
const currentRow = ref<any>(null); // 表格列配置
const handleRowClick = ({ row }: { row: any }) => { const tableColumns = ref([
{ field: 'finish', title: '完成', width: 60, align: 'center', slotName: 'finish' },
{ field: 'jgbz', title: '审核', width: 60, align: 'center', slotName: 'jgbz' },
{ field: 'alarmflag', title: '报警', width: 60, align: 'center', slotName: 'alarmflag' },
{ field: 'brly', title: '类型', width: 60, align: 'center', slotName: 'brly' },
{ field: 'autojgbz', title: '自审', width: 60, align: 'center', slotName: 'autojgbz' },
{ field: 'ybh', title: '样本号', width: 100, align: 'center' },
{ field: 'brxm', title: '病人姓名', width: 100, align: 'center' },
{ field: 'brdh', title: '病历号', width: 120, align: 'center' },
{ field: 'ch', title: '床号', width: 60, align: 'center' },
{ field: 'brxb', title: '病人性别', width: 100, align: 'center', slotName: 'brxb' },
{ field: 'nl', title: '年', width: 60, align: 'center' },
{ field: 'nldw', title: '龄', width: 60, align: 'center', slotName: 'nldw' },
{ field: 'ksdh', title: '科室', width: 60, align: 'center' },
{ field: 'yblx', title: '标本', width: 60, align: 'center' },
{ field: 'dybz', title: '打印', width: 60, align: 'center', slotName: 'dybz' },
{ field: 'fslx', title: '发送', width: 60, align: 'center', slotName: 'fslx' },
{ field: 'shcs', title: '次数', width: 60, align: 'center' },
{ field: 'sqh', title: '申请号/条码', width: 150, align: 'center' },
{ field: 'jymd', title: '检验目的', width: 120, align: 'center' },
{ field: 'yhdh', title: '检验医生', width: 120, align: 'center', },
{ field: 'yljg', title: '送检医院', width: 120, align: 'center', slotName: 'yljg' }
])
// 更新列配置
const handleColumnDragEnd = (data: any) => {
// 先清空再赋值,强制触发重新渲染
tableColumns.value = [];
// 使用nextTick确保DOM更新后再设置新值
nextTick(() => {
tableColumns.value = [...data.columns];
});
}
const handleRowClick = (row: any) => {
emits('select', row) emits('select', row)
} }
const tableRef = ref()
const setCurrentRow = (row: any) => { const setCurrentRow = (row: any) => {
tableRef.value.setCurrentRow(row) tableRef.value.setCurrentRow(row)
}
nextTick(() => { // 引入公共组件的字典格式化方法
tableRef.value.scrollToRow(row) const formatDict = (v: string, dictType: string) => {
}) return props.dictData[dictType]?.find((item: any) => item.value == v)?.label
} }
// 暴露公共方法
// 字典格式化方法
const formatDict = (v: string, dictType: string) => {
return props.dictData[dictType]?.find((item: any) => item.value == v)?.label;
};
// 导出方法
defineExpose({ defineExpose({
setCurrentRow, setCurrentRow,
tableRef, tableRef,
}); })
</script> </script>
<style scoped lang="scss"> <style lang="scss" scoped>
.table-container { .table-container {
height: calc(90vh - 250px); height: calc(90vh - 250px);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.vxe-table--border tbody tr,
.vxe-table--border td,
.vxe-table--border th {
border-color: #f00 !important;
/* 设置边框颜色为红色 */
}
/* 2. 表头区域边框 */
::v-deep .vxe-header--row th {
border-color: #1F6DD3 !important;
}
/* 3. 内容区域边框 */
::v-deep .vxe-body--row td {
border-color: #409eff !important;
}
.mytable-style { .mytable-style {
flex: 1; flex: 1;
} }
.common-table {
flex: 1;
border-color: #e5e7eb;
}
</style> </style>

View File

@ -1,193 +0,0 @@
<template>
<div class="table-container">
<el-table :data="labPatList" class="card-content" :cell-style="cellStyle" @row-click="handleRowClick" border
height="100%" highlight-current-row ref="tableRef" v-loading="loading" :row-style="{ height: '30px' }"
:row-key="(row: any) => row.ybh">
<el-table-column prop="finish" label="完成" align="center" width="60px">
<template #default="scope">
<span>{{ scope.row.finish === 1 ? '✅' : '❌' }}</span>
</template>
</el-table-column>
<el-table-column prop="jgbz" label="审核" align="center" width="60px">
<template #default="scope">
<el-checkbox v-model="scope.row.jgbz" true-value="2" disabled />
</template>
</el-table-column>
<el-table-column prop="alarmflag" label="报警" align="center" width="60px">
<template #default="scope">
<el-checkbox :model-value="scope.row.alarmflag == '1'" disabled />
</template>
</el-table-column>
<el-table-column prop="brly" label="类型" align="center" width="60px">
<template #default="scope">
{{ formatDict(scope.row.brly, 'PT') }}
</template>
</el-table-column>
<el-table-column prop="autojgbz" label="自审" align="center" width="60px">
<template #default="scope">
<el-checkbox :model-value="scope.row.autojgbz === '1'" disabled>
</el-checkbox>
</template>
</el-table-column>
<el-table-column prop="ybh" label="样本号" align="center" />
<el-table-column prop="brxm" label="病人姓名" align="center" />
<el-table-column prop="brdh" label="病历号" align="center" width="120" />
<el-table-column prop="ch" label="床号" align="center" />
<el-table-column prop="brxb" label="病人性别" align="center" />
<el-table-column prop="nl" label="年" align="center" />
<el-table-column prop="nldw" label="龄" align="center" />
<el-table-column prop="ksdh" label="科室" align="center" />
<el-table-column prop="yblx" label="标本" align="center" />
<el-table-column prop="dybz" label="打印" align="center" show-overflow-tooltip>
<template #default="scope">
<el-checkbox :model-value="scope.row.dybz === '1'" disabled>
</el-checkbox>
</template>
</el-table-column>
<el-table-column prop="fslx" label="发送" align="center">
<template #default="scope">
<el-checkbox :model-value="scope.row.dybz === '1'" disabled>
</el-checkbox>
</template>
</el-table-column>
<el-table-column prop="shcs" label="次数" align="center" show-overflow-tooltip />
<el-table-column prop="sqh" label="申请号/条码" width="150" show-overflow-tooltip />
<el-table-column prop="jymd" label="检验目的" show-overflow-tooltip align="center" width="120px" />
<el-table-column prop="yhdh" label="检验医生" align="center" show-overflow-tooltip />
<el-table-column prop="yljg" label="送检医院" align="center" show-overflow-tooltip />
</el-table>
<el-pagination class="mt10 page-box" background layout="total, sizes, prev, pager, next, jumper" :total="total"
:page-sizes="[10, 20, 30, 50]" v-model:current-page="currentPage" v-model:page-size="pageSize"
@size-change="handleSizeChange" @current-change="handleCurrentChange">
</el-pagination>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, nextTick } from 'vue'
const props = defineProps({
labPatList: {
type: Array,
default: () => []
},
total: {
type: Number,
default: 0
},
loading: {
type: Boolean,
default: true
},
dictData: {
type: Object,
default: () => { }
}
})
const tableRef = ref()
const emits = defineEmits(['select', 'search', 'page-change'])
const pageSize = ref(50)
const currentPage = ref(1)
const searchText = ref('')
const setCurrentRow = (index: number, row: any) => {
tableRef.value.setCurrentRow(row)
nextTick(() => {
tableRef.value.setScrollTop(32 * index)
})
}
const doLayout = () => {
tableRef.value?.doLayout();
};
const handleSizeChange = (val: number) => {
pageSize.value = val
emits('page-change', currentPage.value, pageSize.value)
}
const handleCurrentChange = (val: number) => {
currentPage.value = val
emits('page-change', currentPage.value, pageSize.value)
}
// 字典格式化方法
const formatDict = (v: string, dictType: string) => {
return props.dictData[dictType]?.find((item: any) => item.value == v)?.label;
};
// 导出方法
defineExpose({
setCurrentRow,
doLayout,
tableRef,
});
const search = () => {
// emits('search', searchText.value, currentPage.value, pageSize.value)
}
const handleRowClick = (row: any) => {
emits('select', row)
}
onMounted(() => {
})
//设置内容格式
const cellStyle = ({ row, column }: { row: any, column: any }) => {
// console.log('检查单元格样式:', row, column); // 调试输出
// 使用 === 比较时注意值的类型(数字 vs 字符串)
if (column.property === 'finish' && row.status === '1') {
return {
backgroundColor: '#006400', // 使用驼峰式写法(可选)
fontWeight: 'bold',
color: 'white', // 添加文字颜色,确保可读性
height: '25px',
lineHeight: '25px'
};
}
if (column.property === 'jgbz' && row.status === '2') {
return {
backgroundColor: '#FF69B4',
fontWeight: 'bold',
height: '25px',
lineHeight: '25px'
};
}
if (column.property === 'alarmflag' && row.status === '1') {
return {
backgroundColor: '#FF0000',
fontWeight: 'bold',
color: 'white',
height: '25px',
lineHeight: '25px'
};
}
return {
height: '25px',
lineHeight: '25px',
padding: '0 0px'
}; // 默认不设置样式
};
</script>
<style scoped lang="scss">
.table-container {
height: calc(90vh - 250px);
display: flex;
flex-direction: column;
}
.card-content {
flex: 1;
}
.page-box {
height: 32px;
}
</style>

View File

@ -438,7 +438,6 @@ const filteredList = ref([]);
const originalData = ref(JSON.parse(JSON.stringify(props.tableData))); const originalData = ref(JSON.parse(JSON.stringify(props.tableData)));
const isEnterHandled = ref(false); const isEnterHandled = ref(false);
const originalCsjgMap = ref({}); const originalCsjgMap = ref({});
const isSaving = ref({}); // 用于防止重复提交的标记
// 组件挂载时初始化缓存 // 组件挂载时初始化缓存
onMounted(() => { onMounted(() => {
@ -463,8 +462,7 @@ const updateOriginalCsjgMap = () => {
* 获取行的唯一标识 * 获取行的唯一标识
*/ */
const getRowUniqueKey = (row) => { const getRowUniqueKey = (row) => {
// 优先使用id,没有则使用xmdh确保唯一性 return row.xmdh;
return row.id || row.xmdh;
}; };
@ -472,16 +470,52 @@ const getRowUniqueKey = (row) => {
/** /**
* csjg输入框回车触发保存 * csjg输入框回车触发保存
*/ */
const handleCsjgEnter = async (row) => { const handleCsjgEnter = async (row) => {
// 获取当前输入值
const currentCsjg = row.csjg ? String(row.csjg).trim() : "";
// 获取原始缓存值
const uniqueKey = getRowUniqueKey(row);
const originalCsjg = originalCsjgMap.value[uniqueKey] || "";
// 判断值是否改变
if (currentCsjg === originalCsjg) return;
// 值已改变,执行保存逻辑
await saveCsjgChange(row); await saveCsjgChange(row);
nextTick(() => { nextTick(() => {
const input = document.activeElement; const input = document.activeElement;
if (input.tagName === "INPUT") input.blur(); if (input.tagName === "INPUT") input.blur();
}); });
}; };
/**
* 核心:保存csjg修改(调用API + 失败回滚)
*/
const saveCsjgChange = async (row) => {
const requestParams = {
...row,
};
if (row.id) {
newresult(requestParams).then(response => {
ElMessage.success("结果保存成功");
emits('fetchLabResults');
}).catch(error => {
emits('fetchLabResults');
});
} else {
changeresult(requestParams).then(response => {
ElMessage.success("结果保存成功");
emits('fetchLabResults');
}).catch(error => {
emits('fetchLabResults');
});
}
};
/** /**
* 处理选择变化 * 处理选择变化
*/ */
@ -562,73 +596,10 @@ const addRowFromDict = async (rowData) => {
// if (lastInput) lastInput.focus(); // if (lastInput) lastInput.focus();
}); });
console.log(`成功新增项目行:`, newRow);
return true; return true;
}; };
/**
* 核心:保存csjg修改(调用API + 失败回滚)
*/
const saveCsjgChange = async (row) => {
const uniqueKey = getRowUniqueKey(row);
// 防止重复提交
// if (isSaving.value[uniqueKey]) return;
const oldCsjg = originalCsjgMap.value[uniqueKey] || "";
let newCsjg = row.csjg || "";
// 标准化处理
newCsjg = String(newCsjg).trim();
// 调试日志
console.log(`
行${uniqueKey} 比较:
缓存旧值:"${oldCsjg}"(类型:${typeof oldCsjg})
当前新值:"${newCsjg}"(类型:${typeof newCsjg})
是否相等:${oldCsjg === newCsjg}
`);
// 无变化或只读状态,直接返回
if (oldCsjg === newCsjg || readonly.value) {
console.log("值未变化,无需保存");
return;
}
// 设置提交中标记
// isSaving.value[uniqueKey] = true;
const requestParams = {
...row,
csjg: newCsjg
};
console.log('提交参数:', requestParams);
if (row.id) {
newresult(requestParams).then(response => {
originalCsjgMap.value[uniqueKey] = newCsjg;
ElMessage.success("结果保存成功");
emits('fetchLabResults');
}).catch(error => {
emits('fetchLabResults');
// 清除提交中标记
// isSaving.value[uniqueKey] = false;
});
} else {
changeresult(requestParams).then(response => {
originalCsjgMap.value[uniqueKey] = newCsjg;
ElMessage.success("结果保存成功");
emits('fetchLabResults');
}).catch(error => {
emits('fetchLabResults');
// 清除提交中标记
// isSaving.value[uniqueKey] = false;
});
}
};
/** /**
* 保存数据 * 保存数据
@ -709,23 +680,17 @@ const previewHandle = () => {
const getRowIndex = (index) => { const getRowIndex = (index) => {
return index + 1; return index + 1;
}; };
// 子组件(labresult.vue):修改缓存初始化逻辑,监听tableData非空后再执行
onMounted(() => { onMounted(() => {
// 若初始tableData为空,等待父组件数据加载后再初始化缓存
if (props.tableData.length > 0) { if (props.tableData.length > 0) {
updateOriginalCsjgMap(); updateOriginalCsjgMap();
} }
}); });
// 子组件(labresult.vue):修改watch逻辑
// 增强watch:当tableData从空变为非空时,初始化缓存
watch( watch(
() => props.tableData.length, () => props.tableData,
(newLength, oldLength) => { () => {
// 只有当tableData从空(0)变为有数据(>0)时,才初始化缓存 updateOriginalCsjgMap();
if (oldLength === 0 && newLength > 0) {
updateOriginalCsjgMap();
console.log("子组件:父组件数据加载完成,初始化缓存");
}
} }
); );

View File

@ -144,9 +144,9 @@ const queryParams = ref({
pageNum: 1, pageNum: 1,
pageSize: 2000, pageSize: 2000,
jyrq: '2025-08-19', jyrq: '2025-08-19',
yq: '49', yq: '46',
ybh: '1', ybh: '1',
instrGroup: '01', instrGroup: '02',
problemId: 0, problemId: 0,
days: 1, days: 1,
}) })
@ -170,7 +170,7 @@ const labPat = ref<any>(
yq: '', yq: '',
ybh: '', ybh: '',
brly: '', brly: '',
jzbz: '', jzbz: '0',
brdh: '', brdh: '',
brxm: '', brxm: '',
brxb: '', brxb: '',
@ -228,8 +228,8 @@ const instrGroupFields = ref([
const loadinstrGroupOptions = () => { const loadinstrGroupOptions = () => {
getComDicts({ zdlb: 'GROUP' }).then((res: any) => { getComDicts({ zdlb: 'GROUP' }).then((res: any) => {
instrGroupOptions.value = res.data instrGroupOptions.value = res.data
queryParams.value.instrGroup = '01' queryParams.value.instrGroup = '02'
queryParams.value.yq = '49' queryParams.value.yq = '46'
getYqConfig() getYqConfig()
}); });
} }
@ -381,6 +381,7 @@ interface DictData {
DP?: Array<any>; DP?: Array<any>;
BT?: Array<any>; BT?: Array<any>;
SRD?: Array<any>; SRD?: Array<any>;
HOS?: Array<any>;
[key: string]: any[] | undefined; // 添加索引签名以支持动态访问 [key: string]: any[] | undefined; // 添加索引签名以支持动态访问
} }
// 字典数据存储 // 字典数据存储
@ -388,7 +389,7 @@ const dictData = ref<DictData>({});
onMounted(async () => { onMounted(async () => {
// 加载病人来源字典 // 加载病人来源字典
const dictRefs = await comDict('PT', 'AU', 'SX', 'DP', 'BT', 'SRD'); const dictRefs = await comDict('PT', 'AU', 'SX', 'DP', 'BT', 'SRD', 'HOS');
// 从 ref 中获取实际数据 // 从 ref 中获取实际数据
dictData.value = { dictData.value = {
@ -398,6 +399,7 @@ onMounted(async () => {
DP: toRaw(dictRefs.DP.value) || [], DP: toRaw(dictRefs.DP.value) || [],
BT: toRaw(dictRefs.BT.value) || [], BT: toRaw(dictRefs.BT.value) || [],
SRD: toRaw(dictRefs.SRD.value) || [], SRD: toRaw(dictRefs.SRD.value) || [],
HOS: toRaw(dictRefs.HOS.value) || [],
}; };
@ -486,7 +488,6 @@ onMounted(async () => {
text-align: center; text-align: center;
} }
.text1 {}
.text2 { .text2 {
color: #1F33FF; color: #1F33FF;

View File

@ -66,9 +66,20 @@ export default defineConfig(({
} }
}] }]
} }
} },
} // 新增build配置,用于生产环境移除console
optimizeDeps: { build: {
include: ['jquery', 'select2', 'vue3-select2-component'] // 只有生产环境才移除console
minify: VITE_APP_ENV === 'production' ? 'esbuild' : 'terser',
esbuild: {
// 生产环境下移除console和debugger
drop: VITE_APP_ENV === 'production' ? ['console', 'debugger'] : []
}
},
optimizeDeps: {
// include: ['jquery', 'select2', 'vue3-select2-component'],
// exclude: ['sortablejs'] // 跳过 Vite 对 SortableJS 的预构建
},
} }
}) })