批量打印

This commit is contained in:
wyuu 2026-07-03 18:03:45 +08:00
parent 880c4a0ba9
commit 3eb9a9d9f1
58 changed files with 912 additions and 461 deletions

View File

@ -36,3 +36,21 @@ export function queryBatchCheckDetailService(query: any) {
params: query,
});
}
// 批量打印查询
export function queryBatchPrintService(query: any) {
return request({
url: "/batchPrint/queryList",
method: "post",
data: query,
});
}
// 批量打印数据
export function batchPrintAll(query: any) {
return request({
url: "/batchPrint/printAll",
method: "post",
data: query,
});
}

View File

@ -3,44 +3,53 @@
import request from '@/utils/request'
// 查询字典列表
export function liststatstemp(params:any) {
return request({
url: '/statstemp/list',
method: 'get',
params
})
export function liststatstemp(params: any) {
return request({
url: '/statstemp/list',
method: 'get',
params
})
}
// 复制模板
export function copyParameter(params: any) {
return request({
url: '/statstemp/param/copyparameter',
method: 'get',
params
})
}
// 查询字典详细
export function getstatstemp(id:number) {
return request({
url: `/statstemp/${id}`,
method: 'get'
})
export function getstatstemp(id: number) {
return request({
url: `/statstemp/${id}`,
method: 'get'
})
}
// 新增字典
export function addstatstemp(params:any) {
return request({
url: '/statstemp',
method: 'post',
data:params
})
export function addstatstemp(params: any) {
return request({
url: '/statstemp',
method: 'post',
data: params
})
}
// 修改字典
export function updatestatstemp(params:any) {
return request({
url: '/statstemp',
method: 'put',
data:params
})
export function updatestatstemp(params: any) {
return request({
url: '/statstemp',
method: 'put',
data: params
})
}
// 删除字典
export function delstatstemp(id:any) {
return request({
url: `/statstemp/${id}`,
method: 'delete'
})
export function delstatstemp(id: any) {
return request({
url: `/statstemp/${id}`,
method: 'delete'
})
}

View File

@ -394,4 +394,79 @@ aside {
.el-form-item {
margin-bottom: 10px;
}
}
.bb_table {
.vxe-table.border--full {
border: 1px solid #ccc !important;
.vxe-header--column,
.vxe-body--column,
.vxe-footer--column {
border-right: 1px solid #ccc !important;
border-bottom: 1px solid #ccc !important;
height: 30px;
line-height: 30px;
padding: 0 !important;
background-image: none !important;
}
.vxe-footer--column {
border-bottom: none !important;
}
/* 表头最下方单元格强制底红线 */
.vxe-header--row:last-of-type .vxe-header--column {
border-bottom: 1px solid #ccc !important;
}
.vxe-body--row {
border-bottom: 1px solid #ccc !important;
}
.vxe-footer--row.vxe-footer--row {
border-top: 1px solid #ccc !important;
}
.vxe-header--row th {
height: 30px !important;
line-height: 30px;
padding: 0 !important;
}
.vxe-body--row td {
height: 30px !important;
line-height: 30px;
padding: 0 !important;
}
.vxe-footer--row td {
height: 30px !important;
line-height: 30px;
font-size: 13px;
font-weight: 700;
padding: 0 !important;
}
/* 清除最后一列重复竖线,避免双线重叠 */
.vxe-header--col:last-child .vxe-header--column,
.vxe-body--col:last-child .vxe-body--column,
.vxe-footer--col:last-child .vxe-footer--column {
border-right: none !important;
}
}
.vxe-table--render-default .vxe-table--footer-wrapper {
border-top: 1px solid #ccc !important;
}
.vxe-table--header-wrapper {
border-bottom: 1px solid #ccc !important;
background-color: #eff6fa !important;
}
}

View File

@ -340,16 +340,17 @@
.vxe-table {
border: 1px solid #96B8D9 !important;
border-top: none !important;
/* 蓝色外边框 */
border-radius: .5rem;
/* 可选:添加边框圆角 */
overflow: hidden;
}
.mytable-style {
.vxe-table {
border: 1px solid #96B8D9 !important;
border-top: none !important;
/* 蓝色外边框 */
border-radius: .5rem;
/* 可选:添加边框圆角 */
overflow: hidden;
}
.vxe-header--column {
word-break: break-word;
@ -465,7 +466,7 @@
/** 表格布局 **/
.pagination-container {
position: relative;
height: 25px;
height: 50px;
margin-bottom: 10px;
margin-top: 15px;
padding: 10px 20px !important;

View File

@ -55,7 +55,6 @@
import { reactive, ref, onMounted, watch, nextTick, toRaw } from "vue";
import { getFirstLetter } from '@/utils/pinyin';
import { ElEmpty } from 'element-plus';
// @ts-ignore
import { comDict } from '@/utils/dict'
import { getoptionselect } from '@/api/liswork/xtwh/localconfigApi'
import { Emits, Props } from '@/types';

View File

@ -1,7 +1,6 @@
//仪器,字典数据自动格式化类
import { DictData } from "@/types/index";
import { getGroupInstrdList } from "@/api/liswork/work/LisWork";
//@ts-ignore
import { comDict } from "@/utils/dict";
const dictData = ref<DictData>({});
@ -19,16 +18,30 @@ export const getYqData = (data?: any) => {
}
});
};
//'XMGL','ITEMCLASS', 'YQDL'
// 正在请求中的字典标记,防止并发重复调用
const pendingDict = new Set<string>()
export const getDictData = async (...args: string[]) => {
const dictRefs = await comDict(...args);
// 遍历传入的字典类型参数,动态处理赋值
args.forEach((key) => {
if (dictRefs[key] !== undefined) {
dictData.value[key] = toRaw(dictRefs[key].value) || [];
}
});
};
// 过滤:无缓存 且 当前没有正在请求
const needReqKeys = args.filter(key => !(key in dictData.value) && !pendingDict.has(key))
if (needReqKeys.length === 0) return
// 标记开始请求
needReqKeys.forEach(k => pendingDict.add(k))
try {
const dictRefs = await comDict(...needReqKeys)
needReqKeys.forEach((key) => {
if (dictRefs[key] !== undefined) {
dictData.value[key] = toRaw(dictRefs[key].value) || []
}
})
} finally {
// 请求结束无论成功失败都清除标记
needReqKeys.forEach(k => pendingDict.delete(k))
}
}
//字典数据格式化方法
export const formatDict = (v: string, dictType: string) => {

View File

@ -167,8 +167,8 @@
import { ref, reactive, toRaw, computed, watch, nextTick, onMounted, } from 'vue';
import { HiprintPrinter } from '@/utils/hiprintPrinter';
import { classCom } from '@/utils/classCom';
import CustomTable from '@/components/elTable/index.vue'
import CustomVxeTable from '@/components/vxeTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import CustomVxeTable from '@/components/VxeTable/index.vue'
import { useRouter, useRoute } from 'vue-router'
import { usePrintStore } from '@/store/modules/printStore'
import { checkPrintService, downloadPrintSetup } from '@/utils/printHelper'

View File

@ -189,8 +189,8 @@
<script setup lang="ts">
import { ref, reactive, toRaw, computed, watch, nextTick, onMounted } from 'vue';
import CustomTable from '@/components/elTable/index.vue'
import CustomVxeTable from '@/components/vxeTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import CustomVxeTable from '@/components/VxeTable/index.vue'
import { useRouter } from 'vue-router'
import ContextMenu from "@/components/contextMenu/index.vue";
import { reportList, reportPrintPdf, reportResult, reportMedList, reportFsresult, getSQDDetailList, getCdssUrl } from '@/api/checkCode/index'

View File

@ -196,8 +196,8 @@
<script setup lang="ts" name="ReportQuery">
import { ref, reactive, toRaw, computed, watch, nextTick, onMounted } from 'vue';
import CustomTable from '@/components/elTable/index.vue'
import CustomVxeTable from '@/components/vxeTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import CustomVxeTable from '@/components/VxeTable/index.vue'
import { reportList, reportPrintPdf, reportResult, reportMedList, reportFsresult } from '@/api/checkCode/index'
import dayjs from 'dayjs';
import SelectTable from '@/components/SelectTable/index.vue';

View File

@ -11,10 +11,11 @@
<div class="box-shadow">
<el-row class="top-box">
<el-col :span="8" class="col_box">
<el-button type="success" :size="aotuSize" :loading="saveLoading" @click="saveHandle">保存</el-button>
<el-button type="primary" :size="aotuSize" @click="addHandle">新增</el-button>
<el-button type="warning" :size="aotuSize" :loading="printLoading" @click="printHandle">打印</el-button>
<el-button type="danger" :size="aotuSize" @click="deleteHandle">作废</el-button>
<el-button type="success" :size="aotuSize" :loading="saveLoading" plain @click="saveHandle">保存</el-button>
<el-button type="primary" :size="aotuSize" @click="addHandle" plain>新增</el-button>
<el-button type="warning" :size="aotuSize" :loading="printLoading" plain
@click="printHandle">打印</el-button>
<el-button type="danger" :size="aotuSize" plain @click="deleteHandle">作废</el-button>
</el-col>
<el-col :span="16">
<div class="tips">

View File

@ -7,7 +7,7 @@
</template>
<script setup lang="ts">
import { queryBatchCheckDetailService } from '@/api/liswork/batchCheck/batchCheckApi'
import { queryBatchCheckDetailService } from '@/api/liswork/batch'
const tableData = ref([])
const columns = ref([

View File

@ -15,7 +15,7 @@
</template>
<script setup lang="ts">
import { queryBatchCheckDetailService } from '@/api/liswork/batchCheck/batchCheckApi'
import { queryBatchCheckDetailService } from '@/api/liswork/batch'
const tableDataUp = ref([])

View File

@ -123,9 +123,9 @@
</template>
<script setup lang="ts" name="BatchCheck">
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import SelectTable from '@/components/SelectTable/index.vue';
import { batchCheckService, queryBatchCheckListService, cancelBatchCheckService } from '@/api/liswork/batchCheck/batchCheckApi';
import { batchCheckService, queryBatchCheckListService, cancelBatchCheckService } from '@/api/liswork/batch/index.js';
import dayjs from 'dayjs';
import { formatDict, getDictData } from '@/hooks'
import { displayBRNL, displayBRXB } from '@/utils/czUtil/lisUtil'

View File

@ -12,38 +12,38 @@
</el-col>
<el-col :span="8">
<el-form-item label="组别:">
<SelectTable v-model:data="queryForm.instrGroup" :tableData="instrGroupOptions" placeholder=""
@getDataValue="handleinstrGroupChange" :clearable="false" />
<SelectTable v-model:data="queryForm.yqz" :tableData="instrGroupOptions" placeholder=""
@getDataValue="handleinstrGroupChange" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="检验仪器:">
<SelectTable v-model:data="queryForm.yq" :tableData="instrOptions" label="yqmc" value="yq" objKey="yq"
placeholder="" :clearable="false" @getDataValue="" />
<SelectTable v-model:data="queryForm.yq" :tableData="instrOptions" clearable placeholder=""
@getDataValue="" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="样本号:">
<el-input v-model="queryForm.ybh" placeholder="请输入样本号" clearable />
<el-form-item label="标本号:">
<el-input v-model="queryForm.ybh" placeholder="可以输入如:1,2,5-6等格式" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="病人类型:">
<SelectTable v-model:data="queryForm.brly" dictType="PT" placeholder="" />
<SelectTable v-model:data="queryForm.brly" :tableData="dictData.PT" placeholder="" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="科室:">
<SelectTable v-model:data="queryForm.ksdh" dictType="DP" placeholder="" />
<SelectTable v-model:data="queryForm.ksdh" :tableData="dictData.DP" placeholder="" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-form-item label="打印顺序:" class="print-order-item">
<el-radio-group v-model="queryForm.printOrder">
<el-radio-group v-model="queryForm.sorttype">
<el-radio v-for="order in printOrders" :key="order.value" :label="order.value">
{{ order.label }}
</el-radio>
@ -52,100 +52,130 @@
</el-row>
</el-form>
<div>
<el-button type="primary" icon="search" @click="printHandle">查询</el-button>
<el-button type="warning" icon="Printer" plain @click="printHandle">打印</el-button>
<el-button type="primary" icon="search" @click="searchHandle">查询</el-button>
<el-button type="warning" icon="Printer" :loading="printLoading" plain @click="printHandle">打印</el-button>
</div>
</el-col>
<el-col :span="8" class="top-right-col">
<div class="option-panel">
<div class="option-title">过滤选项</div>
<el-checkbox-group v-model="selectedOptions" @change="updateSelectedOptions">
<el-row :gutter="12" class="option-list">
<el-col :span="12" v-for="option in optionItems" :key="option.key">
<el-checkbox :label="option.key">{{ option.label }}</el-checkbox>
</el-col>
</el-row>
</el-checkbox-group>
<el-row :gutter="12" class="option-list">
<el-col :span="12" v-for="option in optionItems">
<el-checkbox v-model="queryForm[option.key]" :label="option.label" :true-value="1" :false-value="0"
:disabled="option.disabled" />
</el-col>
</el-row>
</div>
</el-col>
</el-row>
<div class="bottom-card mt10">
<div class="table-section">
<el-table :data="tableData" border style="width: 100%" height="60vh">
<el-table-column label="样本号" prop="ybh" width="120" />
<el-table-column label="病人姓名" prop="brxm" width="120" />
<el-table-column label="病人类型" prop="brly" width="120" />
<el-table-column label="科室" prop="ksmc" width="120" />
<el-table-column label="床号" prop="ch" width="120" />
<el-table-column label="消息提示" prop="msg" />
</el-table>
</div>
<el-table :data="tableData" border style="width: 100%" height="100%" v-loading="loading">
<el-table-column label="样本号" prop="ybh" width="120" align="center" />
<el-table-column label="病人姓名" prop="brxm" width="120" align="center" />
<el-table-column label="病人类型" prop="brly" width="120" align="center">
<template #default="scope">
{{ formatDict(scope.row.brly, 'PT') }}
</template>
</el-table-column>
<el-table-column label="科室" prop="ksdh" width="200" align="center">
<template #default="scope">
{{ formatDict(scope.row.ksdh, 'DP') }}
</template>
</el-table-column>
<el-table-column label="床号" prop="ch" width="120" />
<el-table-column label="消息提示" prop="cp_msg">
<template #default="scope">
<span v-if="scope.row.flag == 0" style="color:#f00"> {{ scope.row.cp_msg }} </span>
<span> {{ scope.row.cp_msg }} </span>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script setup lang="ts">
import { getComDicts } from '@/api/liswork/dict/ComDict';
import { getGroupInstrdList } from '@/api/liswork/work/LisWork';
import { reactive, ref } from 'vue';
import dayjs from 'dayjs';
import { queryBatchPrintService, batchPrintAll } from '@/api/liswork/batch/index';
import { getDictData, formatDict, dictData } from '@/hooks'
import { useCommonStore } from '@/store/modules/commonStore';
import { ElMessage, ElNotification } from 'element-plus';
import { classCom } from '@/utils/classCom';
const mbStore = useCommonStore();
const queryForm = reactive({
jyrq: '',
instrGroup: '',
yq: '',
jyrq: dayjs().format('YYYY-MM-DD'),
yqz: '',
yq: mbStore.defaultConfig.defaultinstr || '',
ybh: '',
brly: '',
ksdh: '',
printOrder: 'ybh',
options: {
excludePatientType: false,
excludeDept: false,
excludeNegative: false,
positiveOnly: false,
noNameSkip: false,
noResultSkip: false,
groupedPrint: false,
notPrintedOnly: false,
pendingReview: false,
reviewedOnly: false
}
sorttype: 1,
notbrly: null,
notksdh: null,
pcyx: null,
dyyx: null,
nobrxm: null,
nocsjg: null,
fzdy: null,
dybz: null,
jgbz: null,
jgbz2: 1,
});
const printLoading = ref(false);
const loading = ref(false);
const tableData = ref([]);
const printOrders = ref([
{ label: '样本号', value: 'ybh' },
{ label: '科室+床号+样本号', value: 'deptBedSample' },
{ label: '病人类型+科室+床号+样本号', value: 'typeDeptBedSample' },
{ label: '病人类型+科室+样本号', value: 'typeDeptSample' },
{ label: '阳性结果', value: 'positiveResult' }
{ label: '样本号', value: 1 },
{ label: '科室+床号+样本号', value: 2 },
{ label: '病人类型+科室+床号+样本号', value: 3 },
{ label: '病人类型+科室+样本号', value: 4 },
{ label: '阳性结果', value: 5 }
]);
const optionItems = ref([
{ label: '排除选择的病人类型', key: 'excludePatientType' },
{ label: '排除选择的科室', key: 'excludeDept' },
{ label: '排除阴性报告', key: 'excludeNegative' },
{ label: '仅打印阳性报告', key: 'positiveOnly' },
{ label: '无病人姓名不打印', key: 'noNameSkip' },
{ label: '无检验结果不打印', key: 'noResultSkip' },
{ label: '分组打印报告', key: 'groupedPrint' },
{ label: '打印未打印报告', key: 'notPrintedOnly' },
{ label: '打印待核报告', key: 'pendingReview' },
{ label: '打印已审核报告', key: 'reviewedOnly' }
]);
const selectedOptions = ref(Object.keys(queryForm.options).filter(key => queryForm.options[key]));
const updateSelectedOptions = () => {
Object.keys(queryForm.options).forEach(key => {
queryForm.options[key] = selectedOptions.value.includes(key);
});
{ key: 'notbrly', label: '排除选择的病人类型', disabled: false },
{ key: 'notksdh', label: '排除选择的科室', disabled: false },
{ key: 'pcyx', label: '排除阴性报告', disabled: false },
{ key: 'dyyx', label: '仅打印阳性报告', disabled: false },
{ key: 'nobrxm', label: '无病人姓名不打印', disabled: false },
{ key: 'nocsjg', label: '无检验结果不打印', disabled: false },
{ key: 'fzdy', label: '分组打印报告', disabled: false },
{ key: 'dybz', label: '打印未打印报告', disabled: false },
{ key: 'jgbz', label: '打印未审核报告', disabled: true },
{ key: 'jgbz2', label: '打印已审核报告', disabled: true }
])
// 查询
const searchHandle = () => {
if (!queryForm.yq) return ElMessage.warning('检验仪器不能为空!')
loading.value = true
queryForm.jyrq = dayjs(queryForm.jyrq).format('YYYY-MM-DD') + ' 00:00:00'
queryBatchPrintService(queryForm).then((res) => {
loading.value = false
if (res.code == 0) {
tableData.value = res.data
} else {
tableData.value = []
}
})
}
// 打印
const printHandle = () => {
if (!tableData.value.length) return ElMessage.warning('样本打印数据为空')
printLoading.value = true
batchPrintAll(queryForm).then((res) => {
printLoading.value = false
if (res.code == 0) {
classCom.printBase64PDF(res.data.base64data)
tableData.value = res.data.printflag
}
})
}
const handleinstrGroupChange = () => {
@ -157,7 +187,7 @@ const instrGroupOptions = ref<{ value: string, label: string }[]>([])
const instrOptions = ref<{ value: string, label: string }[]>([])
const getYqConfig = () => {
getGroupInstrdList({ lisgroup: queryForm.instrGroup })
getGroupInstrdList({ lisgroup: queryForm.yqz })
.then((res: any) => {
if (res.code == 0) {
instrOptions.value = res.data.map((item: any) => ({
@ -177,6 +207,8 @@ onMounted(() => {
}))
instrGroupOptions.value.push({ value: 'ALL', label: '所有仪器' })
getYqConfig()
getDictData('PT', 'DP')
});
});
@ -184,6 +216,11 @@ onMounted(() => {
<style scoped lang="scss">
.app-container {
display: flex;
flex-direction: column;
}
.query-form {
.el-form-item {
margin-bottom: 10px;
@ -217,7 +254,9 @@ onMounted(() => {
.bottom-card {
border-top: 1px solid #d9e8fb;
padding: 10px;
padding: 10px 0;
flex: 1;
overflow: hidden;
}
.action-buttons {

View File

@ -33,7 +33,7 @@ import { ref, reactive, toRefs, watch, computed, onMounted, nextTick } from "vue
// @ts-ignore
import { listUser } from '@/api/system/user.js'
import { reqdetail, reqdetailmx } from '@/api/liswork/work/LisWork'
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
const props = defineProps({
// 主键

View File

@ -15,7 +15,7 @@
<script setup lang="ts">
import { ref, watch, toRefs, onMounted, computed } from 'vue'
import { inputmdl } from "@/api/liswork/work/LisWork";
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import emitter from '@/utils/mitt'
import { useCommonStore } from '@/store/modules/commonStore';
const props = defineProps({

View File

@ -41,7 +41,7 @@ import { onMounted, ref, toRefs, computed, watch, nextTick } from 'vue';
import * as echarts from 'echarts';
import { historyInfo } from '@/api/liswork/work/LisWork'
import dayjs from 'dayjs';
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
const props = defineProps({
// 主键
queryParams: {

View File

@ -52,7 +52,7 @@
import type { PropType } from 'vue';
import { ref, watch, computed, reactive, toRefs, onMounted, nextTick } from 'vue';
import { otherinstr, otherInstrDetail } from '@/api/liswork/work/LisWork';
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import dayjs from 'dayjs';
const baseUrl = import.meta.env.VITE_APP_BASE_API

View File

@ -28,7 +28,7 @@
<script setup lang="ts">
import { getresultmedList } from "@/api/liswork/micro";
import { historyInfo } from "@/api/liswork/work/LisWork";
import CustomTable from "@/components/elTable/index.vue"
import CustomTable from "@/components/ElTable/index.vue"
import { LabResultItem, ymTableDataItem } from '@/types/index';
const props = defineProps({

View File

@ -69,7 +69,7 @@
<script setup lang="ts">
import { formatDict, getDictData, dictData } from '@/hooks';
import SelectTable from '@/components/SelectTable/index.vue'
import CustomVxeTable from '@/components/vxeTable/index.vue'
import CustomVxeTable from '@/components/VxeTable/index.vue'
import YQSelectTable from '@/components/SelectTable/YQSelectTable/index.vue'
import { queryBatchList, addBatch, delBatch } from '@/api/liswork/labItem/labItemApi'
import { ElMessage } from 'element-plus';

View File

@ -112,7 +112,7 @@ import CommonlyValues from './tab/commonlyValues.vue'
import UseInstr from './tab/useInstr.vue'
import Knowledge from './tab/knowledge.vue'
import CommonDescriptions from './tab/commonDescriptions.vue'
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import ReferenceValueDetails from './tab/referenceValueDetails.vue';
import { queryXmInfoNewService, queryXmInfoNewDetailService, saveDataService, deleteXmInfoService } from '@/api/liswork/labItem/labItemApi';
import SelectTable from '@/components/SelectTable/index.vue'

View File

@ -25,7 +25,7 @@
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import { dictData, getDictData } from '@/hooks';
import { ElMessage, ElMessageBox } from 'element-plus';
import { delXmValNewService } from '@/api/liswork/labItem/labItemApi'

View File

@ -39,7 +39,7 @@
</template>
<script setup lang="ts">
import CustomVxeTable from '@/components/vxeTable/index.vue'
import CustomVxeTable from '@/components/VxeTable/index.vue'
import { queryXmInfoNew } from '@/api/liswork/labItem/labItemApi'
import { getFirstLetter } from '@/utils/pinyin';

View File

@ -45,8 +45,8 @@
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import CustomVxeTable from '@/components/vxeTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import CustomVxeTable from '@/components/VxeTable/index.vue'
import { queryXmInfoNew, queryXmAlarmdetailNew, addXmAlarmdetailNew, delXmAlarmdetailNew } from '@/api/liswork/labItem/labItemApi'
import { XmAlarmdetailNew } from '@/types'
import { ElMessageBox, ElMessage } from 'element-plus'

View File

@ -18,7 +18,7 @@
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import { XmTextresultNew } from '@/types';
import { ElMessage, ElMessageBox } from 'element-plus';
import { ref } from 'vue';

View File

@ -8,7 +8,7 @@
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import { ref } from 'vue';
const props = defineProps({

View File

@ -74,7 +74,7 @@
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import { ref } from 'vue';
import { getDictData, dictData } from '@/hooks'
import SelectTable from '@/components/SelectTable/index.vue'

View File

@ -34,7 +34,7 @@
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import { XmInfoVs } from '@/types';
import SelectTable from '@/components/SelectTable/index.vue'
import { ElMessage, ElMessageBox } from 'element-plus'

View File

@ -70,7 +70,7 @@
<script setup lang="ts">
import { ref, nextTick, onMounted, watch } from 'vue'
import CommonTable from '@/components/vxeTable/index.vue'
import CommonTable from '@/components/VxeTable/index.vue'
import ContextMenu from "@/components/contextMenu/index.vue";
import { ContextMenuItem } from '@/types/index'
import yqSelectTable from '@/components/SelectTable/YQSelectTable/index.vue';

View File

@ -149,7 +149,7 @@
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import { LabResultItem } from '@/types/index';
import { changeresult, saveresult, newresult, sampleMedInfo, cbebCheck } from '@/api/liswork/micro/index';
import { deleteresult, queryXmVal, setinputmdl, queryLabPat, checkuser, printListwork } from "@/api/liswork/work/LisWork";

View File

@ -11,7 +11,7 @@
<script setup lang="ts">
import { ref, watch, toRefs, onMounted, computed } from 'vue'
import { inputmdl } from "@/api/liswork/work/LisWork";
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import emitter from '@/utils/mitt'
import { useCommonStore } from '@/store/modules/commonStore';
const props = defineProps({

View File

@ -22,7 +22,7 @@
</template>
<script setup lang="ts">
import CustomTable from "@/components/elTable/index.vue"
import CustomTable from "@/components/ElTable/index.vue"
import { getgermtextdict } from "@/api/liswork/micro"
const visible = ref(false)

View File

@ -43,7 +43,7 @@
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue';
import CustomTable from '@/components/ElTable/index.vue';
import { getmediumList, insertmedium, updatemedium, deletemedium, deletemediums } from '@/api/liswork/micro/index';
import { classCom } from '@/utils/classCom';
import { ElMessage, ElMessageBox } from 'element-plus';

View File

@ -5,7 +5,7 @@
</template>
<script setup lang="ts">
import CustomTable from "@/components/elTable/index.vue"
import CustomTable from "@/components/ElTable/index.vue"
import { getComLog } from "@/api/liswork/micro/index"
const props = defineProps({

View File

@ -185,7 +185,7 @@
</template>
<script setup lang="ts">
import CustomTable from "@/components/elTable/index.vue";
import CustomTable from "@/components/ElTable/index.vue";
import { classCom } from "@/utils/classCom";
import {
getresultmedList, savetestResult, changeresult, saveresult, newresult, getmeddictList, savemedresult,

View File

@ -9,8 +9,8 @@
<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>
<el-button type="primary" icon="Edit" @click="getList">画图</el-button>
<el-button type="warning" icon="Printer">打印</el-button>
</div>
<el-form :model="queryParams" ref="queryRef" size="small">
<el-form-item label="组别:" prop="instrGroup">

View File

@ -0,0 +1,194 @@
/**
* @file index.vue
* @description: 报告合并
* @author: w
* @since: 2026-06-30
*/
<template>
<div class="app-container">
<!-- 顶部筛选区域 -->
<el-form :model="filterForm" label-width="auto" class="query-form">
<el-row :gutter="16">
<el-col :span="7">
<el-form-item label="标本日期:">
<el-date-picker v-model="filterForm.startDate" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
style="width:47%" />
<span class="split-line">—</span>
<el-date-picker v-model="filterForm.endDate" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
style="width:47%" />
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="仪器分组:">
<SelectTable v-model:data="filterForm.yqz" :tableData="instrGroupOptions" placeholder="" />
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="病人类型:">
<SelectTable v-model:data="filterForm.brly" :tableData="dictData.PT" placeholder="" />
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="科室:">
<SelectTable v-model:data="filterForm.ksdh" :tableData="dictData.DP" placeholder="" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="4">
<el-form-item label="病历号:">
<el-input v-model="filterForm.patientId" placeholder="" />
</el-form-item>
</el-col>
<el-col :span="3">
<el-form-item label="姓名:" label-width="55px">
<el-input v-model="filterForm.name" placeholder="" />
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="样本号:">
<el-input v-model="filterForm.sampleNo" placeholder="" />
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="合并方式:">
<el-select v-model="filterForm.mergeType" placeholder="病历号">
<el-option label="病历号" value="id" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label=" ">
<el-checkbox v-model="filterForm.delOldSample">删除合并前标本</el-checkbox>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div>
<el-button type="primary" icon="search">查询</el-button>
<el-button type="warning" icon="Printer" plain>打印</el-button>
<el-button type="warning" icon="search" plain>查重</el-button>
<el-button type="warning" icon="Document" plain>合并</el-button>
</div>
<!-- 左右表格主体 -->
<div class="table-wrap">
<!-- 左侧患者标本主表 -->
<div class="left-table-box">
<el-table :data="patientTableData" border height="100%" @selection-change="handleSelectChange">
<el-table-column type="selection" width="55" label="全选" />
<el-table-column label="病历号" prop="patientId" align="center" width="110" />
<el-table-column label="姓名" prop="name" align="center" width="80" />
<el-table-column label="性别" prop="gender" align="center" width="60" />
<el-table-column label="年龄" prop="age" align="center" width="60" />
<el-table-column label="审核标志" prop="auditFlag" align="center" width="80" />
<el-table-column label="标本日期" prop="sampleDate" align="center" />
<el-table-column label="样本号" prop="sampleNo" align="center" />
<el-table-column label="病人类型" prop="brly" align="center" />
<el-table-column label="科室" prop="dept" align="center" />
<el-table-column label="送检医生" prop="sendDoctor" align="center" />
<el-table-column label="检验医师" prop="testDoctor" align="center" />
<el-table-column label="核对医师" prop="checkDoctor" align="center" />
</el-table>
</div>
<!-- 右侧检验项目明细表 -->
<div class="right-table-box">
<el-table :data="itemTableData" border height="100%">
<el-table-column label="项目代号" prop="itemCode" align="center" />
<el-table-column label="项目名称" prop="itemName" align="center" />
<el-table-column label="检验结果" prop="result" align="center" />
<el-table-column label="参考值" prop="refValue" align="center" />
<el-table-column label="单位" prop="unit" align="center" />
</el-table>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import dayjs from 'dayjs'
import { getDictData, formatDict, dictData } from '@/hooks'
import { getComDicts } from '@/api/liswork/dict/ComDict'
// 顶部筛选条件
const filterForm = reactive({
yqz: '',
startDate: dayjs().format('YYYY-MM-DD'),
endDate: dayjs().format('YYYY-MM-DD'),
brly: '',
ksdh: '',
patientId: '',
name: '',
sampleNo: '',
mergeType: 'id',
delOldSample: false
})
// 左侧患者标本表格数据
const patientTableData = ref([
// 模拟数据
])
// 右侧检验项目表格数据
const itemTableData = ref([
// 模拟数据
])
// 左侧多选事件
const handleSelectChange = (rows: any[]) => {
console.log('选中标本', rows)
// 可联动加载右侧检验项目
}
const instrGroupOptions = ref<{ value: string, label: string }[]>([])
onMounted(() => {
getComDicts({ zdlb: 'GROUP' }).then((res: any) => {
instrGroupOptions.value = res.data.map((item: any) => ({
value: item.zddh.trim(),
label: item.zdmc
}))
instrGroupOptions.value.unshift({ value: 'ALL', label: '所有仪器' })
getDictData('PT', 'DP')
})
})
</script>
<style scoped lang="scss">
.app-container {
display: flex;
flex-direction: column;
.split-line {
width: 6%;
display: flex;
align-items: center;
justify-content: center;
color: #ccc;
}
// 左右双表格容器
.table-wrap {
display: flex;
flex: 1;
gap: 10px;
margin-top: .625rem;
.left-table-box {
flex: 3;
height: 99%;
}
.right-table-box {
flex: 1;
height: 99%;
}
.el-table {
width: 100%;
height: 100%;
}
}
}
</style>

View File

@ -28,7 +28,7 @@
<script setup lang="ts">
import { changeLinkList, datalink } from '@/api/liswork/work/LisWork'
import { ElMessage } from 'element-plus'
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
const props = defineProps({
tableKey: {

View File

@ -46,7 +46,7 @@
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
const props = defineProps({
tableKey: {

View File

@ -77,7 +77,7 @@
<script setup lang="ts">
import { ref, nextTick, onMounted, watch } from 'vue'
import CommonTable from '@/components/vxeTable/index.vue'
import CommonTable from '@/components/VxeTable/index.vue'
import ContextMenu from "@/components/contextMenu/index.vue";
import { ContextMenuItem } from '@/types/index'
import yqSelectTable from '@/components/SelectTable/YQSelectTable/index.vue';

View File

@ -113,7 +113,7 @@ import ProjectDetails from "@/components/projectDetails/index.vue";
import projectsJg from "@/components/projectsjg/index.vue"
import BuiltDialog from "./components/builtDialog.vue";
import { classCom } from '@/utils/classCom'
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import dayjs from 'dayjs';
import emitter from "@/utils/mitt";
import CheckUser from "./components/CheckUser.vue";

View File

@ -73,7 +73,7 @@
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import { addService } from '@/api/liswork/xmKnowledge/xmKnowledgeApi'
import { ElMessage } from 'element-plus'

View File

@ -8,7 +8,7 @@
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
const props = defineProps({
dataList: {

View File

@ -38,7 +38,7 @@
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import { queryService, queryDetailService, delService } from '@/api/liswork/xmKnowledge/xmKnowledgeApi'
import TableRight from './TableData.vue'
import Modify from './Modify.vue'

View File

@ -1,20 +1,20 @@
<template>
<!-- 报告项目维护 -->
<el-form ref="form" :model="formData" label-width="80px">
<el-form-item label="项目代号" prop="xmdh">
<el-input placeholder="项目代号" v-model="formData.xmdh"></el-input>
</el-form-item>
<el-form-item label="项目名称" prop="xmmc">
<el-input placeholder="项目名称" v-model="formData.xmmc"></el-input>
</el-form-item>
</el-form>
<el-form ref="form" :model="formData" label-width="80px">
<el-form-item label="项目代号" prop="xmdh">
<el-input placeholder="项目代号" v-model="formData.xmdh"></el-input>
</el-form-item>
<el-form-item label="项目名称" prop="xmmc">
<el-input placeholder="项目名称" v-model="formData.xmmc"></el-input>
</el-form-item>
</el-form>
<CustomTable ref="tableRef" :data="dataList" :columns="columns" :enable-column-drag="true" @column-drag-end="handleColumnDragEnd"
:config="tableConfig"/>
<CustomTable ref="tableRef" :data="dataList" :columns="columns" :enable-column-drag="true"
@column-drag-end="handleColumnDragEnd" :config="tableConfig" />
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
const formData = ref()
const dataList = ref()
const columns = ref([
@ -40,5 +40,4 @@ const handleColumnDragEnd = (data: any) => {
}
</script>
<style scoped lang="scss">
</style>
<style scoped lang="scss"></style>

View File

@ -3,52 +3,22 @@
<!-- 搜索表单 -->
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch">
<el-form-item :label="menuname + '类别'" prop="paramType">
<el-select
v-model="queryParams.paramType"
:placeholder="`请选择${menuname}类别`"
clearable
style="width: 200px"
@change="handleQuery"
>
<el-option
v-for="item in paramTypeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
<el-select v-model="queryParams.paramType" :placeholder="`请选择${menuname}类别`" clearable style="width: 200px"
@change="handleQuery">
<el-option v-for="item in paramTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item :label="menuname + '编码'" prop="paramCode">
<el-input
v-model="queryParams.paramCode"
:placeholder="`请输入${menuname}编码`"
clearable
style="width: 200px"
@keyup.enter="handleQuery"
/>
<el-input v-model="queryParams.paramCode" :placeholder="`请输入${menuname}编码`" clearable style="width: 200px"
@keyup.enter="handleQuery" />
</el-form-item>
<el-form-item :label="`${menuname}名称`" prop="paramName">
<el-input
v-model="queryParams.paramName"
:placeholder="`请输入${menuname}名称`"
clearable
style="width: 200px"
@keyup.enter="handleQuery"
/>
<el-input v-model="queryParams.paramName" :placeholder="`请输入${menuname}名称`" clearable style="width: 200px"
@keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="状态"
clearable
style="width: 200px"
>
<el-option
v-for="dict in sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
<el-select v-model="queryParams.status" placeholder="状态" clearable style="width: 200px">
<el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item>
@ -71,45 +41,44 @@
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport">导出</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Document" @click="copyTem">复制模版</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<!-- 数据表格 -->
<div class="table-container">
<el-table
v-loading="loading"
:data="regdictList"
@selection-change="handleSelectionChange"
class="param-table"
height="100%"
>
<el-table v-loading="loading" :data="regdictList" @selection-change="handleSelectionChange" class="param-table"
height="100%">
<el-table-column type="selection" width="55" align="center" />
<el-table-column :label="`${menuname}编号`" align="center" prop="paramId" v-if="false" />
<el-table-column :label="`${menuname}类别`" align="center" prop="paramType" width="100" show-overflow-tooltip>
<template #default="scope">
<span>
{{ paramTypeOptions.find(item => item.value === scope.row.paramType)?.label || scope.row.paramOptiontype }}
{{paramTypeOptions.find(item => item.value == scope.row.paramType)?.label || scope.row.paramType}}
</span>
</template>
</el-table-column>
<el-table-column :label="`${menuname}编码`" align="center" prop="paramCode" show-overflow-tooltip >
<el-table-column :label="`${menuname}编码`" align="center" prop="paramCode" show-overflow-tooltip>
</el-table-column>
<el-table-column :label="`${menuname}名称`" align="left" prop="paramName" show-overflow-tooltip />
<el-table-column :label="`${menuname}名称`" align="left" prop="paramName" show-overflow-tooltip />
<el-table-column label="默认值" align="left" prop="paramDefvalue" width="80" show-overflow-tooltip />
<el-table-column label="前置条件" align="left" prop="precondition" width="100" show-overflow-tooltip />
<el-table-column label="筛选条件" align="left" prop="paramSql" width="120" show-overflow-tooltip />
<el-table-column label="筛选类型" align="left" prop="paramOptiontype" width="80" show-overflow-tooltip >
<template #default="scope">
<el-table-column label="筛选类型" align="left" prop="paramOptiontype" width="80" show-overflow-tooltip>
<template #default="scope">
<span>
{{ paramOptiontypeOptions.find(item => item.value === scope.row.paramOptiontype)?.label || scope.row.paramOptiontype }}
{{paramOptiontypeOptions.find(item => item.value === scope.row.paramOptiontype)?.label ||
scope.row.paramOptiontype}}
</span>
</template>
</template>
</el-table-column>
<el-table-column label="值域" align="left" prop="remark" width="100" show-overflow-tooltip />
<el-table-column label="是否隐藏" align="center" prop="paramHide" width="80" >
<template #default="scope">
<dict-tag :options="sys_yes_no" :value="scope.row.paramHide" />
</template>
<el-table-column label="是否隐藏" align="center" prop="paramHide" width="80">
<template #default="scope">
<dict-tag :options="sys_yes_no" :value="scope.row.paramHide" />
</template>
</el-table-column>
<el-table-column label="表格排序" align="center" prop="paramSequence" width="80" />
<el-table-column label="排序" align="center" prop="paramSort" width="80" />
@ -133,29 +102,15 @@
</div>
<!-- 分页组件 -->
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize" @pagination="getList" />
<!-- 新增/修改对话框 -->
<el-dialog :title="title" v-model="open" width="700px" class="compact-dialog">
<el-form ref="statsparamRef" :model="form" :rules="rules" label-width="150px" class="compact-form">
<el-form-item :label="`${menuname}类别`" prop="paramType">
<el-select
v-model="form.paramType"
:placeholder="`请选择${menuname}类别`"
style="width: 100%"
>
<el-option
v-for="item in paramTypeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
<el-select v-model="form.paramType" :placeholder="`请选择${menuname}类别`" style="width: 100%">
<el-option v-for="item in paramTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item :label="`${menuname}编码`" prop="paramCode">
@ -168,17 +123,9 @@
<el-input v-model="form.paramDefvalue" :placeholder="`请输入${menuname}默认值`" />
</el-form-item>
<el-form-item :label="`${menuname}筛选类型`" prop="paramOptiontype">
<el-select
v-model="form.paramOptiontype"
:placeholder="`请选择${menuname}筛选类型`"
style="width: 100%"
>
<el-option
v-for="item in paramOptiontypeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
<el-select v-model="form.paramOptiontype" :placeholder="`请选择${menuname}筛选类型`" style="width: 100%">
<el-option v-for="item in paramOptiontypeOptions" :key="item.value" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
<el-form-item :label="`${menuname}前置条件`" prop="precondition">
@ -190,11 +137,7 @@
</el-form-item>
<el-form-item label="是否隐藏" prop="paramHide">
<el-radio-group v-model="form.paramHide">
<el-radio
v-for="dict in sys_yes_no"
:key="dict.value"
:label="dict.value"
>
<el-radio v-for="dict in sys_yes_no" :key="dict.value" :label="dict.value">
{{ dict.label }}
</el-radio>
</el-radio-group>
@ -207,11 +150,7 @@
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in sys_normal_disable"
:key="dict.value"
:label="dict.value"
>
<el-radio v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.value">
{{ dict.label }}
</el-radio>
</el-radio-group>
@ -229,6 +168,19 @@
</div>
</template>
</el-dialog>
<!-- 复制模板 -->
<el-dialog title="复制模板" v-model="copyOpen" width="300px">
<el-form-item label="模板">
<el-select v-model="copyTemplate" placeholder="请选择复制模板" style="width: 100%">
<el-option v-for="item in copyTemplateOptions" :key="item.value" :label="item.statsName"
:value="item.statsCode" />
</el-select>
</el-form-item>
<template #footer>
<el-button type="primary" @click="copyTemplateSubmit">确 定</el-button>
</template>
</el-dialog>
</div>
</template>
@ -239,20 +191,28 @@ import {
getstatsparam,
liststatsparam,
updatestatsparam
} from "@/api/liswork/xtwh/statsparameterApi.ts";
} from "@/api/liswork/xtwh/StatsparameterApi.ts";
import { liststatstemp, copyParameter } from "@/api/liswork/xtwh/StatstemplateApi.ts";
import { copy } from "clipboard";
const route = useRoute();
// ========== 基础变量声明(避免提前访问) ==========
// 菜单名称
const menuname = ref("参数明细");
const statsCode = ref("1");
const copyOpen = ref(false);
const copyTemplate = ref("");
const copyTemplateOptions = ref([])
// 报表类别选项
const paramTypeOptions = ref([
{ label: "过滤参数", value: "0"},
{ label: "显示列", value: "1"},
{ label: "过滤+显示", value: "2"},
{ label: "汇总栏", value: "3"},
{ label: "子查询", value: "4"},
{ label: "逻辑条件", value: "5"}
{ label: "过滤参数", value: "0" },
{ label: "显示列", value: "1" },
{ label: "过滤+显示", value: "2" },
{ label: "汇总栏", value: "3" },
{ label: "子查询", value: "4" },
{ label: "逻辑条件", value: "5" },
{ label: "计算列", value: "6" }
]);
// 图表类型选项
@ -275,10 +235,10 @@ const proxy = instance?.proxy || null;
// 字典数据(空值保护)
const sys_normal_disable = proxy?.useDict("sys_normal_disable")?.sys_normal_disable || [];
const sys_yes_no= proxy?.useDict("sys_yes_no")?.sys_yes_no || [];
const sys_yes_no = proxy?.useDict("sys_yes_no")?.sys_yes_no || [];
// 表单数据
const form = ref({
statsCode:statsCode.value,
statsCode: statsCode.value,
paramId: undefined,
paramCode: undefined,
paramName: undefined,
@ -287,8 +247,8 @@ const form = ref({
paramType: paramTypeOptions.value[0]?.value || "",
paramOptiontype: paramOptiontypeOptions.value[0]?.value || "",
paramSql: "", // SQL语句(绑定到SqlEditor组件)
paramSequence:0,
paramHide:"",
paramSequence: 0,
paramHide: "",
paramSort: 0,
status: "0",
remark: undefined
@ -342,9 +302,9 @@ function resetForm() {
precondition: undefined,
paramType: paramTypeOptions.value[0]?.value || "",
paramOptiontype: paramOptiontypeOptions.value[0]?.value || "",
paramSequence:0,
paramHide:"",
statsCode:statsCode.value,
paramSequence: 0,
paramHide: "",
statsCode: statsCode.value,
paramSql: "",
paramSort: 0,
status: "0",
@ -361,18 +321,23 @@ function getList() {
loading.value = true;
const params = queryParams.value || { pageNum: 1, pageSize: 30 };
liststatsparam(params)
.then(response => {
regdictList.value = response?.rows || [];
total.value = response?.total || 0;
})
.catch(() => {
regdictList.value = [];
total.value = 0;
proxy && proxy.$modal.msgError("数据加载失败");
})
.finally(() => {
loading.value = false;
});
.then(response => {
regdictList.value = response?.rows || [];
total.value = response?.total || 0;
})
.catch(() => {
regdictList.value = [];
total.value = 0;
proxy && proxy.$modal.msgError("数据加载失败");
})
.finally(() => {
loading.value = false;
});
liststatstemp().then(response => {
copyTemplateOptions.value = response?.rows || [];
})
}
// 搜索
@ -450,6 +415,21 @@ function handleExport() {
}, `报表模板_${new Date().getTime()}.xlsx`);
}
const copyTem = () => {
copyOpen.value = true;
copyTemplate.value = ''
}
const copyTemplateSubmit = () => {
copyParameter({ statsCode: statsCode.value, statsCodeother: copyTemplate.value }).then(res => {
if (res.code == 200) {
getList()
proxy && proxy.$modal.msgSuccess("复制成功")
copyOpen.value = false
}
})
}
// 提交表单
async function submitForm() {
if (!proxy || !proxy.$refs || !proxy.$refs.statsparamRef) return;
@ -488,8 +468,8 @@ function cancel() {
getTypes(route.query && route.query.statsCode);
/** 查询字典类型详细 */
function getTypes(statsCode0) {
statsCode.value=statsCode0
queryParams.value.statsCode =statsCode0;
statsCode.value = statsCode0
queryParams.value.statsCode = statsCode0;
getList();
}
</script>
@ -544,6 +524,10 @@ function getTypes(statsCode0) {
.compact-form {
--el-form-item-margin-bottom: 8px;
line-height: 1.4;
.el-form-item {
margin-bottom: 8px;
}
}
:deep(.compact-form .el-form-item__label) {

View File

@ -34,7 +34,7 @@
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import YQSelectTable from '@/components/SelectTable/YQSelectTable/index.vue';
import { queryService, queryXmService, addService, delService } from '@/api/liswork/xtwh/xmFeeinstrApi';
import { queryOneService } from '@/api/system/parameter'

View File

@ -60,7 +60,7 @@
<script setup lang="ts">
import { queryListService, queryDetailService, queryOldxminfo, addXminfo, delXminfo, searchxminfo } from '@/api/liswork/xtwh/xmReqItemVsApi';
import YQSelectTable from '@/components/SelectTable/YQSelectTable/index.vue';
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import { ElMessage } from 'element-plus';
import { useCommonStore } from '@/store/modules/commonStore'
const mbStore = useCommonStore();

View File

@ -480,7 +480,7 @@ onMounted(() => {
.el-table__fixed-header-wrapper {
th {
word-break: break-word;
background-color: #c0c0c0 !important;
background-color: #eff6fa !important;
color: #000;
font-size: .8125rem;
font-weight: 500;
@ -491,21 +491,21 @@ onMounted(() => {
:deep(.el-table--border th.el-table__cell) {
border-right: 1px solid #d1d4d9 !important;
border-bottom: 1px solid #d1d4d9 !important;
border-right: 1px solid #ccc !important;
border-bottom: 1px solid #ccc !important;
}
:deep(.el-table--border) {
border: 1px solid #d1d4d9 !important;
border: 1px solid #ccc !important;
}
:deep(.el-table td.el-table__cell,
.el-table th.el-table__cell.is-leaf) {
border-bottom: 1px solid #d1d4d9 !important;
border-bottom: 1px solid #ccc !important;
}
:deep(.el-table--border .el-table__cell) {
border-right: 1px solid #d1d4d9 !important;
border-right: 1px solid #ccc !important;
}
:deep(.el-table__row) {

View File

@ -104,7 +104,7 @@
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import { querySample } from '@/api/regional/index'
import SelectTable from '@/components/SelectTable/index.vue';
import { classCom } from '@/utils/classCom';

View File

@ -78,7 +78,7 @@
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import { querySampleSign, sampleSign } from '@/api/regional/index'
import SelectTable from '@/components/SelectTable/index.vue';
// @ts-ignore

View File

@ -78,7 +78,7 @@
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import { querySampleSignBack, sampleSign } from '@/api/regional/index'
import SelectTable from '@/components/SelectTable/index.vue';
import { classCom } from '@/utils/classCom';

View File

@ -87,7 +87,7 @@
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import { querySample, sampleSign } from '@/api/regional/index'
// @ts-ignore
import { listhospital } from "@/api/regional/dict/hospital.js";

View File

@ -163,7 +163,7 @@
import { ref, reactive, toRaw, computed, watch, nextTick, onMounted, } from 'vue';
import { HiprintPrinter } from '@/utils/hiprintPrinter';
import { classCom } from '@/utils/classCom';
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import { useRouter } from 'vue-router'
import { usePrintStore } from '@/store/modules/printStore'
import { fetchCodeList, addObj, fetchCodeDetail, fetchCodeExec, fetchCodeReqmain, printSendSample, printsetup } from '@/api/checkCode/index'

View File

@ -178,7 +178,7 @@
<script setup lang="ts">
import { ref, reactive, toRaw, computed, watch, nextTick, onMounted } from 'vue';
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import { useRouter } from 'vue-router'
import { reportList, reportPrintPdf, reportResult, reportMedList, reportFsresult } from '@/api/checkCode/index'
import dayjs from 'dayjs';

View File

@ -78,7 +78,7 @@
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import { querySampleSignBack, sampleSign } from '@/api/regional/index'
import SelectTable from '@/components/SelectTable/index.vue';
import { classCom } from '@/utils/classCom';

View File

@ -45,7 +45,7 @@
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import CustomTable from '@/components/ElTable/index.vue'
import { sampleitemCount, sampleSign } from '@/api/regional/index'
import SelectTable from '@/components/SelectTable/index.vue';
import { classCom } from '@/utils/classCom';

View File

@ -5,12 +5,14 @@
*/
<template>
<div class="app-container">
<el-button type="primary" @click="search" size="default">查询</el-button>
<el-button type="primary" @click="print" size="default">打印</el-button>
<div class="mb8">
<el-button type="primary" icon="Search" @click="search" size="default">查询</el-button>
<el-button type="warning" icon="Printer" @click="print" size="default">打印</el-button>
</div>
<el-form ref="form" :model="queryParams" inline size="small" class="stats-form">
<el-row :gutter="10" class="stats-form-row">
<el-col :span="16">
<el-col :span="checkBoxs.length ? 16 : 24">
<div class="form-panel">
<div class="tips">统计条件</div>
<div class="panel-content panel-content-left">
@ -32,7 +34,6 @@
placeholder="请选择" style="width:150px" size="small" />
</template>
<template v-if="item.paramOptiontype == '0'">
<el-checkbox v-model="item.paramDefvalue" :label="item.paramName" true-value="1" false-value="0" />
</template>
@ -42,7 +43,7 @@
</div>
</el-col>
<el-col :span="8">
<div class="form-panel">
<div class="form-panel" v-if="checkBoxs.length">
<div class="tips">统计项目</div>
<div class="panel-content panel-content-right">
<el-form-item label="" class="stats-items-form-item">
@ -59,20 +60,51 @@
</el-form>
<div class="print_box">
<div class="print_content">
<div class="title">{{ formatDict(userStore.sysLoginParam.loginYLJG, 'HOS') }}</div>
<div class="content">{{ statsTitle }}</div>
<div class="table-container bb_table">
<vxe-table :data="tableData" border v-loading="loading" height="100%"
:tooltip-config="{ appendToBody: true, zIndex: 3000 }" show-footer :footer-method="getSummaries"
:scroll-y="{ enabled: true, rSize: 30, height: '100%', }" show-footer-overflow>
<vxe-column v-for="col in tableColumns" :key="col.prop" :title="col.label" :field="col.prop" width="100"
show-overflow align="center">
<template #default="scope">
{{ col.dictType ? formatDict(scope.row[col.prop], col.dictType) : scope.row[col.prop] }}
</template>
</vxe-column>
</vxe-table>
</div>
</div>
</div>
<!-- 视觉移出屏幕,页面看不见,但DOM完整存在用于iframe打印 -->
<div class="print-only-wrap" id="printWrap">
<div class="title">{{ formatDict(userStore.sysLoginParam.loginYLJG, 'HOS') }}</div>
<div class="content">{{ statsTitle }}</div>
<div class="table-container">
<vxe-table :data="tableData" border v-loading="loading" height="100%" class="mytable-style"
:tooltip-config="{ appendToBody: true, zIndex: 3000 }" show-footer :footer-method="getSummaries"
:scroll-y="{ enabled: true, rSize: 30, height: '100%', }">
<vxe-column v-for="col in tableColumns" :key="col.prop" :title="col.label" :field="col.prop" width="100"
show-overflow align="center">
<template #default="scope">
{{ col.dictType ? formatDict(scope.row[col.prop], col.dictType) : scope.row[col.prop] }}
</template>
</vxe-column>
</vxe-table>
</div>
<!-- 原生完整table,无滚动、无虚拟DOM,所有数据全部渲染 -->
<table class="print-table" border="1" cellpadding="0" cellspacing="0">
<thead>
<tr>
<th v-for="col in tableColumns" :key="col.prop">{{ col.label }}</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, rowIdx) in tableData" :key="rowIdx">
<td v-for="col in tableColumns" :key="col.prop" align="center">
{{ col.dictType ? formatDict(row[col.prop], col.dictType) : row[col.prop] }}
</td>
</tr>
</tbody>
<!-- 合计行,和vxe合计逻辑完全一致 -->
<tfoot>
<tr>
<td v-for="(col, colIdx) in tableColumns" :key="col.prop" align="center">
{{ getPrintFooterText(col, colIdx) }}
</td>
</tr>
</tfoot>
</table>
</div>
</div>
</template>
@ -84,7 +116,7 @@ import { classCom } from '@/utils/classCom';
import { getstatsTemplate, getstatsQuery } from "@/api/liswork/xtwh/StatsparameterApi";
import { listUser } from '@/api/system/user.js'
import useUserStore from '@/store/modules/user'
import { getDictData, formatDict } from '@/hooks'
import { getDictData, formatDict, dictData } from '@/hooks'
import { ElMessage } from "element-plus";
const userStore = useUserStore()
const mbStore = useCommonStore();
@ -98,9 +130,9 @@ const Parameter = ref([])
const statsTitle = ref('' || '报告统计')
const tableData = ref([])
const loading = ref(false)
const coloums = ref([]) //固定列
const sumColoums = ref([]) //计算列
const checkBoxs = ref([])
const originalColumn = ref([]) //原始列
const tableColumns = ref([]);
const Template = ref({})
@ -130,57 +162,78 @@ const handletime = () => {
}
const getSummaries = ({ columns, data }) => {
if (!sumColoums.value.length) return
const sumSamplecnt = tableData.value.reduce((sum, item) => sum + item.cp_samplecnt, 0)
const sumCnt = tableData.value.reduce((sum, item) => sum + item.cp_cnt, 0)
const sumAmt = tableData.value.reduce((sum, item) => sum + item.cp_amt, 0).toFixed(2)
// 构建合计行数据
const footerData = columns.map((column) => {
const colField = column.field;
// 匹配当前列是否是需要合计的列
const isSumColumn = sumColoums.value.some(item => item.paramCode === colField);
// 2. 定义合计行每一列的内容
const footerData = columns.map((column, index) => {
switch (column.field) {
case tableColumns.value[0].prop: // 第一列显示“合计”
return '合计'
case 'cp_samplecnt':
return sumSamplecnt
case 'cp_cnt':
return sumCnt
case 'cp_amt':
return sumAmt
default:
return '' // 其他列空值
// if (colField === tableColumns.value[0]?.prop) {
// // 第一列固定显示"合计"
// return '合计';
// } else
if (isSumColumn) {
// 对合计列求和(处理空值/非数字)
const sum = data.reduce((total, row) => {
const value = Number(row[colField] || 0);
return total + (isNaN(value) ? 0 : value);
}, 0);
return sum;
} else {
// 非合计列显示空
return '';
}
});
return [footerData];
};
// 处理checkbox选中
const handleCheckBoxChange = (val) => {
// 基础列:保留,不随勾选删除
const baseCols = tableColumns.value.filter(col => {
// 判断是否是统计项目复选框对应的列:checkBoxs里存在该paramCode就是可选列
const isCheckItem = checkBoxs.value.some(item => item.paramCode === col.prop)
return !isCheckItem
})
return [footerData]
// 2. 获取当前勾选的所有可选列配置
const selectedCheckCols = checkBoxs.value
.filter(item => val.includes(item.paramCode))
.map(item => ({
key: item.paramCode,
label: item.paramName,
prop: item.paramCode,
dictType: item.remark,
paramSequence: 0
}))
// 3. 合并数组:勾选项放最前面 + 原有基础列在后
tableColumns.value = [...selectedCheckCols, ...baseCols]
let seq = 1
tableColumns.value.forEach((col, idx) => {
if (col.paramSequence === 0) {
col.paramSequence = seq++
}
})
};
// 查询
const search = () => {
const checkedCols = [...coloums.value, ...checkBoxs.value];
const arr = [];
tableColumns.value.forEach((tableItem, tableIndex) => {
const matchItem = checkedCols.find(
(checkItem) => checkItem.paramName === tableItem.label
);
if (matchItem) {
arr.push({
...matchItem,
paramSequence: matchItem.paramSequence ? matchItem.paramSequence : tableIndex + 1,
});
originalColumn.value.forEach(item => {
const matchTabCol = tableColumns.value.find(col => col.prop == item.paramCode)
if (matchTabCol) {
item.paramSequence = matchTabCol.paramSequence
} else {
item.paramSequence = 0
}
});
const unmatchedItems = checkedCols.filter(
(checkItem) => !tableColumns.value.some((tableItem) => tableItem.label === checkItem.paramName)
);
unmatchedItems.forEach((item, unmatchIndex) => {
arr.push({ ...item, });
});
})
const data = {
Parameter: Parameter.value,
Column: arr,
Column: originalColumn.value,
Template: Template.value
};
loading.value = true;
@ -191,43 +244,136 @@ const search = () => {
})
};
const print = () => {
};
const handleCheckBoxChange = (val) => {
const checkedCols = val.map(paramCode => {
const matchItem = checkBoxs.value.find(item => item.paramCode === paramCode);
return matchItem ? { label: matchItem.paramName, prop: matchItem.paramCode, dictType: matchItem.remark } : null;
}).filter(Boolean); // 过滤null
const fixedCols = coloums.value.map(item => ({
label: item.paramName,
prop: item.paramCode,
dictType: item.remark,
}));
tableColumns.value = [...checkedCols, ...fixedCols];
// 打印专用合计文本,和getSummaries逻辑统一
const getPrintFooterText = (col, idx) => {
// if (idx === 0) return '合计'
const isSumColumn = sumColoums.value.some(item => item.paramCode === col.prop)
if (!isSumColumn) return ''
// 求和
const sum = tableData.value.reduce((total, row) => {
const val = Number(row[col.prop] || 0)
return total + (isNaN(val) ? 0 : val)
}, 0)
return sum
}
// iframe打印核心方法
const print = () => {
return;
// 获取隐藏打印容器完整HTML
const printDom = document.getElementById('printWrap')
const printHtml = printDom.outerHTML
// 打印页面内置样式(统一红边框、行高、打印A4横向、合计加粗)
const printStyle = `
<style>
@page {
size: A4 landscape;
margin: 8mm;
}
html,body {
padding: 0;
margin: 0;
}
.title {
font-size: 20px;
text-align: center;
font-weight: 600;
margin-bottom: 6px;
}
.content {
font-size: 16px;
text-align: center;
margin-bottom: 12px;
font-weight: 600;
}
.print-table {
width: 100%;
border-collapse: collapse;
}
.print-table th,
.print-table td {
border: 1px solid #ccc;
height: 30px;
line-height: 30px;
font-size: 12px;
padding: 2px 4px;
}
.print-table tfoot td {
font-size: 13px;
font-weight: 700;
}
tr {
page-break-inside: avoid;
}
/* 打印渲染完整颜色边框 */
* {
-webkit-print-color-adjust: exact !important;
print-color-adjust: exact !important;
}
</style>
`
// 1. 创建隐藏iframe
const iframe = document.createElement('iframe')
iframe.style.width = '0px'
iframe.style.height = '0px'
iframe.style.position = 'absolute'
iframe.style.left = '-9999px'
document.body.appendChild(iframe)
// 2. 写入完整打印页面内容
const iframeDoc = iframe.contentDocument
iframeDoc.open()
iframeDoc.write(`
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>报表打印</title>
${printStyle}
</head>
<body>
${printHtml}
</body>
</html>
`)
iframeDoc.close()
// 3. 等待DOM渲染完成后打印
setTimeout(() => {
iframe.contentWindow.print()
// 打印弹窗关闭后销毁iframe
setTimeout(() => {
document.body.removeChild(iframe)
}, 1000)
}, 600)
}
// 获取模板参数
const getParams = () => {
getstatsTemplate({ StatsCode: route.query && route.query.statsCode, }).then(res => {
Parameter.value = res.data.Parameter
tableColumns.value = res.data.Column.filter(item => item.paramType == '6').map(item => {
originalColumn.value = res.data.Column
//先对 Column 按 paramSequence 从小到大排序
const sortedColumn = res.data.Column.sort((a, b) => a.paramSequence - b.paramSequence)
tableColumns.value = sortedColumn.filter(item => (item.paramType == '1' || item.paramType == '6') && item.paramSequence > 0).map(item => {
if (item.remark) { getDictData(item.remark) }
return {
key: item.paramCode,
label: item.paramName,
prop: item.paramCode,
dictType: item.remark,
paramSequence: item.paramSequence,
}
})
}) //显示列 (item.paramType == '1' || item.paramType == '6') && item.paramSequence > 0
coloums.value = res.data.Column.filter(item => item.paramType == '6')
sumColoums.value = res.data.Column.filter(item => item.paramType == '6') //计算列 paramType==6
checkBoxs.value = res.data.Column.filter(item => item.paramType != '6')
Template.value = res.data.Template
statsTitle.value = res.data.Template.statsTitle
checkBoxs.value = res.data.Column.filter(item => item.paramSequence == 0) //选择列 paramSequence==0
Template.value = res.data.Template //模板
statsTitle.value = res.data.Template.statsTitle //统计标题
})
};
@ -237,10 +383,28 @@ onMounted(() => {
getParams()
})
</script>
<style scoped lang="scss">
@media print {
.no-print {
display: none !important;
}
}
// 打印专用容器:屏幕视觉隐藏,DOM保留
.print-only-wrap {
position: absolute;
left: -9999px;
top: -9999px;
width: 1px;
height: 1px;
overflow: hidden;
}
.app-container {
display: flex;
flex-direction: column;
overflow: auto;
background-color: #eee;
}
.stats-form {
@ -315,12 +479,21 @@ onMounted(() => {
}
.print_box {
height: 65vh;
flex: 1;
display: flex;
justify-content: center;
.print_content {
width: 70%;
height: 100%;
background-color: #fff;
}
}
.table-container {
margin-top: 10px;
height: calc(100% - 65px);
height: calc(100% - 70px);
padding: 10px;
}
.tips {
@ -343,60 +516,6 @@ onMounted(() => {
background: #3282F6;
}
:deep(.el-table__footer-wrapper tfoot td.el-table__cell) {
color: #1f6dd3 !important;
font-weight: 700;
/* 可替换为任意颜色值 */
}
: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;
}
:deep(.vxe-table--render-default.is--padding .vxe-body--column:not(.col--ellipsis)) {
padding: 0 !important;
}
:deep(.vxe-table--render-default .vxe-footer--column:not(.col--ellipsis)) {
padding: 0 !important;
color: #1f6dd3 !important;
font-weight: 700;
}
:deep(.vxe-header--gutter),
:deep(.col--gutter) {
display: none !important;
}
@media (max-width: 1400px) {
.checkbox-form-item {