打印服务

This commit is contained in:
wuyy 2026-04-02 18:01:47 +08:00
parent 7dee664561
commit 4909e9b67b
12 changed files with 331 additions and 140 deletions

View File

@ -348,9 +348,9 @@ const setLabel = (val: any) => {
const clearHandle = () => {
selectShowValue.value = '';
currentRow.value = null;
tableRef.value.clearCurrentRow();
emits("update:data", null);
emits('getDataValue', null);
tableRef.value?.clearCurrentRow();
};
</script>

View File

@ -2,11 +2,11 @@
<section class="app-main">
<router-view v-slot="{ Component, route }">
<transition name="fade-transform" mode="out-in">
<keep-alive :include="tagsViewStore.cachedViews">
<el-watermark :font="font" :content="content">
<el-watermark :font="font" :content="content">
<keep-alive :include="tagsViewStore.cachedViews">
<component v-if="!route.meta.link" :is="Component" :key="route.path" />
</el-watermark>
</keep-alive>
</keep-alive>
</el-watermark>
</transition>
</router-view>
<iframe-toggle />

View File

@ -15,7 +15,22 @@ export default {
method: 'get',
url: url,
responseType: 'blob',
headers: { 'Authorization': 'Bearer ' + getToken() }
headers: { 'Authorization': 'Bearer ' + getToken() },
onDownloadProgress: (progressEvent) => {
// console.log(progressEvent)
//progressEvent.loaded 下载文件的当前大小
//progressEvent.total 下载文件的总大小 如果后端没有返回 请让他加上
let progressPercent = Math.round((progressEvent.loaded / progressEvent.total) * 100);
let loading = ElLoading.service({
lock: true,
text: `下载中,请稍候${progressPercent}%`,
background: 'rgba(0, 0, 0, 0.7)',
})
loading.setText(`下载中,请稍候${progressPercent}%`)
if (progressPercent == 100) {
loading.close()
}
}
}).then((res: any) => {
const isBlob = blobValidate(res.data)
if (isBlob) {

View File

@ -20,6 +20,7 @@ interface UserState {
roles: string[]
permissions: string[]
sysLoginParam: Object
deptParam: Object
}
const useUserStore = defineStore(
@ -35,6 +36,7 @@ const useUserStore = defineStore(
roles: [],
permissions: [],
sysLoginParam: {}, // 登录参数
deptParam: {} // 部门参数
}),
actions: {
// 单点登录
@ -79,6 +81,7 @@ const useUserStore = defineStore(
const user = res.user
let avatar = user.avatar || ''
this.sysLoginParam = user.sysLoginParam
this.deptParam = user.dept
if (!isHttp(avatar)) {
avatar = (isEmpty(avatar)) ? defAva : import.meta.env.VITE_APP_BASE_API + avatar
}

View File

@ -48,4 +48,29 @@ export function checkRole(value: string[]): boolean {
})
return hasRole
}
}
/**
* 管理员、检测机构权限校验
* @param value 校验值
* @returns {Boolean}
*/
export function checkDeptRole(value: string[]): boolean {
if (!value || !(value instanceof Array) || value.length === 0) {
console.error(`need roles! Like checkRole="['admin','editor']"`)
return false
}
const userStore = useUserStore()
const roles = userStore.roles
const permissionRoles = value
const deptParam = userStore.deptParam
// 取出 roleKey 进行判断
const hasRole = roles.some((role: any) => {
const roleKey = role.roleKey || ''
// 是超级管理员 admin 或者 包含指定角色 、 检测机构人员权限 203
return roleKey === 'admin' || permissionRoles.includes(roleKey) || deptParam.parentId == 203
})
return hasRole
}

View File

@ -7,15 +7,14 @@
import { ElMessageBox, ElMessage } from 'element-plus'
import { printcheck } from '@/api/checkCode/index'
import Download from '@/plugins/download'
import { getWebSocketState } from '@/utils/webSocket';
export const checkPrintService = async (): Promise<boolean> => { //连接成功返回true,失败返回false
try {
const res = await printcheck()
if (res.code == 0) {
if (getWebSocketState() == 1) { // 1表示WebSocket已连接
return true
} else {
await showPrintServiceError(res.msg)
await showPrintServiceError('打印服务未连接')
return false
}
} catch (error) {

103
src/utils/webSocket.ts Normal file
View File

@ -0,0 +1,103 @@
// WebSocket连接配置
type WebSocketOptions = {
fullUrl: string;
onMessage?: (data: string) => void;
onOpen?: () => void;
onError?: (error: Event) => void;
onClose?: () => void;
reconnectInterval?: number;
};
let websocket: WebSocket | null = null;
let reconnectTimer: any = null;
let isManualClose = false;
// 初始化WebSocket连接
export function initWebSocket(options: WebSocketOptions) {
const {
fullUrl,
onMessage,
onOpen,
onError,
onClose,
reconnectInterval = 3000
} = options;
// 关闭旧连接
if (websocket) {
websocket.close();
}
// 检查浏览器支持性
if (!('WebSocket' in window)) {
console.error('当前浏览器不支持WebSocket');
return;
}
// 创建WebSocket连接
try {
websocket = new WebSocket(fullUrl);
// 连接成功回调
websocket.onopen = () => {
clearTimeout(reconnectTimer!);
isManualClose = false;
onOpen?.();
};
// 接收消息回调
websocket.onmessage = (event) => {
onMessage?.(event.data);
};
// 错误回调
websocket.onerror = (error) => {
onError?.(error);
startReconnect(() => initWebSocket(options), reconnectInterval);
};
// 关闭回调
websocket.onclose = () => {
onClose?.();
if (!isManualClose) {
startReconnect(() => initWebSocket(options), reconnectInterval);
}
};
} catch (error) {
console.error('WebSocket连接创建失败:', error);
startReconnect(() => initWebSocket(options), reconnectInterval);
}
}
// 发送消息
export function sendWebSocketMessage(message: any): boolean {
if (websocket && websocket.readyState === WebSocket.OPEN) {
websocket.send(JSON.stringify(message));
return true;
}
console.error('WebSocket未连接,无法发送消息');
return false;
}
// 手动关闭WebSocket
export function closeWebSocket(): void {
isManualClose = true;
if (reconnectTimer) {
clearTimeout(reconnectTimer);
}
websocket?.close();
websocket = null;
}
// 启动重连
function startReconnect(connectCallback: () => void, interval: number): void {
if (reconnectTimer) {
clearTimeout(reconnectTimer);
}
reconnectTimer = setTimeout(connectCallback, interval);
}
// 获取当前连接状态
export function getWebSocketState(): number | null {
return websocket?.readyState || null;
}

View File

@ -11,10 +11,10 @@
<div class="box-shadow">
<el-row class="top-box">
<el-col :span="8" class="col_box">
<el-button type="primary" :loading="saveLoading" @click="saveHandle">保存</el-button>
<el-button type="primary" @click="addHandle">新增</el-button>
<el-button type="primary" :loading="printLoading" @click="printHandle">打印</el-button>
<el-button type="danger" @click="deleteHandle">作废</el-button>
<el-button type="primary" :size="aotuSize" :loading="saveLoading" @click="saveHandle">保存</el-button>
<el-button type="primary" :size="aotuSize" @click="addHandle">新增</el-button>
<el-button type="primary" :size="aotuSize" :loading="printLoading" @click="printHandle">打印</el-button>
<el-button type="danger" :size="aotuSize" @click="deleteHandle">作废</el-button>
</el-col>
<el-col :span="16">
<div class="tips">
@ -72,12 +72,12 @@
<div class="box-shadow">
<el-form :model="searchForm" inline>
<el-form-item label="" prop="brxm">
<el-input v-model="searchForm.brxm" clearable style="width: 8rem;" @change="handleQuery"
<el-input v-model="searchForm.brxm" clearable style="width: 8rem;" @change="handleQuery" :size="aotuSize"
placeholder="请输入姓名" />
</el-form-item>
<el-form-item label="" prop="status">
<div class="radio_box">
<el-radio-group v-model="searchForm.status" @change="handleQuery" size="small">
<el-radio-group v-model="searchForm.status" @change="handleQuery" :size="aotuSize">
<el-radio :value="''">所有</el-radio>
<el-radio :value="item.value" v-for="item in dictData.SQDS">{{ item.label }}</el-radio>
</el-radio-group>
@ -86,7 +86,7 @@
<el-form-item label="" prop="begdate">
<div class="radio_box">
<el-radio-group v-model="searchForm.days" @change="changeDays" size="small">
<el-radio-group v-model="searchForm.days" @change="changeDays" :size="aotuSize">
<el-radio :value="3">近3天</el-radio>
<el-radio :value="7">近7天</el-radio>
<el-radio :value="0">此日
@ -96,8 +96,8 @@
</el-radio>
</el-radio-group>
<el-date-picker v-model="today" type="date" value-format="YYYY-MM-DD" style="width: 9rem;"
@change="dateHandle" /> &nbsp;
<el-button type="primary" icon="RefreshRight" @click="handleQuery">刷新</el-button>
:size="aotuSize" @change="dateHandle" /> &nbsp;
<el-button type="primary" icon="RefreshRight" :size="aotuSize" @click="handleQuery">刷新</el-button>
</div>
</el-form-item>
</el-form>
@ -130,6 +130,9 @@ import { listitemclass } from "@/api/regional/dict/itemclass.ts";
import { classCom } from '@/utils/classCom';
import { useGroupTableData } from '@/utils/groupHelper'
const { proxy } = getCurrentInstance();
import { initWebSocket, sendWebSocketMessage, closeWebSocket, getWebSocketState } from '@/utils/webSocket';
const aotuSize = classCom.useAutoSize();
const labpat = ref({
ageUnit: '1'
})
@ -383,6 +386,7 @@ const printHandle = () => {
printLoading.value = true
reqPrint(uniqueData).then(res => {
if (res.code == 0) {
sendWebSocketMessage(res.data)
handleRowClick({ row: rowInfo.value })
ElMessage.success('正在打印中...')
handleQuery()
@ -420,11 +424,17 @@ const xmcellStyle = ({ row, column }) => {
const searchList = ref([])
const handleTabClick = (tab) => {
const currentTab = xmdlList.value.find(item => item.dictCode === tab.paneName)
if (currentTab) {
searchList.value = processedTableData.value.filter(item => item.classid === currentTab.dictCode)
if (tab.paneName) {
const currentTab = xmdlList.value.find(item => item.dictCode === tab.paneName)
if (currentTab) {
searchList.value = processedTableData.value.filter(item => item.classid === currentTab.dictCode)
filterData.value = [...searchList.value]
}
} else {
searchList.value = [...processedTableData.value]
filterData.value = [...searchList.value]
}
}
const processedTableData = ref([])
@ -582,6 +592,7 @@ const getXmList = () => {
listregdict({ dictType: 'CLASS' }).then(response => {
xmdlList.value = response.rows;
xmdlList.value.unshift({ dictCode: '', dictName: '全部' })
activeName.value = xmdlList.value.length > 0 ? xmdlList.value[0].dictCode : '';
handleTabClick({ paneName: activeName.value });
});
@ -589,7 +600,24 @@ const getXmList = () => {
}
const itemclassList = ref([]) // 容器类别
const initSocket = () => {
initWebSocket({
fullUrl: `ws://localhost:9801`,
onOpen: () => {
console.log('WebSocket连接成功');
},
onMessage: (data) => {
console.log(`收到消息: `, JSON.parse(data));
},
onError: (error) => {
console.log(`连接错误: ${error.type}`);
},
onClose: () => {
console.log('WebSocket连接已关闭');
},
reconnectInterval: 3000 // 重连间隔(毫秒)
});
}
onMounted(() => {
getXmList()
@ -602,7 +630,13 @@ onMounted(() => {
// 初始化初始值
updateInitialData()
initSocket()
})
// 页面卸载时清理
onUnmounted(() => {
closeWebSocket();
});
</script>
<style scoped lang="scss">
@ -628,7 +662,7 @@ onMounted(() => {
.table-box {
margin-top: 2px;
height: calc(100% - 80px);
height: calc(100% - 85px);
}
.el-form-item {
@ -682,6 +716,10 @@ onMounted(() => {
.el-radio {
margin-right: .3125rem;
:deep(.el-radio__label) {
padding-left: .3125rem;
}
}
}

View File

@ -1,8 +1,6 @@
<template>
<div class="login">
<!-- <FloatingLines :enabled-waves="['top', 'middle', 'bottom']" :line-count="[10, 15, 20]" :line-distance="[8, 6, 4]"
:bend-radius="5.0" :bend-strength="-0.5" :interactive="true" :parallax="true" /> -->
<el-form ref="loginRef" class="login-form">
<el-form ref="loginRef" class="login-form" :model="loginForm" :rules="loginRules" :hide-required-asterisk="true">
<div class="login-header">
<div class="login-logo">
<img src="@/assets/images/logo_new.png" alt="系统Logo" />
@ -17,14 +15,13 @@
<el-tabs v-model="activeName" type="card" @tab-click="handleClick" class="login-tabs">
<!-- 工号登录 Tab -->
<el-tab-pane label="账号密码登录" name="first">
<el-form-item label="医疗机构:" prop="loginYLJG" class="custom-select">
<el-form-item label="医疗机构:" prop="loginParam.loginYLJG" class="custom-select">
<el-select v-model="loginForm.loginParam.loginYLJG" placeholder="请选择医疗机构" style="width: 100%"
@change="handleChange">
<template #prefix>
<svg-icon icon-class="international" class="el-input__icon input-icon" />
</template>
<el-option v-for="item in selectOptions" :key="item.id" :label="item.name"
:value="item.id.toString()"></el-option>
<el-option v-for="item in selectOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
@ -44,12 +41,6 @@
</template>
</el-input>
</el-form-item>
<!-- 修复:移除空的el-form-item,验证码关闭时不渲染任何内容 -->
<el-form-item prop="code" v-if="!captchaEnabled" size="large">
</el-form-item>
<el-form-item prop="code" label="验 证 码 :" v-if="captchaEnabled">
<el-input v-model="loginForm.code" size="large" auto-complete="off" placeholder="验证码" style="width: 53%"
@keyup.enter="handleLogin">
@ -98,7 +89,7 @@
<div class="el-login-footer">
<span>版权所有(R){{ oem.copyrightyear }} {{ oem.compay }} 电话:{{ oem.phone }} E-mail:{{ oem.Email }} version:{{
oem.version
}}</span>
}}</span>
</div>
</div>
</template>
@ -106,8 +97,7 @@
<script setup>
import { ref, watch, getCurrentInstance, onMounted } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { useFingerprint } from '@/utils/useFingerprint';
import { getCodeImg, getInfo, getLocalconfig } from "@/api/login";
import { getCodeImg, getInfo, getLocalconfig, login } from "@/api/login";
import Cookies from "js-cookie";
import { encrypt, decrypt } from "@/utils/jsencrypt";
import useUserStore from '@/store/modules/user';
@ -127,25 +117,25 @@ const oem = ref({
Email: "",
copyrightyear: ""
});
const loginRef = ref(null); // 修复:直接用ref获取表单引用
const loginRef = useTemplateRef('loginRef');
const loginForm = ref({
username: "admin",
username: "",
password: "",
rememberMe: false,
code: "",
uuid: "",
loginParam: { loginYLJG: undefined, localid: undefined, loginYLJGName: undefined }
loginParam: { loginYLJG: 1, localid: undefined, loginYLJGName: '' }
});
const selectOptions = ref([]);
const loginRules = ref({ // 修复:改为ref响应式,方便动态修改
username: [{ required: true, trigger: "blur", message: "请输入您的账号" }],
// password: [{ required: true, trigger: "blur", message: "请输入您的密码" }],
hospid: [{ required: true, message: '请选择医疗机构', trigger: 'change' }],
const loginRules = ref({
'loginParam.loginYLJG': [{ required: true, message: '请选择医疗机构', trigger: 'change' }],
username: [{ required: true, trigger: "blur", message: "请输入您的工号" }],
password: [{ required: true, trigger: "blur", message: "请输入您的密码" }],
code: [{ required: true, trigger: "change", message: "请输入验证码" }]
});
const codeUrl = ref("");
const loading = ref(false);
const captchaEnabled = ref(true);
const captchaEnabled = ref(false);
const register = ref(false);
const redirect = ref(undefined);
@ -166,33 +156,37 @@ const handleChange = (value) => {
loginForm.value.loginParam.loginYLJGName = item?.name || '';
}
// 登录方法(修复proxy.$refs问题)
// 登录方法
const handleLogin = async () => {
loginForm.value.loginParam.loginYLJG
loading.value = true;
Cookies.set("czlisjy_username", loginForm.value.username, { expires: 30 });
Cookies.set("czlisjy_loginYLJG", loginForm.value.loginParam.loginYLJG, { expires: 30 });
Cookies.set("czlisjy_loginYLJGName", loginForm.value.loginParam.loginYLJGName, { expires: 30 });
// 调用action的登录方法
userStore.login(loginForm.value).then(() => {
const query = route.query;
const otherQueryParams = Object.keys(query).reduce((acc, cur) => {
if (cur !== "redirect") {
acc[cur] = query[cur];
}
return acc;
}, {});
const targetPath = redirect.value || "/";
if (route.path !== targetPath) {
router.push({ path: targetPath, query: otherQueryParams });
loginRef.value.validate((valid) => {
if (valid) {
loading.value = true;
Cookies.set("czlisjy_username", loginForm.value.username, { expires: 30 });
Cookies.set("czlisjy_loginYLJG", loginForm.value.loginParam.loginYLJG, { expires: 30 });
Cookies.set("czlisjy_loginYLJGName", loginForm.value.loginParam.loginYLJGName, { expires: 30 });
// loginForm.value.password = encrypt(loginForm.value.password); // 密码加密
userStore.login(loginForm.value).then(() => {
const query = route.query;
const otherQueryParams = Object.keys(query).reduce((acc, cur) => {
if (cur !== "redirect") {
acc[cur] = query[cur];
}
return acc;
}, {});
const targetPath = redirect.value || "/";
if (route.path !== targetPath) {
router.push({ path: targetPath, query: otherQueryParams });
}
}).catch(() => {
loading.value = false;
// 重新获取验证码
if (captchaEnabled.value) {
getCode();
}
});
}
}).catch(() => {
loading.value = false;
// 重新获取验证码
if (captchaEnabled.value) {
getCode();
}
});
})
};
// 获取验证码
@ -203,12 +197,6 @@ const getCode = () => {
codeUrl.value = "data:image/gif;base64," + res.img;
loginForm.value.uuid = res.uuid;
}
// 验证码关闭时移除校验规则,避免报错
if (!captchaEnabled.value) {
loginRules.value.code = [];
} else {
loginRules.value.code = [{ required: true, trigger: "change", message: "请输入验证码" }];
}
});
};
@ -216,53 +204,31 @@ const getCode = () => {
const getCookie = () => {
const cookieUsername = Cookies.get("czlisjy_username");
const cookieloginYLJG = Cookies.get("czlisjy_loginYLJG");
if (cookieUsername !== undefined && cookieUsername !== null && cookieUsername !== "") {
loginForm.value.username = cookieUsername;
loginForm.value.username = cookieUsername;
if (cookieloginYLJG) {
loginForm.value.loginParam.loginYLJG = Number(cookieloginYLJG);
loginForm.value.loginParam.loginYLJGName = selectOptions.value.find(item => item.id == cookieloginYLJG)?.name || '';
} else {
loginForm.value.loginParam.loginYLJG = selectOptions.value[0]?.id || 1;
loginForm.value.loginParam.loginYLJGName = selectOptions.value[0]?.name || '';
}
if (cookieloginYLJG !== undefined && cookieloginYLJG !== null && cookieloginYLJG !== "") {
loginForm.value.loginParam.loginYLJG = cookieloginYLJG;
}
// const cookieloginYLJGName = Cookies.get("czlisjy_loginYLJGName");
// if (cookieloginYLJGName !== undefined && cookieloginYLJGName !== null && cookieloginYLJGName !== "") {
// loginForm.value.loginParam.loginYLJGName = cookieloginYLJGName;
// }
};
// 获取本地配置
const Localconfig = (localid) => {
getLocalconfig({ localid }).then(res => {
const Localconfig = () => {
getLocalconfig().then(res => {
if (res) {
const { localconfig, hosplist, oem: oemData } = res;
mbStore.setDefaultConfig(localconfig)
if (oemData) oem.value = oemData;
if (JSON.stringify(selectOptions.value) !== JSON.stringify(hosplist)) {
selectOptions.value = hosplist || [];
// 判重后赋值,避免重复修改触发更新
if (!selectOptions.value.some(item => item.id === loginForm.value.hospid)) {
loginForm.value.loginParam.loginYLJG = selectOptions.value[0]?.id || 1;
loginForm.value.loginParam.loginYLJGName = selectOptions.value[0]?.name || '';
}
getCookie();
}
selectOptions.value = hosplist || [];
getCookie();
}
}).catch(err => {
console.error("获取本地配置失败:", err);
});
};
// 获取指纹并加载配置
const { getFingerprint } = useFingerprint();
const refreshFingerprint = async () => {
try {
const res = await getFingerprint();
loginForm.value.loginParam.localid = res.visitorId
Localconfig(res.visitorId);
} catch (err) {
console.error("获取指纹失败:", err);
Localconfig("default"); // 兜底使用默认ID
}
};
// Tab切换事件(移除activeName手动赋值,避免递归)
const handleClick = (tab) => {
@ -273,11 +239,9 @@ const handleClick = (tab) => {
}
};
// 页面挂载时初始化
onMounted(() => {
refreshFingerprint();
getCode();
});
Localconfig();
getCode();
</script>
<style lang='scss' scoped>

View File

@ -6,7 +6,7 @@
<el-col :span="4">
<el-form-item label="委托机构:" prop="srcHospName">
<el-input v-model="queryParams.srcHospName" :title="queryParams.srcHospName" :size="aotuSize" readonly
v-if="!checkRole(['admin'])" />
v-if="!checkDeptRole(['admin'])" />
<SelectTable v-model:data="queryParams.srcHospName" :fields="ksdhFields" :tableData="hosList" v-else
label="label" :size="aotuSize" value="label" placeholder="请选择委托机构" />
</el-form-item>
@ -75,7 +75,8 @@
</div>
<div>
<CustomTable ref="tableRefs" :data="tableData" :columns="columns" :config="tableConfig" :pagination="pagination"
@size-change="sizeChange" @page-change="currentChange" @row-click="rowHandle">
@size-change="sizeChange" @page-change="currentChange" @row-click="rowHandle" :enableColumnDrag="true"
@column-drag-end="handleColumnDragEnd">
<template #patAge="{ row }">
{{ row.patAge }}{{ formatDict(row.ageUnit, 'AU') }}
</template>
@ -85,6 +86,9 @@
<template #patSex="{ row }">
{{ row.patSex == 1 ? '男' : '女' }}
</template>
<template #brly="{ row }">
{{ formatDict(row.brly, 'PT') }}
</template>
</CustomTable>
</div>
<!-- 样本流程 -->
@ -116,24 +120,26 @@ import { listregdict } from "@/api/regional/dict/regdict";
import useUserStore from '@/store/modules/user'
import dayjs from 'dayjs';
import { getDictData, formatDict, dictData } from '@/hooks'
import { checkRole } from '@/utils/permission'
import { checkDeptRole } from '@/utils/permission'
const userStore = useUserStore()
const queryParams = ref({
pageSize: 50,
pageNum: 1,
srcHospName: userStore.sysLoginParam.loginYLJGName,
srcHospName: '',
times: [],
dateType: '登记时间'
})
const tableData = ref([])
const columns = ref([
{ prop: 'barcode', label: '条码号', align: 'center', visible: true, width: 150 },
{ prop: 'srcHospName', label: '委托机构', align: 'center', visible: true, width: 200 },
{ prop: 'brly', label: '病人来源', align: 'center', visible: true, width: 100, slot: "brly" },
{ prop: 'patId', label: '病人代号', align: 'center', visible: true, width: 100 },
{ prop: 'patName', label: '姓名', align: 'center', visible: true, width: 100 },
{ prop: 'patSex', label: '性别', align: 'center', visible: true, width: 60, slot: "patSex" },
{ prop: 'patAge', label: '年龄', align: 'center', visible: true, slot: "patAge", width: 60 },
{ prop: 'ch', label: '床号', align: 'center', visible: true, width: 60 },
{ prop: 'checkPUR', label: '申请项目', align: 'center', visible: true, width: 250 },
{ prop: 'orderTime', label: '申请时间', align: 'center', visible: true, width: 140 },
{ prop: 'sampleTypeName', label: '标本类型', align: 'center', visible: true, },
@ -144,6 +150,7 @@ const columns = ref([
{ prop: 'signInUserName', label: '签收人', align: 'center', visible: true, },
{ prop: 'signInTime', label: '签收时间', align: 'center', visible: true, width: 140 },
{ prop: 'dstHospName', label: '检测机构名称', align: 'center', visible: true, width: 150 },
{ prop: 'srcHospName', label: '委托机构', align: 'center', visible: true, width: 200 },
])
const tableConfig = ref({
border: true, // 边框
@ -152,6 +159,10 @@ const tableConfig = ref({
// fit: true, // 列宽自适应
})
const handleColumnDragEnd = (newColumns: any) => {
columns.value = newColumns.columns
}
const pagination = ref({
show: true,
total: 0,
@ -205,7 +216,6 @@ const resetHandle = () => {
pageSize: 50,
pageNum: 1,
dateType: '登记时间',
srcHospName: userStore.sysLoginParam.loginYLJGName,
}
getDays()
handleQuery()
@ -236,8 +246,21 @@ const getList = () => {
querySample(queryParams.value).then((res) => {
tableData.value = res.rows
pagination.value.total = res.total
tableRefs.value.setCurrentRow(res.rows[0])
rowHandle(res.rows[0])
if (res.rows.length > 0) {
tableRefs.value.setCurrentRow(res.rows[0])
rowHandle(res.rows[0])
} else {
timelineItems.value =
[
{ title: '检验申请', time: '' },
{ title: '标本采集', time: '' },
{ title: '标本送检', time: '' },
{ title: '标本签收', time: '' },
{ title: '上机检验', time: '' },
{ title: '结果审核', time: '' },
]
}
})
}
@ -245,6 +268,13 @@ const getDays = () => {
const end = dayjs().format('YYYY-MM-DD');
const start = dayjs().subtract(2, 'day').format('YYYY-MM-DD'); //add 时间往后
queryParams.value.times = [start, end];
// 医疗机构为1
if (userStore.sysLoginParam.loginYLJG == 1) {
queryParams.value.srcHospName = ''
} else {
queryParams.value.srcHospName = userStore.sysLoginParam.loginYLJGName
}
}
const hosList = ref([])
@ -252,7 +282,7 @@ const regdictList = ref([])
onMounted(() => {
getDays()
handleQuery()
listhospital().then((res) => {
listhospital({ pageSize: 100, pageNum: 1 }).then((res) => {
hosList.value = res.rows.map((item) => {
return {
label: item.hospitalName,
@ -264,7 +294,7 @@ onMounted(() => {
listregdict({ pageSize: 100, pageNum: 1, dictType: 'ZT' }).then((res) => {
regdictList.value = res.rows;
})
getDictData('AU')
getDictData('AU', 'PT')
})

View File

@ -51,6 +51,7 @@ const aotuSize = classCom.useAutoSize();
const queryParams = ref({
barcode: '',
})
const tableRefs = useTemplateRef('tableRefs')
const tableData = ref([])
const columns = ref([
{ type: 'selection', align: 'center', visible: true, width: 40 },
@ -123,6 +124,7 @@ const getList = () => {
sampleCollect({ barcode: queryParams.value.barcode }).then((res) => {
tableData.value.push(res.data)
queryParams.value.barcode = ''
tableRefs.value.toggleRowSelection(res.data, true)
})
}

View File

@ -8,7 +8,7 @@
<el-col :span="4">
<el-form-item label="委托机构:" prop="yljg">
<el-input v-model="queryParams.yljg" :title="queryParams.yljg" :size="aotuSize" readonly
v-if="!checkRole(['admin'])" />
v-if="!checkDeptRole(['admin'])" />
<SelectTable v-model:data="queryParams.yljg" :fields="ksdhFields" :tableData="hosList" v-else
label="label" :size="aotuSize" value="label" placeholder="请选择委托机构" />
</el-form-item>
@ -190,7 +190,7 @@ import * as echarts from 'echarts';
import { getDictData, formatDict, dictData } from '@/hooks'
import useUserStore from '@/store/modules/user'
import { listhospital } from '@/api/regional/dict/hospital';
import { checkRole } from '@/utils/permission'
import { checkDeptRole } from '@/utils/permission'
const userStore = useUserStore()
const aotuSize = classCom.useAutoSize();
const compactForm = ref<HTMLElement | null>(null);
@ -234,7 +234,7 @@ const queryParams = reactive<QueryParams>({
dybz: '',
pageNum: 1,
pageSize: 20,
yljg: userStore.sysLoginParam.loginYLJGName,
yljg: '',
});
const total = ref(0);
@ -247,7 +247,7 @@ const jzbz = ref()
const showSearch = ref(true);
const queryRef = ref()
// 项目点击数据
const Info = ref<any>({})
const Info = ref(null)
// 定义校验规则
const queryRules = ref({
// clientId: [
@ -311,29 +311,27 @@ const rows = ref<any[]>([])
const tableData = ref([])
// 配置项
const columns = ref([
// { type: 'selection', visible: true, align: 'center', width: 30, label: '多选框' },
{ prop: 'yljg', label: '委托机构', align: 'center', visible: true, width: 200 },
{ prop: 'dybz', label: '印', align: 'center', visible: true, slot: 'dybz', width: 40 },
{ prop: 'alarmflag', label: '危', align: 'center', visible: true, slot: 'alarmflag', width: 40 },
{ prop: 'brdh', label: '病人代号', align: 'center', visible: true, width: 100 },
{ prop: 'brlyname', label: '病人类型', align: 'center', visible: true, width: 80 },
{ prop: 'brxm', label: '病人姓名', align: 'center', visible: true, },
{ prop: 'brxbname', label: '性别', align: 'center', visible: true, width: 40 },
{ prop: 'ch', label: '床号', align: 'center', visible: true, width: 50 },
{ prop: 'sqh', label: '条码号', align: 'center', visible: true, width: 140 },
{ prop: 'barcode_zt', label: '状态', align: 'center', visible: true, width: 100, slot: 'barcode_zt' },
{ prop: 'jymd', label: '检验目的', align: 'center', visible: true, width: 200 },
{ prop: 'yblxname', label: '样本类型', align: 'center', visible: true, },
{ prop: 'sqsj', label: '申请时间', align: 'center', visible: true, width: 150 },
{ prop: 'sqh', label: '条码号', align: 'center', visible: true, width: 140 },
{ prop: 'confirmtime', label: '报告时间', align: 'center', visible: true, sortable: true, width: 150 },
{ prop: 'sjysname', label: '送检医生', align: 'center', visible: true, width: 80 },
{ prop: 'brlyname', label: '病人类型', align: 'center', visible: true, width: 80 },
{ prop: 'jyrq', label: '检验日期', align: 'center', visible: true, width: 100 },
{ prop: 'applyid', label: '申请单号', align: 'center', visible: true, width: 120 },
{ prop: 'ybh', label: '样本号', align: 'center', visible: true, width: 60 },
{ prop: 'yqmc', label: '仪器名称', align: 'center', visible: true, width: 150 },
{ prop: 'dybz', label: '印', align: 'center', visible: true, slot: 'dybz', width: 40 },
{ prop: 'jzbz', label: '急', align: 'center', visible: true, slot: 'jzbz', width: 40 },
{ prop: 'alarmflag', label: '危', align: 'center', visible: true, slot: 'alarmflag', width: 40 },
// { prop: 'yqdl', label: '仪器', align: 'center', visible: true, width: 100 },
{ prop: 'jcjg', label: '检验机构', align: 'center', visible: true, width: 150 },
{ prop: 'yljg', label: '委托机构', align: 'center', visible: true, width: 200 },
])
const selectionChange = (selection: any) => {
@ -397,11 +395,14 @@ const handleColumnDragEnd = (newColumns: any) => {
// 打印单张Pdf
const printPdf = () => {
if (!Info.value) return ElMessage.warning('请选择一条数据')
printLoading.value = true
reportPrintPdf({ bgdh: Info.value.bgdh }).then((res) => {
if (res.code == 0) {
if (!res.data) return ElMessage.warning('未找到打印文件')
classCom.printBase64PDF(res.data)
ElMessage.success('正在打印中...')
handleQuery()
}
}).finally(() => {
printLoading.value = false
@ -422,6 +423,9 @@ const cellStyleHd = ({ row, column, rowIndex, columnIndex }: {
if (column.label == "危" && row.alarmflag == "1") {
return { color: '#f00' };
}
if (row.dybz == 1) {
return { background: '#ccc' };
}
};
// 表格配置
@ -738,10 +742,18 @@ onMounted(async () => {
const end = dayjs().format('YYYY-MM-DD');
const start = dayjs().subtract(2, 'day').format('YYYY-MM-DD'); //add 时间往后
queryParams.times = [start, end];
console.log('userStore.sysLoginParam==>', userStore.sysLoginParam);
// 医疗机构为1
if (userStore.sysLoginParam.loginYLJG == 1) {
queryParams.yljg = ''
} else {
queryParams.yljg = userStore.sysLoginParam.loginYLJGName
}
getList()
adjustTableHeight();
listhospital().then((res) => {
listhospital({ pageSize: 100, pageNum: 1 }).then((res) => {
hosList.value = res.rows.map((item) => {
return {
label: item.hospitalName,
@ -775,7 +787,7 @@ const getList = () => {
tableRefs.value.setCurrentRow(res.rows[0])
rowHandle(res.rows[0])
} else {
Info.value = {}
Info.value = null
rightTableData.value = []
bottomTableData.value = []
}