This commit is contained in:
tangw 2025-11-26 20:02:21 +08:00
commit ccce5849f8
85 changed files with 10035 additions and 1295 deletions

View File

@ -41,6 +41,7 @@
"vue-plugin-hiprint": "^0.0.60",
"vue-router": "4.2.5",
"vue3-print-nb": "^0.1.4",
"vue3-seamless-scroll": "^3.0.2",
"vue3-select2-component": "^0.1.7",
"vuedraggable": "^4.1.0",
"vxe-pc-ui": "^4.3.2",

13
pnpm-lock.yaml generated
View File

@ -92,6 +92,9 @@ importers:
vue3-print-nb:
specifier: ^0.1.4
version: 0.1.4(typescript@5.9.3)
vue3-seamless-scroll:
specifier: ^3.0.2
version: 3.0.2(vue@3.5.23(typescript@5.9.3))
vue3-select2-component:
specifier: ^0.1.7
version: 0.1.7
@ -2711,6 +2714,9 @@ packages:
vue3-print-nb@0.1.4:
resolution: {integrity: sha512-LExI7viEzplR6ZKQ2b+V4U0cwGYbVD4fut/XHvk3UPGlT5CcvIGs6VlwGp107aKgk6P8Pgx4rco3Rehv2lti3A==}
vue3-seamless-scroll@3.0.2:
resolution: {integrity: sha512-LpKoL1ht71MASabUBsoSqbhLqcuKSrD+u01dgHac+/cthPAShKvcdM7dSGtaxjVntSFqdeViqJssjcwy/KqRSA==}
vue3-select2-component@0.1.7:
resolution: {integrity: sha512-8UPZmFl02I47XwW+j8ICmHyAND8wfbavlvMrqh10wwdSVER1aF2kI9XCmfIrNlVQvxSbvc0mJjWQAHHSCW9dkw==}
@ -5611,6 +5617,13 @@ snapshots:
transitivePeerDependencies:
- typescript
vue3-seamless-scroll@3.0.2(vue@3.5.23(typescript@5.9.3)):
dependencies:
element-plus: 2.11.5(vue@3.5.23(typescript@5.9.3))
transitivePeerDependencies:
- '@vue/composition-api'
- vue
vue3-select2-component@0.1.7:
dependencies:
jquery: 3.7.1

View File

@ -6,13 +6,28 @@
import useSettingsStore from '@/store/modules/settings'
import { handleThemeStyle } from '@/utils/theme'
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
import { useFingerprint } from '@/utils/useFingerprint';
import { useCommonStore } from '@/store/modules/commonStore'
const mbStore = useCommonStore();
// 使用自定义hook获取指纹信息
const {
fingerprint,
loading,
error,
getFingerprint
} = useFingerprint();
onMounted(() => {
nextTick(() => {
// 初始化主题样式
handleThemeStyle(useSettingsStore().theme)
})
if (!mbStore.fingerprint) {
// 重新获取指纹
getFingerprint();
mbStore.setFingerprint(fingerprint)
}
})

View File

@ -0,0 +1,142 @@
// @ts-ignore
import request from '@/utils/request'
// 查询微生物数据列表
export function wswsampleList(query?: Object) {
return request({
url: '/lisworkgerm/wswsamplelist',
method: 'get',
params: query
})
}
// 查询微生物数据列表 分页
export function wswsamplelistpage(query?: Object) {
return request({
url: '/lisworkgerm/wswsamplelistpage',
method: 'get',
params: query
})
}
// 获取微生物样本信息
export function sampleMedInfo(query?: Object) {
return request({
url: '/lisworkgerm/getresultlist',
method: 'get',
params: query
})
}
// 获取药敏数据
export function getresultmedList(query?: Object) {
return request({
url: '/lisworkgerm/getresultmedlist',
method: 'get',
params: query
})
}
// 写入专家评语
export function savetestResult(query?: Object) {
return request({
url: '/lisworkgerm/savetestresult',
method: 'post',
data: query
})
}
// 获取操作记录
export function getComLog(query?: Object) {
return request({
url: '/lisworkgerm/getcomlog',
method: 'get',
params: query
})
}
//新增结果明细
export function newresult(data?: Object) {
return request({
url: '/lisworkgerm/newresult',
method: 'post',
data
})
}
//修改结果明细
export function changeresult(data?: Object) {
return request({
url: '/lisworkgerm/changeresult',
method: 'post',
data
})
}
//修改结果明细
export function saveresult(data?: Object) {
return request({
url: '/lisworkgerm/saveresult',
method: 'post',
data
})
}
//获取药敏字典
export function getmeddictList(data?: Object) {
return request({
url: '/lisworkgerm/getmeddict',
method: 'get',
params: data
})
}
//获取药敏模板
export function getmedgroupList(data?: Object) {
return request({
url: '/lisworkgerm/getmedgrouplist',
method: 'get',
params: data
})
}
//获取药敏模板明细
export function getmedgroupMbList(data?: Object) {
return request({
url: '/lisworkgerm/getmedgroup',
method: 'get',
params: data
})
}
//保存药敏结果
export function savemedresult(data?: Object) {
return request({
url: '/lisworkgerm/savemedresult',
method: 'post',
data
})
}
//保存所有药敏结果
export function savemedresultall(data?: Object) {
return request({
url: '/lisworkgerm/savemedresultall',
method: 'post',
data
})
}
//删除药敏结果
export function deletemedresult(data?: Object) {
return request({
url: '/lisworkgerm/deletemedresult',
method: 'post',
data
})
}
//获取培养基记录
export function getmediumList(data?: Object) {
return request({
url: '/lisworkgerm/getmedium',
method: 'get',
params: data
})
}
//微生物报告审核
export function cbebCheck(data?: Object) {
return request({
url: '/lisworkgerm/check',
method: 'get',
params: data
})
}

View File

@ -9,7 +9,6 @@ export function queryLabPatList(query?: Object) {
params: query
})
}
// 查询数据
export function queryLabPat(query?: Object) {
return request({

View File

@ -0,0 +1,41 @@
//知识库
// @ts-ignore
import request from '@/utils/request'
//查询数据
export function queryService(params:any){
return request({
url: '/xmKnowledge/query',
method: 'get',
params
})
}
//查询明细数据
export function queryDetailService(xmdh: string){
return request({
url: '/xmKnowledge/detail',
method: 'get',
params: {
xmdh
}
})
}
//新增数据
export function addService(params:any){
return request({
url: '/xmKnowledge/add',
method: 'post',
params
})
}
//删除数据
export function delService(params:any){
return request({
url: '/xmKnowledge/del',
method: 'get',
params
})
}

View File

@ -0,0 +1,39 @@
//仪器收费项目对照
// @ts-ignore
import request from '@/utils/request'
//查询已分配数据
export function queryService(params:any){
return request({
url: '/feeinstr/query',
method: 'get',
params
})
}
//查询未分配的项目数据
export function queryXmService(params:any){
return request({
url: '/feeinstr/queryXm',
method: 'get',
params
})
}
//新增数据
export function addService(params:any){
return request({
url: '/feeinstr/add',
method: 'post',
params
})
}
//删除数据
export function delService(params:any){
return request({
url: '/feeinstr/del',
method: 'delete',
params
})
}

View File

@ -33,3 +33,27 @@ export function querySampleSignBack(query?: Object) {
params: query
})
}
// 标本报表
export function sampleTypeCount(query?: Object) {
return request({
url: '/transitReport/sampleTypeCount',
method: 'get',
params: query
})
}
// 标本报表费用
export function sampleitemCount(query?: Object) {
return request({
url: '/transitReport/itemCount',
method: 'get',
params: query
})
}
// 标本报表费用
export function getallcount(query?: Object) {
return request({
url: '/transitstat/getallcount',
method: 'get',
params: query
})
}

View File

@ -42,3 +42,12 @@ export function paramTree(query?: Object) {
params: query,
});
}
// 查询某个参数
export function queryOneService(yq: string,xxdh: string) {
return request({
url: '/param/queryOne',
method: 'get',
params: {yq,xxdh}
});
}

View File

@ -97,3 +97,19 @@
font-size: 14px;
border-radius: 4px;
}
.btn_green {
background-color: #aef5ef !important;
color: #148A7F;
border-color: #aef5ef;
}
.btns_box {
padding: .3125rem .625rem !important;
font-size: .875rem;
height: 1.25rem !important;
margin: 5px 0;
margin-left: .625rem !important;
border-radius: 0 !important;
}

View File

@ -287,3 +287,20 @@ aside {
}
}
}
.next_box {
display: flex;
align-items: center;
justify-content: space-between;
.jtIcon {
width: 2.5rem;
height: 2rem;
line-height: 2rem;
font-size: 1rem;
text-align: center;
background-color: #1f6dd3;
color: #fff;
cursor: pointer;
}
}

View File

@ -106,13 +106,63 @@
.el-dialog:not(.is-fullscreen) {
margin-top: 6vh !important;
padding: 0;
// border-radius: 20px;
.el-dialog__body {
padding: 10px;
}
}
.el-dialog.scrollbar .el-dialog__body {
overflow: auto;
overflow-x: hidden;
max-height: 70vh;
padding: 10px 20px 0;
padding: 16px;
}
.el-dialog__header {
background: linear-gradient(90deg, #0c1a97 0%, #1373d3 100%);
padding: 10px 20px;
position: relative;
font-family: SourceHanSansCN, SourceHanSansCN;
&::before {
content: '';
position: absolute;
left: 20px;
top: 50%;
transform: translateY(-50%);
width: 28px;
height: 28px;
background: url('@/assets/logo/logo.png') no-repeat center;
background-size: contain;
z-index: 1;
}
// 标题文本样式
.el-dialog__title {
color: #fff;
/* 标题文字颜色 */
padding-left: 40px;
/* 给 Logo 留出空间 */
font-size: 16px;
font-weight: 600;
}
.el-dialog__headerbtn .el-dialog__close {
color: #fff;
/* 关闭按钮颜色 */
font-size: 18px;
&:hover {
color: #fff;
}
}
}
.el-dialog__footer {
padding: 10px;
}
.el-table {
@ -125,7 +175,7 @@
word-break: break-word;
background-color: #1F6DD3 !important;
color: #FFF;
height: 1.875rem !important;
height: 1.6875rem !important;
font-size: .8125rem;
}
}
@ -136,6 +186,11 @@
}
}
.el-table__body td {
font-size: .8125rem;
}
/* 表格最外层边框(可选) */
.el-table--border {
@ -177,9 +232,12 @@
padding: 0 !important;
}
.el-table--default .cell {
.el-table--default {
.cell {
padding: 0 !important;
}
}
.el-table__cell {
padding: 0 !important;
@ -249,7 +307,7 @@
}
.el-input.is-disabled .el-input__inner {
-webkit-text-fill-color: #4e4c4c
-webkit-text-fill-color: #4e4c4c;
}
@ -337,11 +395,6 @@
cursor: pointer;
}
.btn_green {
background-color: #aef5ef !important;
color: #148A7F;
border-color: #aef5ef;
}
// 表格input宽度,表格select宽度
.full-width-input .el-input__inner .el-select__inner {

View File

@ -390,6 +390,13 @@ defineExpose({
}
:deep(.el-table__footer-wrapper tfoot td.el-table__cell) {
color: #1f6dd3 !important;
font-weight: 700;
/* 可替换为任意颜色值 */
}

View File

@ -114,7 +114,7 @@ setTimeout(() => {
.scroll-btn {
width: 1.875rem;
height: 3rem;
height: 2.9375rem;
display: flex;
align-items: center;
justify-content: center;
@ -173,8 +173,8 @@ setTimeout(() => {
font-size: 1rem;
color: #1F6DD3;
width: 5.625rem;
height: 3rem;
line-height: 3rem;
height: 2.9375rem;
line-height: 2.9375rem;
text-align: center;
flex-shrink: 0;
cursor: pointer;

View File

@ -13,13 +13,16 @@
<template>
<div class="common-table-container">
<vxe-table :data="tableData" :loading="loading" border height="auto" class="common-table" :row-config="rowConfig"
:show-overflow="showOverflow" @current-change="handleRowClick" ref="tableRef" :size="size"
:current-row="currentRow" :highlight-current-row="highlightCurrentRow" :scroll-y="scrollYConfig"
<vxe-table :data="tableData" :loading="loading" border height="auto" :checkbox-config="config.checkboxConfig"
@checkbox-change="handleCheckboxChange" :row-config="rowConfig" :show-overflow="showOverflow"
@current-change="handleRowClick" ref="tableRef" :size="size" :current-row="currentRow"
:highlight-current-row="highlightCurrentRow" :scroll-y="scrollYConfig"
:header-cell-class-name="enableColumnDrag ? 'el-table-header-cell' : ''" v-bind="$attrs">
<!-- 动态渲染列 -->
<template v-for="(column, i) in columns" :key="`${column.field}-${i}`">
<vxe-column v-bind="column">
<vxe-column type="checkbox" width="40" align="center" v-if="column.type == 'selection'" />
<vxe-column type="seq" width="40" :title="column.title || '序号'" align="center" v-if="column.type == 'seq'" />
<vxe-column v-bind="column" v-if="column.field">
<!-- 自定义列模板 -->
<template v-if="column.slotName" #default="scope">
<slot :name="column.slotName" :row="scope.row"></slot>
@ -66,6 +69,11 @@ const props = defineProps({
type: Object,
default: () => ({ isHover: true, height: 30 })
},
// 表格配置
config: {
type: Object,
default: () => ({}),
},
// 是否显示内容溢出省略
showOverflow: {
type: Boolean,
@ -94,7 +102,7 @@ const props = defineProps({
}
})
const emits = defineEmits(['current-change', "column-drag-end",])
const emits = defineEmits(['current-change', "column-drag-end", "selection-change"])
const tableRef = ref<any>(null)
const currentRow = ref<any>(null)
@ -104,6 +112,23 @@ const handleRowClick = (params: { row: any }) => {
emits('current-change', params.row)
}
const handleCheckboxChange = ({ checked, records }: { checked: boolean, records: any[] }) => {
// console.log('选中的数据:', records);
// console.log('是否全选:', checked);
emits('selection-change', records)
};
// 处理行选择
const toggleRowSelection = (row: any, checked: boolean) => {
if (tableRef.value) {
tableRef.value.setCheckboxRow(row, checked)
}
}
// 获取所有选中行数据
const allSelection = () => {
return tableRef.value.getCheckboxRecords()
}
// 设置当前行
const setCurrentRow = (row: any) => {
if (tableRef.value) {
@ -180,6 +205,8 @@ const initColumnDrag = () => {
defineExpose({
setCurrentRow,
clearCurrentRow,
toggleRowSelection,
allSelection,
tableRef,
})
</script>

View File

@ -25,6 +25,9 @@ export const getDictData = async (...args: string[]) => {
if(dictRefs.ITEMCLASS != undefined) dictData.value.ITEMCLASS = toRaw(dictRefs.ITEMCLASS.value) || []
if(dictRefs.YQDL != undefined) dictData.value.YQDL = toRaw(dictRefs.YQDL.value) || []
if(dictRefs.VA != undefined) dictData.value.VA = toRaw(dictRefs.VA.value) || []
if(dictRefs.LF != undefined) dictData.value.LF = toRaw(dictRefs.LF.value) || []
if(dictRefs.BT != undefined) dictData.value.BT = toRaw(dictRefs.BT.value) || []
if(dictRefs.SLZQ != undefined) dictData.value.SLZQ = toRaw(dictRefs.SLZQ.value) || []
}
//字典数据格式化方法

View File

@ -71,6 +71,7 @@ import TreeSelect from '@/components/TreeSelect'
// 字典标签组件
import DictTag from '@/components/DictTag'
import print from 'vue3-print-nb';
import Vue3SeamlessScroll from 'vue3-seamless-scroll' // 引入插件
const app = createApp(App)
// 全局方法挂载
@ -97,6 +98,7 @@ app.component('Editor', Editor)
//VUE3标准方法注入全局方法
app.provide('comDict', comDict);
app.use(print); // 注册打印插件
app.use(Vue3SeamlessScroll)
app.provide('$vuePrint', app.config.globalProperties.$vuePrint);
app.use(router)
app.use(store)

View File

@ -21,7 +21,7 @@ NProgress.configure({
showSpinner: false
});
const whiteList = ['/login', '/register', '/report'];
const whiteList = ['/login', '/register', '/report', '/checkCode'];
router.beforeEach((to, from, next) => {
NProgress.start()

View File

@ -52,6 +52,12 @@ export const constantRoutes = [{
component: () => import('@/views/checkCode/report'),
hidden: true
},
{
path: '/checkCode',
component: () => import('@/views/checkCode/index'),
hidden: true
},
{
path: "/:pathMatch(.*)*",
component: () => import('@/views/error/404'),
@ -62,6 +68,12 @@ export const constantRoutes = [{
component: () => import('@/views/error/401'),
hidden: true
},
// 大屏
{
path: '/regional/statistics/overview',
component: () => import('@/views/regional/statistics/overview/index'),
hidden: true
},
{
path: '',
component: Layout,

View File

@ -4,10 +4,15 @@ import { defineStore } from 'pinia'
export const useCommonStore = defineStore('commonStore', {
state: () => ({
lxsrs: [] as string[], // 存储项目模板名称
fingerprint: '',// 存储指纹信息
}),
actions: {
setLxsrList(list: any[]) {
this.lxsrs = list
},
setFingerprint(fingerprint: string) {
this.fingerprint = fingerprint
},
}
})

View File

@ -28,11 +28,15 @@ const useUserStore = defineStore(
loginAnonymous(data) {
return new Promise((resolve, reject) => {
loginAnonymous({
username: data.name
username: data.name,
yljg: data.yljg
}).then(res => {
if (res.code == 200) {
setToken(res.token)
this.token = res.token
resolve()
resolve(true)
}
}).catch(error => {
reject(error)
})

44
src/types/Object.d.ts vendored
View File

@ -15,6 +15,10 @@ export interface DictData {
YQDL?: Array<any>;
xmlbList?: Array<any>;
YQ?: Array<any>;
VA?: Array<any>;
LF?: Array<any>;
BT?: Array<any>;
SLZQ?: Array<any>;
[key: string]: any[] | undefined; // 添加索引签名以支持动态访问
}
@ -114,3 +118,43 @@ export class XmValNew {
jgbz?: string;
}
export class XmInfoVs {
yq: string;
xmid: number;
xs?: number;
zkxm?: string;
cksx?: number;
ckxx?: number;
dyckz?: string;
}
export class XmTextresultNew {
xmid?: string;
xmdh?: string;
xh?: number;
textresult?: string;
}
export class LabResultItem {
xmdh: string;
xmmc: string;
csjg: string;
qz: string;
[key: string]: any;
}
export class ymTableDataItem {
zhywdh: string;
ywdh: any;
ywmc: any;
mic: string;
rad: string;
csjg: string;
jgbz: string;
ckz: string;
bz: string;
txtresult: string;
cp_bz: string;
}

View File

@ -3,8 +3,8 @@ import mitt, { Emitter, EventType } from "mitt"
// 扩展原始Emitter类型,添加自定义方法
interface CustomEmitter extends Emitter<Record<EventType, unknown>> {
emitWithCache?: (eventName: string, data: any) => void
getCache?: (eventName: string) => any
emitWithCache: (eventName: string, data: any) => void
getCache: (eventName: string) => any
}
const emitter = mitt() as CustomEmitter

View File

@ -41,7 +41,7 @@ export function useFingerprint() {
// 组件挂载时自动获取指纹
onMounted(() => {
getFingerprint();
// getFingerprint();
});
return {

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

@ -9,24 +9,23 @@
value-format="YYYY-MM-DD HH:mm:ss" @change="handletime" style="width: 25rem;" />
</el-form-item>
<el-form-item label="医疗机构:" prop="yljg">
<!-- <el-form-item label="医疗机构:" prop="yljg">
<el-select v-model="queryParams.yljg" placeholder="请选择" style="width: 9.37rem;">
<el-option v-for="item in dictData.HOS" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-form-item> -->
<el-form-item label="条码状态:" prop="zt">
<el-select v-model="queryParams.zt" placeholder="请选择" style="width: 6.25rem;">
<el-select v-model="queryParams.zt" placeholder="请选择" style="width: 8rem;">
<el-option v-for="item in dictData.ST" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="" prop="failed4">
<el-select v-model="queryParams.failed4" placeholder="请选择" style="width:8.75rem">
<el-form-item label="" prop="queryType">
<el-select v-model="queryParams.queryType" placeholder="请选择" style="width:10rem">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="" prop="failed5">
<el-input v-model="queryParams.failed5" clearable placeholder="条件搜索" @keyup.enter="handleQuery"
@clear="handleQuery" />
<el-form-item label="" prop="queryValue">
<el-input v-model="queryParams.queryValue" clearable placeholder="条件搜索" @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="">
@ -72,8 +71,10 @@
:columns="columns"></right-toolbar> -->
</el-row>
<CustomTable ref="tableRef" :data="tableData" :columns="columns" :config="tableConfig" :loading="loading"
@row-click="rowHandle" @selection-change="selectionChange" :enable-column-drag="true"
<VxeTable :table-data="tableData" :loading="loading" :columns="columns"
:row-config="{ isHover: true, keyField: 'ybh' }" @current-change="rowHandle" size="small"
:row-style="rowClassNameHd" :cell-style="cellStyleHd" class="mytable-style" ref="tableRef"
@selection-change="selectionChange" :config="tableConfig" :enable-column-drag="true"
@column-drag-end="handleColumnDragEnd">
<template #dy="{ row }">
<svg-icon v-if="row.zt != 1" icon-class="lvgou" />
@ -93,12 +94,12 @@
<template #yljg="{ row }">
{{ formatDict(row.yljg, 'HOS') }}
</template>
</CustomTable>
</VxeTable>
</el-col>
<el-col :span="8" class="right-table">
<!-- <div class="title"> 项目 </div> -->
<el-button type="primary" plain class="mb8" :size="aotuSize">拆分选中项目</el-button>
<div class="mb8" style="height:2rem"> </div>
<!-- <el-button type="primary" plain class="mb8" :size="aotuSize">拆分选中项目</el-button> -->
<CustomTable :data="rightTableData" :columns="rightColumns" :config="rightTableConfig">
<template #jjzt="{ row }">
{{ row.jjzt == '1' ? '计价' : '无' }}
@ -160,14 +161,20 @@ 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 { useRouter } from 'vue-router'
import VxeTable from '@/components/vxeTable/index.vue'
import { useRouter, useRoute } from 'vue-router'
import { usePrintStore } from '@/store/modules/printStore'
import { fetchCodeList, addObj, fetchCodeDetail, fetchCodeExec, fetchCodeReqmain } from '@/api/checkCode/index'
const aotuSize = classCom.useAutoSize();
//@ts-ignore
import useUserStore from '@/store/modules/user'
//@ts-ignore
import { comDict } from '@/utils/dict'
import { ElMessage, ElMessageBox } from 'element-plus'
import dayjs from 'dayjs';
const router = useRouter()
const route = useRoute()
const userStore = useUserStore()
const printStore = usePrintStore();
const compactForm = ref<HTMLElement | null>(null);
const heightForm = ref(90);
@ -179,8 +186,10 @@ interface QueryParams {
times: string[]; // 明确类型为字符串元组
yljg: string;
zt: string;
failed4: string;
failed5: string;
queryType: string;
queryValue: string;
ksdh: string;
userid: string;
}
// 提交表单数据
const queryParams = reactive<QueryParams>({
@ -188,8 +197,10 @@ const queryParams = reactive<QueryParams>({
// times: [],
yljg: '1',
zt: '',
failed4: '',
failed5: '',
queryType: '',
queryValue: '',
ksdh: '',
userid: ''
});
const showSearch = ref(true);
const queryRef = ref()
@ -206,15 +217,15 @@ const queryRules = ref({
})
const options = [
{
value: '1',
value: 'brxm',
label: '通过姓名搜索',
},
{
value: '2',
value: 'brdh',
label: '通过病人号搜索',
},
{
value: '3',
value: 'ch',
label: '通过床号搜索',
},
]
@ -233,40 +244,39 @@ const handleQuery = async () => {
// 重置
const resetQuery = () => {
queryRef.value?.resetFields();
queryParams.zt = ''
queryParams.queryType = ''
queryParams.queryValue = ''
getList()
}
const loading = ref(true);
const loading = ref(false);
// 数据源
const tableData = ref([])
// 配置项
const columns = ref([
{ type: 'selection', visible: true, align: 'center', width: 35, label: '多选框' },
// { type: 'index', visible: true, align: 'center', width: 60, label: '序号' },
{ prop: 'zt', label: '打印', visible: true, align: 'center', slot: 'dy', width: 40 },
{ prop: 'jzbz', label: '急', align: 'center', visible: true, slot: 'jzbz', width: 30 },
{ prop: 'ch', label: '床号', visible: true, align: 'center', width: 40 },//sortable: true,
{ prop: 'brxm', label: '姓名', align: 'center', visible: true, width: 50 },
{ prop: 'brxbname', label: '性别', align: 'center', visible: true, width: 30 },
{ prop: 'jymd', label: '项目名称', visible: true, width: 130 },
{ prop: 'bgddhname', label: '类别', align: 'center', visible: true, width: 80 },
{ prop: 'sampletips', label: '采样提示', align: 'center', visible: true, width: 60 },
{ prop: 'yblx', label: '样本类型', align: 'center', visible: true, width: 60 },
{ prop: 'brdh', label: '病人号', align: 'center', visible: true, width: 90 },
{ prop: 'ksname', label: '科室名称', align: 'center', visible: true, width: 100 },
{ prop: 'sqh', label: '申请号/条码', align: 'center', visible: true, width: 100 },
{ prop: 'zt', label: '状态', align: 'center', visible: true, slot: 'zt', width: 40 },
{ prop: 'brly', label: '病人来源', align: 'center', visible: true, slot: 'brly', width: 60 },
{ prop: 'sqysname', label: '申请医生', align: 'center', visible: true, width: 60 },
{ prop: 'sqsj', label: '申请时间', align: 'center', visible: true, width: 150 },
{ prop: 'jjzt', label: '计价标志', align: 'center', visible: true, slot: 'jjzt', width: 60 },
{ prop: 'zxysname', label: '执行医生', align: 'center', visible: true, width: 60 },
{ prop: 'bbsjrname', label: '送检人', align: 'center', visible: true, width: 50 },
{ prop: 'yljg', label: '医疗机构', align: 'center', visible: true, slot: 'yljg', width: 150 },
{ type: 'selection', field: '', title: '', resizable: true, align: 'center', width: 40 },
{ field: 'zt', title: '打印', resizable: true, align: 'center', slotName: 'dy', width: 40 },
{ field: 'jzbz', title: '急', align: 'center', resizable: true, slotName: 'jzbz', width: 30 },
{ field: 'ch', title: '床号', resizable: true, align: 'center', width: 40 },//sortable: true,
{ field: 'brxm', title: '姓名', align: 'center', resizable: true, width: 50 },
{ field: 'brxbname', title: '性别', align: 'center', resizable: true, width: 30 },
{ field: 'jymd', title: '项目名称', resizable: true, width: 130 },
{ field: 'bgddhname', title: '类别', align: 'center', resizable: true, width: 80 },
{ field: 'sampletips', title: '采样提示', align: 'center', resizable: true, width: 60 },
{ field: 'yblx', title: '样本类型', align: 'center', resizable: true, width: 60 },
{ field: 'brdh', title: '病人号', align: 'center', resizable: true, width: 90 },
{ field: 'ksname', title: '科室名称', align: 'center', resizable: true, width: 100 },
{ field: 'sqh', title: '申请号/条码', align: 'center', resizable: true, width: 100 },
{ field: 'zt', title: '状态', align: 'center', resizable: true, slotName: 'zt', width: 40 },
{ field: 'brly', title: '病人来源', align: 'center', resizable: true, slotName: 'brly', width: 60 },
{ field: 'sqysname', title: '申请医生', align: 'center', resizable: true, width: 60 },
{ field: 'sqsj', title: '申请时间', align: 'center', resizable: true, width: 150 },
{ field: 'jjzt', title: '计价标志', align: 'center', resizable: true, slotName: 'jjzt', width: 60 },
{ field: 'zxysname', title: '执行医生', align: 'center', resizable: true, width: 60 },
{ field: 'bbsjrname', title: '送检人', align: 'center', resizable: true, width: 50 },
{ field: 'yljg', title: '医疗机构', align: 'center', resizable: true, slotName: 'yljg', width: 150 },
])
const single = ref(true);
@ -280,11 +290,11 @@ const cellStyleHd = ({ row, column, rowIndex, columnIndex }: {
columnIndex: number;
}) => {
// console.log(row, column, rowIndex, columnIndex);
if (column.label == "急" && row.jzbz == "1") {
if (column.title == "急" && row.jzbz == "1") {
return { color: '#f00' };
}
if (column.label == "类别") {
if (column.title == "类别") {
const bgColor = classCom.decimalToHexColor(row.bkcolor);
const textColor = classCom.getContrastTextColor(bgColor);
return {
@ -326,6 +336,7 @@ const lastTimeIndex = computed(() => {
}
});
const Info: any = ref({})
// 点击行
const rowHandle = (row: any) => {
timelineItems.value =
@ -338,6 +349,7 @@ const rowHandle = (row: any) => {
{ title: '标本签收', time: row.jssj },
{ title: '结果审核', time: row.confirmtime },
]
Info.value = row
getRightTable(row)
};
@ -348,22 +360,26 @@ const selectionChange = (selection: any) => {
}
const handleColumnDragEnd = (data: any) => {
// 更新列配置
columns.value = data.columns;
// 可以在这里保存列顺序到本地存储等
// localStorage.setItem('tableColumnOrder', JSON.stringify(data.columns));
// 先清空再赋值,强制触发重新渲染
columns.value = [];
// 使用nextTick确保DOM更新后再设置新值
nextTick(() => {
columns.value = [...data.columns];
});
};
// 左侧表格配置
const tableConfig = ref({
// stripe: true, // 斑马纹
border: true, // 边框
index: true, // 序号
height: '', // 高度
highlightCurrentRow: true, // 高亮当前行
cellStyle: cellStyleHd,
rowClassName: rowClassNameHd,
fit: true
height: '76.5vh', // 高度
// 复选框配置
checkboxConfig: {
// 可选配置项
checkField: 'checked', // 绑定数据中的字段(默认:checked)
range: false, // 是否支持范围选择(按住 Shift 连续选择)
disabled: false, // 是否禁用全部复选框
reserve: false, // 是否保留勾选状态(分页/筛选时)
highlight: false // 是否高亮选中行
}
})
// 右侧数据源
const rightTableData = ref([])
@ -414,19 +430,20 @@ const cyTableConfig = ref({
// 采样登记
const openBlock = (value: string) => {
if (sqhs.value.length > 0) {
const selections = tableRef.value.allSelection()
if (selections.length > 0) {
ElMessageBox.confirm(`确定操作选中的数据吗?`, "提示", {
confirmButtonText: "确认",
cancelButtonText: "取消",
beforeClose: async (action, instance, done) => {
if (action === "confirm") {
// 生成请求Promise数组
const requests = sqhs.value.map((item: any) => { return item.sqh });
const requests = selections.map((item: any) => { return item.sqh });
fetchCodeExec({
sqh: requests.join(','),
userid: 'lis',
userid: queryParams.userid,
status: value == '采样登记' ? 12 : 13,
yljg: 1
yljg: queryParams.yljg
}).then((res: any) => {
if (res.code == 0) {
ElMessage.success('调用成功');
@ -456,9 +473,9 @@ const sqdQuery = () => {
if (res.code == 0 && res.data.sqh) {
fetchCodeExec({
sqh: res.data.sqh,
userid: 'lis',
userid: queryParams.userid,
status: 12,
yljg: 1
yljg: queryParams.yljg
})
cyTableData.value = cyTableData.value.concat(res.data)
}
@ -497,22 +514,25 @@ const getRightTable = (row: any) => {
const goReport = () => {
// 跳转到报告查询页面
router.push('/report?startdate=2025-08-19&endate=2025-08-19&deptcode=0210&userid=00910&brdh=')
router.push(`/report?yljg=${Info.value.yljg ? Info.value.yljg : queryParams.yljg}&deptcode=${Info.value.ksdh ? Info.value.ksdh : queryParams.ksdh}&userid=${queryParams.userid}&brdh=${Info.value.brdh ? Info.value.brdh : ''}`)
// router.push('/report?startdate=2025-08-19&endate=2025-08-19&deptcode=0210&userid=00910&brdh=')
};
const cancelHandle = () => {
if (sqhs.value.length <= 0) return ElMessage.warning('请选择数据!')
const selections = tableRef.value.allSelection()
if (selections.length <= 0) return ElMessage.warning('请选择数据!')
ElMessageBox.confirm(`确定作废选中的数据吗?`, "提示", {
confirmButtonText: "确认",
cancelButtonText: "取消",
beforeClose: async (action, instance, done) => {
if (action === "confirm") {
const requests = sqhs.value.map((item: any) => { return item.sqh });
const requests = selections.map((item: any) => { return item.sqh });
fetchCodeExec({
sqh: requests.join(','),
userid: 'lis',
userid: queryParams.userid,
status: 9,
yljg: 1
yljg: queryParams.yljg
}).then((res: any) => {
if (res.code == 0) {
ElMessage.success('调用成功');
@ -528,17 +548,31 @@ const cancelHandle = () => {
},
}).catch(() => { });
}
onMounted(async () => {
// 初始化3天区间(今天-前两天)
// const end = dayjs().format('YYYY-MM-DD HH:mm:ss');
// const start = dayjs().subtract(2, 'day').format('YYYY-MM-DD HH:mm:ss'); //add 时间往后
// queryParams.times = [start, end];
// console.log(queryParams.times);
// 获取当前日期(当天)
const today = dayjs();
// 计算前6天的日期(当天 + 前6天 = 7天)
const startOfWeek = today.subtract(6, 'day');
const startDate = route.query.startdate ? String(route.query.startdate) : startOfWeek.format('YYYY-MM-DD HH:mm:ss');
const endDate = route.query.endate ? String(route.query.endate) : today.format('YYYY-MM-DD HH:mm:ss');
queryParams.times = [startDate, endDate];
queryParams.ksdh = (route.query.deptcode as string) ? (route.query.deptcode as string) : '';
queryParams.userid = (route.query.userid as string) ? (route.query.userid as string) : '';
queryParams.yljg = (route.query.yljg as string) ? (route.query.yljg as string) : '1';
// 进入页面单点登录
const result = await userStore.loginAnonymous({ name: 'admin', yljg: queryParams.yljg })
if (result) {
getList()
}
adjustTableHeight();
// 加载病人来源字典
const dictRefs = await comDict('PT', 'HOS', 'ST');
@ -567,20 +601,25 @@ function adjustTableHeight() {
if (compactForm.value) {
// 获取高度
heightForm.value = compactForm.value.offsetHeight;
tableConfig.value.height = `calc(74vh - ${heightForm.value}px)`; // 设置表格容器的高度
rightTableConfig.value.height = `calc(74vh - ${heightForm.value}px)`;
tableConfig.value.height = `calc(80vh - ${heightForm.value}px)`; // 设置表格容器的高度
rightTableConfig.value.height = `calc(80vh - ${heightForm.value}px)`;
}
}
const handletime = (val: Array<string>) => {
// console.log('时间', val);
// 校验日期格式
const dayDiff = getDayDiff(val[0], val[1]);
if (dayDiff === -1) return ElMessage.warning('请选择有效的日期范围');
//校验是否超过7天
if (dayDiff > 7) return ElMessage.warning('查询时间范围不能超过7天,请重新选择');
}
// 生成条码
const printHandle = () => {
const data = {
dept: '0235',
userid: 'lis',
dept: queryParams.ksdh,
userid: queryParams.userid,
st: '',
et: '',
yljg: queryParams.yljg
@ -588,25 +627,61 @@ const printHandle = () => {
if (queryParams.times && queryParams.times.length) {
data.st = queryParams.times[0]
data.et = queryParams.times[1]
} else {
data.st = ''
data.et = ''
}
addObj(data).then((res: any) => {
if (res.code == 0) {
getList()
}
})
}
// 计算两个日期的天数差(支持带时分秒)
const getDayDiff = (start: string, end: string): number => {
const startTime = new Date(start).getTime();
const endTime = new Date(end).getTime();
// 校验日期有效性
if (isNaN(startTime) || isNaN(endTime)) {
return -1; // 无效日期
}
// 计算毫秒差 → 转换为天数(向上取整,避免因时分秒导致的误差)
return Math.ceil((endTime - startTime) / (24 * 60 * 60 * 1000));
};
// 查询申请单
const getList = () => {
loading.value = true;
const data = {
dept: '0235',
userid: 'lis',
dept: queryParams.ksdh,
userid: queryParams.userid,
st: queryParams.times[0],
et: queryParams.times[1],
yljg: queryParams.yljg
yljg: queryParams.yljg,
queryType: queryParams.queryType,
queryValue: queryParams.queryValue
}
if (!data.yljg) return ElMessage.warning('医疗机构不能为空!')
if (!data.dept) return ElMessage.warning('科室代号不能为空!')
if (!data.userid) return ElMessage.warning('用户userid不能为空!')
// 校验日期格式
const dayDiff = getDayDiff(queryParams.times[0], queryParams.times[1]);
if (dayDiff === -1) return ElMessage.warning('请选择有效的日期范围');
//校验是否超过7天
if (dayDiff > 7) return ElMessage.warning('查询时间范围不能超过7天,请重新选择');
if (queryParams.times && queryParams.times.length > 0) {
data.st = queryParams.times[0]
data.et = queryParams.times[1]
} else {
data.st = ''
data.et = ''
}
loading.value = true;
fetchCodeList(data).then((response: any) => {
if (response.code == 0) {
loading.value = false;
@ -621,28 +696,30 @@ const getList = () => {
}
const selectStatusRows = () => {
tableRef.value.clearSelection()
tableData.value.forEach((item: any) => {
if (item.zt == 1) {
tableRef.value.toggleRowSelection(item, true)
} else {
tableRef.value.toggleRowSelection(item, false)
}
})
}
// 打印pdf
const printPdf = () => {
if (sqhs.value.length <= 0) return ElMessage.warning('请选择数据!')
const selections = tableRef.value.allSelection()
if (selections.length <= 0) return ElMessage.warning('请选择数据!')
ElMessageBox.confirm(`确定打印选中的数据吗?`, "提示", {
confirmButtonText: "确认",
cancelButtonText: "取消",
beforeClose: async (action, instance, done) => {
if (action === "confirm") {
const requests = sqhs.value.map((item: any) => { return item.sqh });
const requests = selections.map((item: any) => { return item.sqh });
fetchCodeExec({
sqh: requests.join(','),
userid: 'lis',
userid: queryParams.userid,
status: 11,
yljg: 1
yljg: queryParams.yljg
}).then((res: any) => {
if (res.code == 0) {
done();
@ -659,12 +736,17 @@ const printPdf = () => {
</script>
<style scoped lang="scss">
.mytable-style {
height: 76.5vh;
}
.custom-row-class {
background-color: #c6c3ff !important;
/* 设置行背景色 */
}
.right-table {
margin-top: .625rem;
border: 1px solid #E1E9F7;
padding-top: .3125rem;
}
@ -683,6 +765,7 @@ const printPdf = () => {
margin-top: .35rem;
background-color: #f0f3f8;
padding: .3rem 2.5rem;
margin-top: .625rem;
}
.time-line-item {
@ -690,6 +773,7 @@ const printPdf = () => {
align-items: center;
justify-content: space-around;
width: 16.6%;
// padding: 0 30px;
.timeline-content {

View File

@ -7,7 +7,8 @@
<el-col :span="5">
<el-form-item label="日期:" prop="times">
<el-date-picker v-model="queryParams.times" type="daterange" range-separator="-"
start-placeholder="开始时间" end-placeholder="结束时间" format="YYYY-MM-DD" value-format="YYYY-MM-DD" />
start-placeholder="开始时间" end-placeholder="结束时间" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
@change="handletime" />
</el-form-item>
</el-col>
<el-col :span="5">
@ -87,9 +88,13 @@
:columns="columns"></right-toolbar> -->
</el-row>
<CustomTable ref="tableRefs" :data="tableData" :columns="columns" :config="tableConfig" :loading="loading"
<!-- <CustomTable ref="tableRefs" :data="tableData" :columns="columns" :config="tableConfig" :loading="loading"
@selection-change="selectionChange" @row-click="rowHandle" :enableColumnDrag="true"
@column-drag-end="handleColumnDragEnd">
@column-drag-end="handleColumnDragEnd"> -->
<VxeTable :table-data="tableData" :loading="loading" :columns="columns"
:row-config="{ isHover: true, keyField: 'ybh' }" @current-change="rowHandle" size="small"
class="mytable-style" ref="tableRefs" :cell-style="cellStyleHd" @selection-change="selectionChange"
:config="tableConfig" :enable-column-drag="true" @column-drag-end="handleColumnDragEnd">
<template #dybz="{ row }">
<svg-icon v-if="row.dybz == 1" icon-class="lvgou" />
</template>
@ -99,7 +104,7 @@
<template #jzbz="{ row }">
{{ row.jzbz == 1 ? '急' : '' }}
</template>
</CustomTable>
</VxeTable>
</el-col>
<el-col :span="8" class="right-table">
@ -167,6 +172,7 @@
<script setup lang="ts">
import { ref, reactive, toRaw, computed, watch, nextTick, onMounted } from 'vue';
import CustomTable from '@/components/elTable/index.vue'
import VxeTable from '@/components/vxeTable/index.vue'
import { useRouter } from 'vue-router'
import { reportList, reportPrintPdf, reportResult, reportMedList, reportFsresult } from '@/api/checkCode/index'
import dayjs from 'dayjs';
@ -206,7 +212,8 @@ interface QueryParams {
ch: string,
dybz: string,
sqh: string,
userid: string
userid: string,
yljg: string,
}
// 提交表单数据
@ -222,22 +229,9 @@ const queryParams = reactive<QueryParams>({
brdh: '',
ch: '',
dybz: '',
userid: ''
userid: '',
yljg: ''
});
// 获取当前日期(当天)
const today = dayjs();
// 计算前6天的日期(当天 + 前6天 = 7天)
const startOfWeek = today.subtract(6, 'day');
const startDate = route.query.startdate ? String(route.query.startdate) : startOfWeek.format('YYYY-MM-DD');
const endDate = route.query.endate ? String(route.query.endate) : today.format('YYYY-MM-DD');
queryParams.times = [startDate, endDate];
queryParams.ksdh = (route.query.deptcode as string) || '';
queryParams.userid = (route.query.userid as string) || '';
queryParams.brdh = (route.query.brdh as string) || '';
const single = ref(true);
const multiple = ref(true);
@ -249,16 +243,17 @@ const queryRef = ref()
const Info = ref<any>({})
// 定义校验规则
const queryRules = ref({
// clientId: [
// { required: true, message: '编号不能为空', trigger: 'blur' },
// ],
// failed3: [
// { required: true, message: '条码状态不能为空', trigger: 'change' },
// ],
})
const handletime = (val: Array<string>) => {
// console.log('时间', val);
// 校验日期格式
const dayDiff = getDayDiff(val[0], val[1]);
if (dayDiff === -1) return ElMessage.warning('请选择有效的日期范围');
//校验是否超过7天
if (dayDiff > 7) return ElMessage.warning('查询时间范围不能超过7天,请重新选择');
}
// 时间线数据
const timelineItems = ref(
@ -302,25 +297,25 @@ const rows = ref<any[]>([])
const tableData = ref([])
// 配置项
const columns = ref([
{ type: 'selection', visible: true, align: 'center', width: 30, label: '多选框' },
{ 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: 'brdh', label: '病人代号', align: 'center', visible: true, sortable: true, width: 100 },
{ 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: '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: '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: 'yljg', label: '医疗机构', align: 'center', visible: true, width: 150 },
{ prop: 'jyrqname', label: '检验日期', align: 'center', visible: true, width: 100 },
{ prop: 'ybh', label: '样本号', align: 'center', visible: true, width: 60 },
{ prop: 'yqmc', label: '仪器名称', align: 'center', visible: true, width: 150 },
{ prop: 'yqdl', label: '仪器', align: 'center', visible: true, width: 100 },
{ type: 'selection', field: '', title: '', resizable: true, align: 'center', width: 40 },
{ field: 'dybz', title: '印', align: 'center', resizable: true, slotName: 'dybz', width: 40 },
{ field: 'jzbz', title: '急', align: 'center', resizable: true, slotName: 'jzbz', width: 40 },
{ field: 'alarmflag', title: '危', align: 'center', resizable: true, slotName: 'alarmflag', width: 40 },
{ field: 'brdh', title: '病人代号', align: 'center', resizable: true, sortable: true, width: 100 },
{ field: 'brxm', title: '病人姓名', align: 'center', resizable: true, width: 60 },
{ field: 'brxbname', title: '性别', align: 'center', resizable: true, width: 40 },
{ field: 'ch', title: '床号', align: 'center', resizable: true, width: 50 },
{ field: 'jymd', title: '检验目的', align: 'center', resizable: true, width: 200 },
{ field: 'yblxname', title: '样本类型', align: 'center', resizable: true, width: 60 },
{ field: 'sqsj', title: '送检时间', align: 'center', resizable: true, width: 150 },
{ field: 'confirmtime', title: '报告时间', align: 'center', resizable: true, sortable: true, width: 150 },
{ field: 'sjysname', title: '送检医生', align: 'center', resizable: true, width: 80 },
{ field: 'brlyname', title: '病人类型', align: 'center', resizable: true, width: 80 },
{ field: 'yljg', title: '医疗机构', align: 'center', resizable: true, width: 150 },
{ field: 'jyrqname', title: '检验日期', align: 'center', resizable: true, width: 100 },
{ field: 'ybh', title: '样本号', align: 'center', resizable: true, width: 60 },
{ field: 'yqmc', title: '仪器名称', align: 'center', resizable: true, width: 150 },
{ field: 'yqdl', title: '仪器', align: 'center', resizable: true, width: 100 },
])
const selectionChange = (selection: any) => {
@ -374,18 +369,20 @@ const rowHandle = (row: any) => {
}
const handleColumnDragEnd = (newColumns: any) => {
columns.value = newColumns.columns
columns.value = [];
// 使用nextTick确保DOM更新后再设置新值
nextTick(() => {
columns.value = [...newColumns.columns];
});
}
// 打印单张Pdf
const printPdf = () => {
const printStore = usePrintStore();
const merge = rows.value.map((item: any) => { return `${item.jyrqname.replace(/-/g, '')}_${item.yq.trim()}_${item.ybh}` })
// const merge = [
// "20250819_11_1",
// "20250819_11_10",
// "20250819_11_11"
// ]
const selections = tableRefs.value.allSelection()
if (selections.length <= 0) return ElMessage.warning('请选择要打印的数据!')
const merge = selections.map((item: any) => { return `${item.jyrqname.replace(/-/g, '')}_${item.yq.trim()}_${item.ybh}` })
reportPrintPdf(merge).then((res: any) => {
if (res.code == 0) {
if (!res.data) return ElMessage.warning('未找到打印文件')
@ -407,32 +404,35 @@ const cellStyleHd = ({ row, column, rowIndex, columnIndex }: {
columnIndex: number;
}) => {
// console.log(row, column, rowIndex, columnIndex);
if (column.label == "急" && row.jzbz == "1") {
if (column.title == "急" && row.jzbz == "1") {
return { color: '#f00' };
}
if (column.label == "危" && row.alarmflag == "1") {
if (column.title == "危" && row.alarmflag == "1") {
return { color: '#f00' };
}
};
// 表格配置
const tableConfig = ref(
{
// stripe: true, // 斑马纹
border: true, // 边框
height: '', // 高度
highlightCurrentRow: true, // 高亮当前行
fit: true,
cellStyle: cellStyleHd
const tableConfig = ref({
height: '71vh', // 高度
// 复选框配置
checkboxConfig: {
// 可选配置项
checkField: 'checked', // 绑定数据中的字段(默认:checked)
range: false, // 是否支持范围选择(按住 Shift 连续选择)
disabled: false, // 是否禁用全部复选框
reserve: false, // 是否保留勾选状态(分页/筛选时)
highlight: false // 是否高亮选中行
}
)
})
// 勾选未打印
const selectStatusRows = () => {
tableRefs.value.clearSelection()
tableData.value.forEach((item: any) => {
if (item.dybz != 1) {
tableRefs.value.toggleRowSelection(item, true)
} else {
tableRefs.value.toggleRowSelection(item, false)
}
})
}
@ -497,7 +497,7 @@ const rightColumns = ref([
{ prop: 'refs', label: '参考值', align: 'center', visible: true, },
{ prop: 'dw', label: '单位', align: 'center', visible: true, },
{ prop: 'od', label: '菌落计数', align: 'center', visible: true, },
{ prop: 'jgbz', label: '结果标志', align: 'center', visible: true, slot: 'jgbz' },
// { prop: 'jgbz', label: '结果标志', align: 'center', visible: true, slot: 'jgbz' },
])
const rightCellStyleHd = ({ row, column, rowIndex, columnIndex }: {
@ -528,7 +528,7 @@ const rightTableConfig = ref(
{
// stripe: true, // 斑马纹
border: true, // 边框
height: '25vh', // 高度
height: '71vh', // 高度
highlightCurrentRow: true, // 高亮当前行
cellStyle: rightCellStyleHd
}
@ -555,12 +555,12 @@ const xmrowHandle = (row: any) => {
bottomTableData.value = res.rows
if (res.rows.length > 0) {
nextTick(() => {
rightTableConfig.value.height = `calc(35vh - ${heightForm.value}px)`
rightTableConfig.value.height = `25vh`
rightTableRef.value?.doLayout && rightTableRef.value.doLayout();
});
} else {
nextTick(() => {
rightTableConfig.value.height = `calc(83vh - ${heightForm.value}px)`
rightTableConfig.value.height = `71vh`
rightTableRef.value?.doLayout && rightTableRef.value.doLayout();
});
}
@ -614,41 +614,48 @@ interface copyItem {
refs: string | number;
dw: string;
jgbz: string;
od: string;
}
// 复制函数
const copyData = (type: string) => {
let str = ''
const getCommonRow = (item: copyItem) => `${item.xmdh}\t${item.xmmc}\t${item.csjg}\t${item.refs}\t${item.dw}\t${item.jgbz}\t\r\n`;
rightTableData.value.forEach((v: any) => {
if (type == 'All') {
str = str + getCommonRow(v)
// str = str + v.xmmc + v.csjg + v.dw + + ',';
let str = '';
// 处理空值的工具函数:null/undefined/空字符串都返回空白
const getFieldValue = (value: any) => {
if (value === null || value === undefined || value === '') {
return '';
}
if (type == 'N' && v.jgbz != 'M' && v.jgbz != '') {
str = str + getCommonRow(v)
}
if (type == 'Y' && v.jgbz == 'M' && v.jgbz != '') {
str = str + getCommonRow(v)
}
})
// 转换为字符串,避免数字等类型直接拼接
return String(value);
};
var input = document.createElement('textarea');
if (!str) return ElMessage.error('没有数据可复制');
// 把文字放进input中,供复制
// 根据设备类型定义不同的字段拼接逻辑
const getCommonRow = Info.value.yqdl === '细菌仪'
? (item: copyItem) => `${getFieldValue(item.xmdh)}\t${getFieldValue(item.xmmc)}\t${getFieldValue(item.csjg)}\t${getFieldValue(item.od)}\t\r\n`
: (item: copyItem) => `${getFieldValue(item.xmdh)}\t${getFieldValue(item.xmmc)}\t${getFieldValue(item.csjg)}\t${getFieldValue(item.refs)}\t${getFieldValue(item.dw)}\t\r\n`;
// 遍历数据拼接内容
rightTableData.value.forEach((v: any) => {
// 根据类型过滤数据
if (type === 'All' ||
(type === 'N' && v.jgbz !== 'M' && v.jgbz !== '') ||
(type === 'Y' && v.jgbz === 'M')) {
str += getCommonRow(v);
}
});
// 执行复制操作
const input = document.createElement('textarea');
if (!str) {
ElMessage.error('没有数据可复制');
return;
}
input.value = str;
document.body.appendChild(input);
// 选中创建的input
input.select();
var copy_result = document.execCommand('copy');
if (copy_result) {
ElMessage.success('复制成功');
} else {
ElMessage.error('复制失败');
}
// 移除
const copyResult = document.execCommand('copy');
copyResult ? ElMessage.success('复制成功') : ElMessage.error('复制失败');
document.body.removeChild(input);
}
};
// 数据重组
const formatGroupedData = (data: any[]) => {
if (!data || data.length === 0) return [];
@ -819,16 +826,27 @@ interface DictData {
// 字典数据存储
const dictData = ref<DictData>({});
onMounted(async () => {
// 初始化3天区间(今天-前两天)
// const end = dayjs().format('YYYY-MM-DD HH:mm:ss');
// const start = dayjs().subtract(1, 'day').format('YYYY-MM-DD HH:mm:ss'); //add 时间往后
// queryParams.times = [start, end];
// console.log(queryParams.times);
// 获取当前日期(当天)
const today = dayjs();
// 计算前6天的日期(当天 + 前6天 = 7天)
const startOfWeek = today.subtract(6, 'day');
const startDate = route.query.startdate ? String(route.query.startdate) : startOfWeek.format('YYYY-MM-DD');
const endDate = route.query.endate ? String(route.query.endate) : today.format('YYYY-MM-DD');
queryParams.times = [startDate, endDate];
queryParams.ksdh = (route.query.deptcode as string) ? (route.query.deptcode as string) : '';
queryParams.userid = (route.query.userid as string) ? (route.query.userid as string) : '';
queryParams.brdh = (route.query.brdh as string) ? (route.query.brdh as string) : '';
queryParams.yljg = (route.query.yljg as string) ? (route.query.yljg as string) : '1';
// 进入页面单点登录
userStore.loginAnonymous({ name: 'admin' })
const result = await userStore.loginAnonymous({ name: 'admin', yljg: queryParams.yljg })
if (result) {
getList()
adjustTableHeight();
}
// 加载病人来源字典
const dictRefs = await comDict('PT', 'DP');
@ -840,10 +858,21 @@ onMounted(async () => {
};
});
// 计算两个日期的天数差(支持带时分秒)
const getDayDiff = (start: string, end: string): number => {
const startTime = new Date(start).getTime();
const endTime = new Date(end).getTime();
// 校验日期有效性
if (isNaN(startTime) || isNaN(endTime)) {
return -1; // 无效日期
}
// 计算毫秒差 → 转换为天数(向上取整,避免因时分秒导致的误差)
return Math.ceil((endTime - startTime) / (24 * 60 * 60 * 1000));
};
const getList = () => {
if (!queryParams.ksdh) return ElMessage.error('科室代号不能为空');
if (!queryParams.userid) return ElMessage.error('用户userid不能为空');
const data = {
alarmflag: alarmflag.value,
jzbz: jzbz.value,
@ -856,14 +885,25 @@ const getList = () => {
userid: queryParams.userid,
st: '',
et: '',
yljg: 1,
yljg: queryParams.yljg,
}
if (!data.ksdh) return ElMessage.error('科室代号不能为空');
if (!data.yljg) return ElMessage.error('医疗机构yljg不能为空');
if (!data.userid) return ElMessage.error('用户userid不能为空');
// 校验日期格式
const dayDiff = getDayDiff(queryParams.times[0], queryParams.times[1]);
if (dayDiff === -1) return ElMessage.warning('请选择有效的日期范围');
//校验是否超过7天
if (dayDiff > 7) return ElMessage.warning('查询时间范围不能超过7天,请重新选择');
if (queryParams.times && queryParams.times.length) {
data.st = queryParams.times[0]
data.et = queryParams.times[1]
} else {
return ElMessage.error('日期时间段不能为空');
data.st = ''
data.et = ''
}
loading.value = true
reportList(data).then((res: any) => {
@ -881,28 +921,15 @@ const getList = () => {
})
}
// 计算table高度
watch(showSearch, () => {
nextTick(() => {
adjustTableHeight();
})
}, { immediate: true });
function adjustTableHeight() {
if (compactForm.value) {
heightForm.value = compactForm.value.offsetHeight;
nextTick(() => {
tableConfig.value.height = `calc(83vh - ${heightForm.value}px)`
tableRefs.value?.doLayout && tableRefs.value.doLayout();
});
}
}
</script>
<style scoped lang="scss">
.mytable-style {
height: 71vh;
}
.compact-form {
border-bottom: 1px solid #E1E9F7;
}
@ -988,7 +1015,7 @@ function adjustTableHeight() {
/* 超出部分隐藏 */
overflow: hidden;
/* 可选:设置行高和最大宽度,优化显示效果 */
line-height: 1.5;
line-height: 1.3;
/* 行高,根据字体大小调整 */
max-width: 100%;
pointer-events: auto;

View File

@ -5,20 +5,8 @@
</template>
<script setup>
import { useFingerprint } from '@/utils/useFingerprint';
// 使用自定义hook获取指纹信息
const {
fingerprint,
loading,
error,
getFingerprint
} = useFingerprint();
// 重新获取指纹
const refreshFingerprint = async () => {
await getFingerprint();
};
</script>
<style scoped></style>

View File

@ -26,6 +26,7 @@ onMounted(() => {
}
emitter.on('refreshClinical', (data) => {
console.log('data==>', data);
getClinicalInfo(data)
})
})

View File

@ -27,7 +27,7 @@ const props = defineProps({
})
const mbStore = useCommonStore();
const { queryParams } = toRefs(props);
const tableData = ref([])
const tableData: any = ref([])
const columns = ref([
{ prop: 'mbmc', label: '批输入模板', visible: true, align: 'center', },
{ prop: 'yblx', label: '标本类型', visible: true, align: 'center', width: 80 },
@ -41,7 +41,7 @@ const columns = ref([
// 左侧表格配置
const tableConfig = ref({
border: true, // 边框
height: '', // 高度
height: '82vh', // 高度
highlightCurrentRow: true, // 高亮当前行
})
const getCombination = () => {
@ -62,7 +62,6 @@ watch(() => props.queryParams.yq, (newValue) => {
const changeLxsr = (row: any) => {
const lxsrs = tableData.value.filter((item: any) => item.lxsr).map((item: any) => item.mbmc);
console.log('lxsrs==>', lxsrs);
mbStore.setLxsrList(lxsrs);
}
@ -70,6 +69,23 @@ const handleRowDblclick = (row: any) => {
emitter.emit('dbMbHandle', row);
}
const clearLxsr = () => {
tableData.value = tableData.value.map((item: any) => {
return {
...item,
lxsr: false,
}
})
mbStore.setLxsrList([]);
}
onMounted(() => {
// 模板渲染清楚标记
emitter.on('clearLxsrList', () => {
clearLxsr()
})
})
</script>
<style scoped lang="scss">

View File

@ -73,9 +73,9 @@
</el-col>
<!-- 右侧区域-->
<el-col :span="10" :xs="24">
<tabView :tabList="tabList" v-model:activeTab="activeTab" />
<tabView :tabList="tabList" v-model:activeTab="activeTab" @update:active-tab="updateActive" />
<KeepAlive>
<component class="tabDiv" :is="activeTabN" :dataList="tabDataList"></component>
<component class="tabDiv" :is="activeTabN" :dataList="tabDataList" :formData="selectRow"></component>
</KeepAlive>
</el-col>
</el-row>
@ -85,7 +85,7 @@
<script setup lang="ts">
import { onMounted, ref, toRaw, computed } from 'vue';
import Basic from './tab/base/Basic.vue'
import CommmonlyValues from '@/views/liswork/labItem/tab/CommmonlyValues.vue'
import CommonlyValues from '@/views/liswork/labItem/tab/CommonlyValues.vue'
import UseInstr from './tab/UseInstr.vue'
import Knowledge from './tab/Knowledge.vue'
import CommonDescriptions from './tab/CommonDescriptions.vue'
@ -131,10 +131,10 @@ const itemclassFields = ref([
const instrOptions = ref<LabInstr[]>([])
const tabList = ref([
{ label: '基本资料', value: 'Basic' },
{ label: '常用取值', value: 'CommmonlyValues' },
{ label: '常用取值', value: 'CommonlyValues' },
{ label: '使用仪器', value: 'UseInstr' },
{ label: '知识库', value: 'Knowledge' },
{ label: '整体排序', value: 'Sort' },
//{ label: '整体排序', value: 'Sort' },
{ label: '常见描述', value: 'CommonDescriptions' },
// { label: '参数', value: 7 },
// { label: '通道号', value: 8 },
@ -143,7 +143,7 @@ const tabList = ref([
const activeTab = ref('Basic')
const activeTabMap = {
Basic,
CommmonlyValues,
CommonlyValues,
UseInstr,
Knowledge,
Sort,
@ -195,7 +195,11 @@ const yqdlFields = ref([
])
//tab页数据
const tabDataList = ref<any>();
const tabDataList = ref<any>([]);
//选中行数据
const selectRow = ref();
//明细数据
const selectDetailRow = ref()
// 仪器
const getYqConfig = () => {
@ -258,28 +262,41 @@ const changeStauts = () => {
}
// 选择行变化
const rowChange = (row: any) => {
queryXmInfoNewDetailService(row.xmid,row.yq,row.xmdh).then((res: any) => {
const rowChange = async (row: any) => {
selectRow.value = row;
const res = await queryXmInfoNewDetailService(row.xmid,row.yq,row.xmdh)
selectDetailRow.value = res.data
console.log('明细数据:', res);
changeActiveTab()
}
//tab变化
const updateActive = () => {
changeActiveTab()
}
const changeActiveTab = () => {
switch(activeTab.value){
case 'Basic':
tabDataList.value = res.data.xmInfoNewRows[0];
tabDataList.value = selectDetailRow.value.xmInfoNewRows[0] || [];
break;
case 'CommmonlyValues':
tabDataList.value = res.data.xmValNewRows[0];
case 'CommonlyValues':
tabDataList.value = selectDetailRow.value.xmValNewRows[0] || [];
break;
case 'UseInstr':
tabDataList.value = res.data.xmInfoVsRows[0];
tabDataList.value = selectDetailRow.value.xmInfoVsRows[0] || [];
break;
case 'Knowledge':
//tabDataList.value = res.data.xmInfoVsRows[0];
case 'Sort':
case 'CommonDescriptions':
tabDataList.value = selectDetailRow.value.xmTextresultNewRows[0] || [];
break;
case 'ReferenceValueDetails':
tabDataList.value = selectDetailRow.value.xmRefNewRows[0] || [];
break;
}
console.log('明细数据:', res);
})
}
</script>

View File

@ -0,0 +1,102 @@
<!-- 常用取值 -->
<template>
<div>
<div class="modifyClass">
<el-button type="primary" @click="bClickAdd">增加</el-button>
<el-button type="primary" @click="bClickDel">删除</el-button>
</div>
<CustomTable ref="tableRef" :data="dataList" :columns="columns" :enable-column-drag="true" @column-drag-end="handleColumnDragEnd"
:config="tableConfig" @row-click="handRowClick">
<template #qz = {row}>
<el-select v-model="row.qz" clearable allow-create filterable default-first-option>
<el-option v-for="item in qzOptions" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
</template>
<template #jgbz = {row}>
<el-select v-model="row.jgbz" clearable>
<el-option v-for="item in jgbzOptions" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
</template>
<template #srm = {row}>
<el-input v-model="row.srm" class="full-width-input"></el-input>
</template>
</CustomTable>
</div>
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import { dictData,getDictData } from '@/hooks';
import { DictData, XmValNew } from '@/types';
import { ElMessageBox } from 'element-plus';
const props = defineProps({
dataList: {
type: Object,
default: []
},
formData: {
type: Object,
default: {}
}
});
const tableRef = ref<any>(null);
const dataList = ref<Array<XmValNew>>([]);
const columns = ref([
{ prop: 'qz', label: '取值', visible: true, align: 'center', slot:'qz', width: 200 },
{ prop: 'srm', label: '快速输入码', visible: true, align: 'center',slot: 'srm', width: 100 },
{ prop: 'jgbz', label: '结果标志', visible: true, align: 'center', slot: 'jgbz', width: 100 }
]);
const tableConfig = ref({
border: true, // 边框
height: '80vh', // 高度
highlightCurrentRow: true, // 高亮当前行
// cellStyle: cellStyleHd
})
const qzOptions = ref()
const selectRow = ref()
const jgbzOptions = ref()
//退拽属性
const handleColumnDragEnd = (data: any) => {
// 更新列配置
columns.value = data.columns;
}
const bClickAdd = () => {
const newData: XmValNew = {
xmid: props.formData.xmid,
qz: '',
srm: '',
jgbz: ''
}
dataList.value?.push(newData);
}
const bClickDel = async () => {
await ElMessageBox.confirm('是否要删除选中的数据?','Warning',
{
confirmButtonText: 'OK',
cancelButtonText: 'Cancel',
type: 'warning',
}
);
//删掉界面上面的数据
dataList.value = dataList.value?.filter(item => item.xh != selectRow.value.xh );
}
const handRowClick = (row:any) => {
selectRow.value = row
}
onActivated(async ()=>{
//默认取值
await getDictData('VA','LF')
qzOptions.value = dictData.value.VA
jgbzOptions.value = dictData.value.LF
})
</script>

View File

@ -286,10 +286,11 @@ const conditionClick = () => {
}
onMounted(() => {
getDictData('XMGL');
onActivated(async () => {
await getDictData('XMGL');
})
</script>

View File

@ -1,82 +0,0 @@
<!-- 常用取值 -->
<template>
<div>
<div class="modifyClass">
<el-button type="primary" @click="bClickAdd">增加</el-button>
<el-button type="primary" @click="bClickDel">删除</el-button>
</div>
<CustomTable ref="tableRef" :data="dataList" :columns="columns" :enable-column-drag="true" @column-drag-end="handleColumnDragEnd"
:config="tableConfig">
<template #qz>
<el-select v-model="selectValue" clearable>
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</template>
</CustomTable>
</div>
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import { dictData,getDictData } from '@/hooks';
import { XmValNew } from '@/types';
const props = defineProps({
formData: {
type: Object,
default: {}
}
});
const tableRef = ref<any>(null);
const dataList = ref();
const columns = ref([
{ prop: 'qz', label: '取值', visible: true, align: 'center', slot:'qz', width: 200 },
{ prop: 'srm', label: '快速输入码', visible: true, align: 'center', width: 100 },
{ prop: 'jgbz', label: '结果标志', visible: true, align: 'center', width: 100 }
]);
const tableConfig = ref({
border: true, // 边框
height: '80vh', // 高度
highlightCurrentRow: true, // 高亮当前行
// cellStyle: cellStyleHd
})
const options = ref()
const selectValue = ref()
//退拽属性
const handleColumnDragEnd = (data: any) => {
// 更新列配置
columns.value = data.columns;
}
const init = () => {
options.value = {...dictData.value}
}
const bClickAdd = () => {
const newData: XmValNew = {
xmid: props.formData.xmid,
qz: ''
}
dataList.value.push(newData);
}
const bClickDel = () => {
}
onMounted(()=>{
//默认取值
getDictData('VA')
init()
})
</script>

View File

@ -1,34 +1,42 @@
<template>
<!-- 常见描述 -->
<div>
<div>
<div class="modifyClass">
<el-button type="primary" @click="">增加</el-button>
<el-button type="primary" @click="">删除</el-button>
</div>
<CustomTable ref="tableRef" :data="dataList" :columns="columns" :enable-column-drag="true" @column-drag-end="handleColumnDragEnd"
:config="tableConfig"/>
<el-button type="primary" @click="onAddClick">增加</el-button>
<el-button type="primary" @click="onDelClick">删除</el-button>
</div>
<CustomTable ref="tableRef" :data="tableList" :columns="columns" :enable-column-drag="true" @column-drag-end="handleColumnDragEnd"
:config="tableConfig" @row-click="rowClick">
<template #textresult="{row}">
<el-input type="textarea" v-model="row.textresult" class="full-width-input" autosize></el-input>
</template>
</CustomTable>
</div>
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import { XmTextresultNew } from '@/types';
import { ElMessageBox } from 'element-plus';
import { ref } from 'vue';
const props = defineProps({
// 是否显示
// visible: {
// type: Boolean,
// required: true,
// default: false
// }
dataList: {
type: Array,
default: () => []
},
formData: {
type: Object,
default: {}
}
});
const tableRef = ref<any>(null);
const dataList = ref();
const tableRef = ref();
const tableList = ref<Array<XmTextresultNew>>([])
const columns = ref([
{ prop: 'textresult', label: '文字描述', visible: true, align: 'center', width: 500 },
{ prop: 'textresult', label: '文字描述', visible: true, align: 'center',slot: 'textresult', width: 500,showOverflowTooltip:false },
]);
const tableConfig = ref({
border: true, // 边框
@ -43,4 +51,51 @@ const handleColumnDragEnd = (data: any) => {
// 更新列配置
columns.value = data.columns;
}
const selectRow = ref()
//序号最大值
const maxXh = computed(() => {
return tableList.value.length > 0 ? Math.max(...tableList.value.map((item:any) => item.xh || 0)) : 0;
});
const rowClick = (row:any) => {
selectRow.value = row
}
const onAddClick = () => {
const newData: XmTextresultNew = {
xmid: props.formData.xmid,
xmdh: props.formData.xmdh,
xh: maxXh.value + 1
}
tableList.value.push(newData)
}
const onDelClick = async ()=> {
if(selectRow.value){
await ElMessageBox.confirm('是否要删除选中的数据?','警告',
{ confirmButtonText: 'OK',cancelButtonText: 'Cancel',type: 'warning',});
tableList.value = tableList.value.filter((item:any) => item.xh != selectRow.value.xh)
}
}
watch(
() => props.dataList,
(newVal:any) => {
tableList.value = newVal;
}
);
</script>
<style lang="scss" scoped>
:deep(.el-table .cell) {
padding: 0;
}
</style>

View File

@ -2,11 +2,80 @@
<!--参考值明细-->
<div>
<div class="modifyClass">
<el-button type="primary" @click="">增加</el-button>
<el-button type="primary" @click="">删除</el-button>
<el-button type="primary" @click="onAddClick">增加</el-button>
<el-button type="primary" @click="onDelClick">删除</el-button>
</div>
<CustomTable ref="tableRef" :data="dataList" :columns="columns" :enable-column-drag="true" @column-drag-end="handleColumnDragEnd"
:config="tableConfig"/>
<CustomTable ref="tableRefUp" :data="dataListUp" :columns="columnsUp" :enable-column-drag="true" @column-drag-end="handleColumnDragEnd"
:config="tableConfig" @row-click="rowClick">
<template #xb="{row}">
<el-select v-model="row.xb" clearable>
<el-option
v-for="item in optionsXb"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</template>
<template #cp_nl1="{row}">
<el-input v-model="row.cp_nl1" class="full-width-input"></el-input>
</template>
<template #cp_nldw1="{row}">
<el-select v-model="row.cp_nldw1" clearable>
<el-option
v-for="item in optionsNLDW"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</template>
<template #cp_nl2="{row}">
<el-input v-model="row.cp_nl2" class="full-width-input"></el-input>
</template>
<template #cp_nldw2="{row}">
<el-select v-model="row.cp_nldw2" clearable>
<el-option
v-for="item in optionsNLDW"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</template>
<template #bblx="{row}">
<SelectTable v-model:data="row.bblx" :fields="fields" :tableData="bblxOptions" label="label"
value="label" objKey="label" :border="true" />
</template>
<template #slzq="{row}">
<el-select v-model="row.slzq" clearable>
<el-option
v-for="item in optionsSLZQ"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</template>
<template #zd="{row}">
<el-input v-model="row.zd" class="full-width-input"></el-input>
</template>
<template #ckxx="{row}">
<el-input v-model="row.ckxx" class="full-width-input"></el-input>
</template>
<template #cksx="{row}">
<el-input v-model="row.cksx" class="full-width-input"></el-input>
</template>
<template #alterxx="{row}">
<el-input v-model="row.alterxx" class="full-width-input"></el-input>
</template>
<template #altersx="{row}">
<el-input v-model="row.altersx" class="full-width-input"></el-input>
</template>
<template #dyck="{row}">
{{ row.ckxx + '--' + row.cksx }}
</template>
</CustomTable>
<el-row>
仪器特定参考值:
</el-row>
@ -14,7 +83,7 @@
<el-button type="primary" @click="">增加</el-button>
<el-button type="primary" @click="">删除</el-button>
</div>
<CustomTable ref="tableRef" :data="dataList" :columns="columns" :enable-column-drag="true" @column-drag-end="handleColumnDragEnd"
<CustomTable ref="tableRefDown" :data="dataListDown" :columns="columnsDown" :enable-column-drag="true" @column-drag-end="handleColumnDragEnd"
:config="tableConfig"/>
</div>
</template>
@ -22,23 +91,61 @@
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import { ref } from 'vue';
import {getDictData,dictData} from '@/hooks'
import SelectTable from '@/components/SelectTable/index.vue'
import { ElMessageBox } from 'element-plus';
const props = defineProps({
// 是否显示
// visible: {
// type: Boolean,
// required: true,
// default: false
// }
dataList: {
type: Array,
default: []
}
});
const optionsXb = [
{value: '1' ,label: '男'},
{value: '2' ,label: '女'},
]
const optionsNLDW = [
{value: '1' ,label: '岁'},
{value: '2' ,label: '月'},
{value: '3' ,label: '天'},
{value: '4' ,label: '时'},
]
const tableRef = ref<any>(null);
const dataList = ref();
const yqDataList = ref();
const columns = ref([
{ prop: 'xb', label: '性别', visible: true, align: 'center', width: 200 },
const optionsSLZQ = ref<any>([])
const fields = ref(
[
{ prop: 'value', label: '代号', width: 80, enablePinyinSearch: true },
{ prop: 'label', label: '名称', width: 150, enablePinyinSearch: true },
]
)
const bblxOptions = ref<Array<{ zddh: string; zdmc: string }>>([]);
const tableRefUp = ref<any>();
const tableRefDown = ref<any>();
const dataListUp = ref(props.dataList);
const dataListDown = ref();
const columnsUp = ref([
{ prop: 'xh', label: '序号', visible: false, align: 'center', width: 70 },
{ prop: 'xb', label: '性别', visible: true, align: 'center',slot: 'xb', width: 70 },
{ prop: 'cp_nl1', label: '年龄下限', visible: true, align: 'center',slot:'cp_nl1', width: 100 },
{ prop: 'cp_nldw1', label: '年龄单位', visible: true, align: 'center',slot:'cp_nldw1', width: 70 },
{ prop: 'cp_nl2', label: '年龄上限', visible: true, align: 'center',slot: 'cp_nl2', width: 100 },
{ prop: 'cp_nldw2', label: '年龄单位', visible: true, align: 'center',slot: 'cp_nldw2', width: 100 },
{ prop: 'bblx', label: '标本类型', visible: true, align: 'center',slot: 'bblx', width: 100 },
{ prop: 'slzq', label: '生理周期', visible: true, align: 'center',slot: 'slzq', width: 100 },
{ prop: 'zd', label: '诊断', visible: true, align: 'center',slot:'zd', width: 100 },
{ prop: 'ckxx', label: '参考下限', visible: true, align: 'center',slot:'ckxx', width: 100 },
{ prop: 'cksx', label: '参考上限', visible: true, align: 'center',slot:'cksx', width: 100 },
{ prop: 'alterxx', label: '危急值下限', visible: true, align: 'center',slot:'alterxx', width: 100 },
{ prop: 'altersx', label: '危急值上限', visible: true, align: 'center',slot:'altersx', width: 100 },
{ prop: 'dyck', label: '参考值', visible: true, align: 'center',slot:'dyck', width: 100 },
]);
const columnsDown = ref([
{ prop: 'xb', label: '性别', visible: true, align: 'center',slot: 'xb', width: 100 },
{ prop: 'cp_nl1', label: '年龄下限', visible: true, align: 'center', width: 100 },
{ prop: 'cp_nldw1', label: '年龄单位', visible: true, align: 'center', width: 100 },
{ prop: 'cp_nl2', label: '年龄上限', visible: true, align: 'center', width: 100 },
@ -58,13 +165,54 @@ const tableConfig = ref({
highlightCurrentRow: true, // 高亮当前行
// cellStyle: cellStyleHd
})
const selectRow = ref()
//退拽属性
const handleColumnDragEnd = (data: any) => {
// 更新列配置
columns.value = data.columns;
columnsUp.value = data.columns;
columnsDown.value = data.columns;
}
//序号最大值
const maxXh = computed(() => {
return dataListUp.value.length > 0 ? Math.max(...dataListUp.value.map((item:any) => item.xh || 0)) : 0;
});
const onAddClick = () => {
const newData = {
xh: maxXh.value + 1
}
dataListUp.value.push(newData)
}
const onDelClick = async () => {
console.log('删除',selectRow.value)
if(selectRow.value){
await ElMessageBox.confirm('是否要删除选中的数据?','警告',
{ confirmButtonText: 'OK',cancelButtonText: 'Cancel',type: 'warning',});
dataListUp.value = dataListUp.value.filter((item:any) => item.xh !== selectRow.value.xh)
}
}
const rowClick = (row:any) => {
selectRow.value = row
}
onActivated( async ()=>{
//加载字典数据
await getDictData('BT','SLZQ')
bblxOptions.value = dictData.value.BT || []
optionsSLZQ.value = dictData.value.SLZQ || []
})
</script>
<style lang="scss" scoped>
::v-deep .el-input__inner {
text-align: center;
}
</style>

View File

@ -18,12 +18,10 @@ import CustomTable from '@/components/elTable/index.vue'
import { ref } from 'vue';
const props = defineProps({
// 是否显示
// visible: {
// type: Boolean,
// required: true,
// default: false
// }
dataList: {
type: Array,
default: []
}
});

View File

@ -2,37 +2,66 @@
<!-- 使用仪器 -->
<div>
<div>
<span>筛选:</span><input v-model="yq" style="width: 240px;" @change="handInputChange">
<el-button type="primary" @click="onClickAdd">新增</el-button>
<el-button type="primary" @click="onClickDel">删除</el-button>
</div>
<!-- <CustomTable ref="tableRef" :data="yqList" :columns="columns" :enable-column-drag="true" @column-drag-end="handleColumnDragEnd"
:config="tableConfig"/> -->
<CustomTable ref="tableRef" :data="yqList" :columns="columns" :enable-column-drag="true" @column-drag-end="handleColumnDragEnd"
:config="tableConfig" @row-click="onRowClick">
<template #yq="{row}">
<YQSelectTable v-model:data="row.yq" placeholder="请输入仪器名称"/>
</template>
<template #xs="{row}">
<el-input v-model="row.xs" class="full-width-input"/>
</template>
<template #zkxm="{row}">
<el-checkbox v-model="row.zkxm" />
</template>
<template #cksx="{row}">
<el-input v-model="row.cksx" class="full-width-input"></el-input>
</template>
<template #ckxx="{row}">
<el-input v-model="row.ckxx" class="full-width-input"></el-input>
</template>
<template #dyckz="{row}">
<el-input v-model="row.dyckz" class="full-width-input"></el-input>
</template>
</CustomTable>
</div>
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import { LabInstr } from '@/types';
import { ref } from 'vue'
import { XmInfoVs } from '@/types';
import YQSelectTable from '@/components/SelectTable/YQSelectTable/index.vue'
import {ElMessageBox} from 'element-plus'
const props = defineProps({
// 是否显示
// 显示数据
dataList: {
type: Array<LabInstr>,
type: Array<XmInfoVs>,
required: true,
default: () => []
},
formData: {
type: Object,
required: false,
default: {}
}
});
const yq = ref<string>('');
const tableRef = ref<any>(null);
const yqList = ref<Array<LabInstr>>(props.dataList);
//const yq = ref<string>('');
const tableRef = ref<any>();
const yqList = ref<Array<XmInfoVs>>([]);
const columns = ref([
{ prop: 'xz', label: '选择', visible: true, align: 'center', width: 50,type: 'selection' },
{ prop: 'yq', label: '仪器代号', visible: true, align: 'center', width: 150 },
{ prop: 'yqmc', label: '仪器名称', visible: true, align: 'center', width: 200},
{ prop: 'xs', label: '调整系数', visible: true, align: 'center', width: 100 },
{ prop: 'zkxm', label: '质控', visible: true, align: 'center', width: 100 }
{ prop: 'yq', label: '仪器代号', visible: true, align: 'center', slot: 'yq', width: 150 },
{ prop: 'xs', label: '调整系数', visible: true, align: 'center', slot: 'xs', width: 100 },
{ prop: 'zkxm', label: '质控', visible: true, align: 'center', slot: 'zkxm', width: 40 },
{ prop: 'cksx', label: '参考上限', visible: true, align: 'center',slot: 'cksx', width: 100 },
{ prop: 'ckxx', label: '参考下限', visible: true, align: 'center',slot: 'ckxx', width: 100 },
{ prop: 'dyckz', label: '打印参考值', visible: true, align: 'center',slot: 'dyckz', width: 100 },
]);
const tableConfig = ref({
border: true, // 边框
@ -40,13 +69,17 @@ const tableConfig = ref({
highlightCurrentRow: true, // 高亮当前行
// cellStyle: cellStyleHd
})
const selectRow = ref<XmInfoVs>({
yq: '',
xmid: 0
})
//退拽属性
// const handleColumnDragEnd = (data: any) => {
// // 更新列配置
// columns.value = data.columns;
// }
const handleColumnDragEnd = (data: any) => {
// 更新列配置
columns.value = data.columns;
}
const handInputChange = () => {
// yqList.value = yqList.value.filter(item => {
@ -57,7 +90,31 @@ const handInputChange = () => {
// }
}
onMounted(() =>{
const onClickAdd = () => {
const newData: XmInfoVs = {
yq: '',
xmid: props.formData.xmid,
}
yqList.value.push(newData)
}
const onClickDel = async () => {
if(selectRow.value){
await ElMessageBox.confirm('是否要删除选中的数据?','Warning',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
});
yqList.value = yqList.value.filter(item => item.yq != selectRow.value.yq);
}
}
const onRowClick = (row: any) => {
selectRow.value = row
}
onActivated(() =>{
yqList.value = Array.isArray(props.dataList) ? props.dataList : [];
})
</script>

View File

@ -1,11 +1,860 @@
<template>
<div class="app-container">
<el-row :gutter="10">
<el-col :span="13">
<div class="box-shadow">
<el-form :model="queryParams" ref="queryRef" :inline="true" :size="aotuSize" :rules="rules"
class="compact-form">
<el-row :gutter="5">
<el-col :span="6">
<el-form-item label="" prop="ybh">
<div class="next_box">
<div class="jtIcon" @click="handlePrev">
<el-icon>
<ArrowUpBold />
</el-icon>
</div>
<el-input v-model="labInfo.ybh" placeholder="样本编号" @keyup.enter="handleQuery" style="width:100%" />
<div class="jtIcon" @click="handleNext">
<el-icon>
<ArrowDownBold />
</el-icon>
</div>
</div>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="日期:" prop="jyrq">
<el-date-picker v-model="labInfo.jyrq" type="date" label-width="1.25rem" placeholder="检验日期"
value-format="YYYY-MM-DD" :clearable="false" @change="" style="width:100%"></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="部门:" prop="instrGroup">
<SelectTable v-model:data="queryParams.instrGroup" :fields="instrGroupFields"
:tableData="instrGroupOptions" label="zdmc" value="zddh" objKey="zddh" :border="true" width="9rem"
placeholder="请选择部门" @getDataValue="handleinstrGroupChange" :clearable="false" :size="aotuSize" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="仪器:" prop="yq">
<SelectTable v-model:data="queryParams.yq" :fields="yqFields" :tableData="instrOptions" label="yqmc"
value="yq" objKey="yq" :border="true" width="9rem" placeholder="请选择仪器" :clearable="false"
:size="aotuSize" @getDataValue="yqHandleChange" />
</el-form-item>
</el-col>
</el-row>
<!-- <el-form-item>
<el-icon color="#3c80d9" size="20" style="margin-right: 10px;" class="cp">
<Search @click="fetchlabPatList" />
</el-icon>
<el-icon color="#3c80d9" size="20" class="cp" @click="selectJob(labPat)">
<Refresh />
</el-icon>
</el-form-item> -->
</el-form>
<el-row :gutter="5">
<el-col :span="8">
<LabPat ref="labPatRef" v-model:labPat="labPat" :labPatKey="queryParams" :labSysList="labInputcolList"
:userList="userList" @changeStatus="changeStatus" @batchShow="handleBatchScan" />
</el-col>
<el-col :span="16">
<el-tabs v-model="activeName" type="card" class="demo-tabs">
<el-tab-pane label="鉴定(终报)结果" name="first">
<ZbReport ref="labResultRef" v-model:labPat="labInfo" :labPatKey="queryParams"
@update:labPatKey="queryParams = $event" :dictData="dictData" :labResutsData="zbLabResuts"
@fetchLabResults="resultsHandle" @changeStatus="changeStatus" @previewHandle="previewHandle" />
</el-tab-pane>
<el-tab-pane label="初级和二级报告" name="second">
<CbReport v-model:labPat="labInfo" :labPatKey="queryParams" @update:labPatKey="queryParams = $event"
:instrdComOpt="instrdComOpt" :dictData="dictData" @changeStatus="changeStatus" :userList="userList"
@previewHandle="previewHandle" />
</el-tab-pane>
<el-tab-pane label="培养基接种" name="third">
<Byj :labPat="labInfo" :labPatKey="queryParams" />
</el-tab-pane>
<el-tab-pane label="操作记录" name="fourth">
<Record :labPat="labInfo" :labPatKey="queryParams" />
</el-tab-pane>
</el-tabs>
<!-- <LabResult ref="labResultRef" v-model:labPat="labInfo" :labPatKey="queryParams" :dictData="dictData"
:labResutsData="labResuts" @fetchLabResults="resultsHandle" @changeStatus="changeStatus"
@previewHandle="previewHandle" /> -->
</el-col>
</el-row>
</div>
</el-col>
<el-col :span="11">
<div>
<!-- 微生物检验录入界面 -->
<tabView :tabList="tabList" v-model:activeTab="activeTab" />
<div class="box-shadow right_box">
<template v-if="activeTab == 'LabPatList'">
<div class="flex-between">
<div>
<el-button type="primary" :size="aotuSize" icon="RefreshRight" @click="fetchlabPatList">刷新</el-button>
<el-button type="danger" :size="aotuSize" @click="delSampleHd">删除</el-button>
<el-button class="btn_green" :size="aotuSize" icon="top" @click="handlePrev">上一个</el-button>
<el-button class="btn_green mr5" :size="aotuSize" icon="bottom" @click="handleNext">下一个</el-button>
<PatientQueryForm :initial-params="initialParams" @query="handleQueryResult" @reset="handleReset"
width="9rem" :size="aotuSize" placeholder="查询条件" :dict-data="dictData" :clearable="true" />
<el-input v-model="searchText" clearable :size="aotuSize" @keyup.enter="searchQuery"
@clear="clearSearch" style="width: 6rem" />
</div>
<div>
<el-checkbox v-model="lbFlag" :size="aotuSize"> 列表翻页 </el-checkbox>
</div>
</div>
<div class="radio_box">
<el-radio-group v-model="queryParams.days" @change="fetchlabPatList" :size="aotuSize">
<el-radio :value="-1">所有</el-radio>
<el-radio :value="30">近30天</el-radio>
<el-radio :value="60">近60天</el-radio>
<el-radio :value="90">近90天</el-radio>
<el-radio :value="7">近7天</el-radio>
<el-radio :value="0">此日 -></el-radio>
</el-radio-group>
<el-date-picker v-model="queryParams.jyrq" type="date" :size="aotuSize" @change="fetchlabPatList"
style="width: 9.375rem;" />
</div>
<LabPatList ref="labPatListRef" :labPatList="labPatList" :loading="loading" @select="selectJob"
:tableKey="queryParams" :dictData="dictData" @search="searchJobs" />
<div class="button-group">
<!-- <div class="text1">样本总数:<span>{{ ybs }}</span></div>
<div class="text2">未审:<span>{{ ws }}</span></div>
<div class="text3">危:<span>{{ wjs }}</span></div> -->
<el-pagination v-model:current-page="queryParams.pageNum" v-model:page-size="queryParams.pageSize"
:page-sizes="[300, 600, 1000]" :size="aotuSize" background
layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="handleSizeChange"
@current-change="handleCurrentChange" />
</div>
</template>
<component :is="activeTabName" :queryParams="queryParams" :dictData="dictData" :instrOptions="instrOptions"
@fetchResults="fetchLabResults" :tablekey="queryParams" />
</div>
</div>
</el-col>
</el-row>
<!-- 批量扫码弹窗 -->
<BatchCode ref="batchRef" v-model:labPat="labPat" :labPatKey="queryParams" :dictData="dictData"
:totalCount="labPatList.length" @goNext="handleNext" @goPrev="handlePrev" @goLast="handleLast"
@queryYbh="ybhChangeTb" @changeStatus="changeStatus" />
<el-dialog v-model="previewShow" title="预览" width="90vw" :close-on-click-modal="false">
<iFrame v-if="pdfUrl" :src="pdfUrl" />
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { ref, nextTick, onMounted, toRaw } from 'vue';
import LabPat from './labpat.vue';
import SelectTable from '@/components/SelectTable/index.vue';
import tabView from '@/components/tabViews/index.vue';
// @ts-ignore
import iFrame from "@/components/iFrame/index.vue";
// @ts-ignore
import LabResult from './labresult/index.vue';
import LabPatList from './labpatlist.vue';
import History from '../components/history/index.vue'
import Others from '../components/others/index.vue'
import Reexamination from '../components/reexamination/index.vue'
import Charge from '../components/charge/index.vue'
import Combination from '../components/combination/index.vue'
import Clinical from '../components/clinical/index.vue'
import Sample from '../components/sample/index.vue'
import ResultGraph from '../components/resultGraph/index.vue'
// 中间部分
import ZbReport from './labresult/zbReport.vue';
import CbReport from './labresult/cbReport.vue';
import Byj from './labresult/byj.vue';
import Record from './labresult/record.vue';
// @ts-ignore
import { comDict } from '@/utils/dict'
import { queryLabResults, loadDefault, queryLabPat, instrdconfig, delSample, getGroupInstrdList } from "@/api/liswork/work/LisWork";
import { wswsamplelistpage, sampleMedInfo } from "@/api/liswork/micro/index";
import { getComDicts, queryComDictListService } from "@/api/liswork/dict/ComDict";
import { ElMessage, ElMessageBox } from "element-plus";
import BatchCode from '../work/components/batchCode.vue';
import { getNextNumber, getPreviousNumber } from "@/utils/getNextNumber";
import { useCommonStore } from '@/store/modules/commonStore';
import { classCom } from '@/utils/classCom';
import PatientQueryForm from '@/components/selectSearch/index.vue'
// @ts-ignore
import { listUser } from '@/api/system/user.js'
import dayjs from 'dayjs'
const aotuSize = classCom.useAutoSize();
import { initWebSocket, sendWebSocketMessage, closeWebSocket, getWebSocketState } from '@/utils/webSocket';
const previewShow = ref(false);
const lbFlag = ref(false);
const queryParams = ref({
jyrq: dayjs().format('YYYY-MM-DD'),
yq: 'PHOENI',
ybh: '',
instrGroup: '04',
problemId: 0,
days: -1,
pageSize: 600,
pageNum: 1,
yhdh: ''
})
const activeName = ref('second');
const total = ref(0)
const ybs = ref(0)
const ws = ref(0)
const wjs = ref(0)
const activeTab = ref('LabPatList')
const tabList = ref([
{ label: '标本列表', value: 'LabPatList' },
{ label: '结果图形', value: 'ResultGraph' },
{ label: '历史对照', value: 'History' },
{ label: '其他结果', value: 'Others' },
{ label: '结果复查', value: 'Reexamination' },
{ label: '收费信息', value: 'Charge' },
{ label: '组合项目', value: 'Combination' },
{ label: '临床意义', value: 'Clinical' },
{ label: '样本流转', value: 'Sample' },
])
const activeTabMap = {
ResultGraph,
History,
Others,
Reexamination,
Charge,
Combination,
Clinical,
Sample
}
const activeTabName = computed(() => activeTabMap[activeTab.value as keyof typeof activeTabMap] || 'LabPatList');
const labPat = ref<any>({})
const labPatList = ref<Array<{ ybh: string; jgbz: string }>>([]);
const originalLabPatList = ref([]) //原始数据
const loading = ref(false)
const searchText = ref('')
const rules = ref([])
const instrGroupOptions = ref<any[]>([])
const instrOptions = ref<{ yq: string; yqmc: string }[]>([])
const pdfUrl = ref('')
// 初始查询参数(可选)
const initialParams = {}
// 定义查询参数类型
interface QueryParams {
brly?: string | number
jgbz?: string | number
dybz?: string | number
alarmflag?: string | number
jzbz?: string | number
finish?: string | number
autojgbz?: string | number
}
watch(() => labPat.value, (newValue) => {
queryParams.value.ybh = newValue.ybh;
}, { deep: true });
// 模糊查询
const searchQuery = () => {
let filterMhList = [...originalLabPatList.value];
if (searchText.value) {
const searchStr = searchText.value.trim().toLowerCase();
filterMhList = filterMhList.filter((item: any) => {
// 处理 zjf大写转为小写
const matchZjf = item.zjf && typeof item.zjf === 'string'
? item.zjf.toLowerCase().includes(searchStr)
: false; const matchBrxm = item.brxm && typeof item.brxm === 'string' && item.brxm.includes(searchStr);
const matchSqh = item.sqh && typeof item.sqh === 'string' && item.sqh.includes(searchStr);
return matchZjf || matchBrxm || matchSqh;
});
}
labPatList.value = filterMhList;
if (filterMhList.length > 0) {
highlightRowIndex.value = 0;
const firstRow = filterMhList[0];
labPatListRef.value.setCurrentRow(firstRow);
selectJob(firstRow);
} else {
labPat.value = {};
labInfo.value = {};
zbLabResuts.value = [];
highlightRowIndex.value = -1;
}
};
const clearSearch = () => {
searchText.value = ''
searchQuery()
}
// 多条件查询
const handleQueryResult = (params: QueryParams) => {
// console.log('查询参数:', params);
// 复制原始列表作为筛选基础
let filteredList = [...originalLabPatList.value];
// 遍历所有查询参数,进行筛选
Object.entries(params).forEach(([key, value]) => {
filteredList = filteredList.filter((item: any) => {
if (value == 0) {
return item[key] == null;
} else {
return item[key] == value;
}
});
});
labPatList.value = filteredList;
if (filteredList.length > 0) {
highlightRowIndex.value = 0;
const firstRow = filteredList[0];
labPatListRef.value.setCurrentRow(firstRow);
selectJob(firstRow);
} else {
labPat.value = {};
labInfo.value = {};
zbLabResuts.value = [];
highlightRowIndex.value = -1;
}
};
// 处理重置
const handleReset = () => {
labPatList.value = [...originalLabPatList.value];
}
const previewHandle = (url: string) => {
if (!url) return ElMessage.warning('未查询到文件')
pdfUrl.value = `data:application/pdf;base64,${url}`
previewShow.value = true
}
const handleinstrGroupChange = (val: any) => {
queryParams.value.yq = ''
getYqConfig()
}
const mbStore = useCommonStore();
const yqHandleChange = (val: any) => {
zbLabResuts.value = [];
labPat.value = {}
labInfo.value = {}
mbStore.setLxsrList([]);
getSysList()
fetchlabPatList()
sendMessage()
}
const instrGroupFields = ref([
{ prop: 'zddh', label: '代号', width: 80, enablePinyinSearch: true },
{ prop: 'zdmc', label: '名称', width: 150, enablePinyinSearch: true },
])
// 部门
const loadinstrGroupOptions = () => {
getComDicts({ zdlb: 'GROUP' }).then((res: any) => {
instrGroupOptions.value = res.data
instrGroupOptions.value.push({ zddh: 'ALL', zdmc: '所有仪器' })
queryParams.value.instrGroup = '04'
queryParams.value.yq = 'PHOENI'
getYqConfig()
});
}
const yqFields = ref([
{ prop: 'yq', label: '代号', width: 80, enablePinyinSearch: true },
{ prop: 'yqmc', label: '名称', width: 150, enablePinyinSearch: true },
])
// 仪器
const getYqConfig = () => {
getGroupInstrdList({ lisgroup: queryParams.value.instrGroup })
.then((res: any) => {
if (res.code == 0) {
instrOptions.value = res.data.map((item: any) => ({
yq: item.yq.trim(),
yqmc: item.yqmc
}))
}
})
}
const resultsHandle = (flag: boolean) => {
if (flag) {
fetchLabPat();
}
fetchLabResults()
}
const labInfo: any = ref({})
const highlightRowIndex = ref(-1)
const labPatListRef = ref()
//样本列表点击切换样本信息,同步载入左边样本信息表单和中间结果表单
const selectJob = (job: any) => {
labInfo.value = { ...job }
lastRow.value = job;
fetchLabPat();
fetchLabResults();
highlightRowIndex.value = labPatList.value.findIndex((item: any) => item.ybh == labInfo.value.ybh);
}
const zbLabResuts = ref([])
//载入样本结果表单(中间labresult.vue组件)
const fetchLabResults = async () => {
sampleMedInfo({ jyrq: labInfo.value.jyrq ? labInfo.value.jyrq : queryParams.value.jyrq, yq: labInfo.value.yq, ybh: labInfo.value.ybh }).then((response: any) => {
zbLabResuts.value = response.data;
})
}
//载入样本编辑表单(左边labpat.vue组件)
const fetchLabPat = () => {
const data = {
jyrq: labInfo.value.jyrq,
yq: labInfo.value.yq,
ybh: labInfo.value.ybh
}
queryLabPat(data).then((response: any) => {
labPat.value = response.data;
})
}
const lastRow: any = ref({})
// 批量扫码ybh同步样本编号
const ybhChangeTb = (val: string) => {
// console.log('val==>', val);
labInfo.value.ybh = val
handleQuery();
}
const handleQuery = () => {
if (!labPatList.value.length) return
if (!labInfo.value.ybh) {
highlightRowIndex.value = -1;
ElMessage.warning('请输入样本编号')
labInfo.value.ybh = lastRow.value.ybh
return;
}
// queryParams.value = { ...queryParams.value };
// 查找匹配的行
const matchedIndex = labPatList.value.findIndex((item: any) => item.ybh == labInfo.value.ybh);
const row = labPatList.value[matchedIndex]
if (matchedIndex !== -1) {
highlightRowIndex.value = matchedIndex;
// 等待DOM更新后滚动到目标行
nextTick(() => {
labPatListRef.value.setCurrentRow(row);
});
selectJob(row);
} else {
handleCreate()
highlightRowIndex.value = -1;
}
}
// 创建新样本
const handleCreate = () => {
labInfo.value.jyrq = ''
loadDefault({ ...queryParams.value }).then((response: any) => {
if (response.code == 0) {
labPat.value = response.data;
labInfo.value = response.data;
labPat.value.id = `temp_${Date.now()}_${Math.random().toString(36).substr(2, 8)}`;
zbLabResuts.value = [];
labPatListRef.value?.clearCurrentRow();
fetchLabResults()
}
});
}
// 删除样本
const delSampleHd = () => {
if (labInfo.value.jgbz == '2') return ElMessage.warning('标本已审核,不能删除!')
const data = {
jyrq: labInfo.value.jyrq,
yq: labInfo.value.yq.trim(),
ybh: labInfo.value.ybh,
}
ElMessageBox.confirm(
`确定删除当前${labInfo.value.ybh}号标本?`,
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
delSample(data).then((res: any) => {
if (res.code == 0) {
ElMessage.success('删除成功')
labPatList.value = labPatList.value.filter((item: any) => item.ybh != labInfo.value.ybh)
// 删除跳当前页面下一个样本
// handleNext()
if (highlightRowIndex.value > labPatList.value.length - 1) {
highlightRowIndex.value--;
}
const row = labPatList.value[highlightRowIndex.value];
labPatListRef.value.setCurrentRow(row);
selectJob(row);
}
})
})
.catch(() => {
})
}
// 上一个样本
const handlePrev = () => {
if (!lbFlag.value) {
const ybh = getPreviousNumber(labInfo.value.ybh) as string;
labInfo.value.ybh = ybh;
const index = labPatList.value.findIndex((item: any) => item.ybh == ybh)
if (index !== -1) {
highlightRowIndex.value = index;
const row = labPatList.value[index];
labPatListRef.value.setCurrentRow(row);
selectJob(row);
} else {
handleCreate();
}
} else {
if (highlightRowIndex.value > 0) {
highlightRowIndex.value--;
const row = labPatList.value[highlightRowIndex.value];
labPatListRef.value.setCurrentRow(row);
selectJob(row);
}
}
}
// 下一个样本
const handleNext = () => {
if (!lbFlag.value) {
const ybh = getNextNumber(labInfo.value.ybh) as string;
labInfo.value.ybh = ybh;
const index = labPatList.value.findIndex((item: any) => item.ybh == ybh)
if (index !== -1) {
highlightRowIndex.value = index;
const row = labPatList.value[index];
labPatListRef.value.setCurrentRow(row);
selectJob(row);
} else {
handleCreate();
}
} else {
if (highlightRowIndex.value < labPatList.value.length - 1) {
highlightRowIndex.value++;
const row = labPatList.value[highlightRowIndex.value];
labPatListRef.value.setCurrentRow(row);
selectJob(row);
} else {
labInfo.value.ybh = getNextNumber(labInfo.value.ybh) as string;
handleCreate();
}
}
}
// 最后一个样本
const handleLast = () => {
labInfo.value.ybh = labPatList.value[labPatList.value.length - 1].ybh;
handleNext();
}
const batchRef = ref()
// 批量扫码
const handleBatchScan = () => {
batchRef.value.open()
}
// 改变样本列表中样本状态
const changeStatus = (updatedPat: any, flag: boolean) => {
const data = {
jyrq: updatedPat.jyrq,
yq: updatedPat.yq.trim(),
ybh: updatedPat.ybh,
}
queryLabPat(data).then((response: any) => {
if (response.code == 0) {
labPat.value = response.data;
labInfo.value = response.data;
const index = labPatList.value.findIndex((item: any) => item.ybh == updatedPat.ybh);
if (index !== -1) {
labPatList.value = labPatList.value.map((item, i) =>
i === index ? { ...labPat.value } : item
);
highlightRowIndex.value = index;
nextTick(() => {
labPatListRef.value.setCurrentRow(labPat.value);
});
// 条码号输入后操作
if (flag) {
setTimeout(() => { handleNext() }, 10)
} else {
fetchLabResults()
}
} else {
// 条码号输入后操作
if (flag) {
setTimeout(() => { handleNext() }, 10)
} else {
fetchLabResults()
}
labPatList.value.push(labPat.value)
setTimeout(() => {
nextTick(() => {
labPatListRef.value.setCurrentRow(labPat.value);
});
}, 10)
}
}
});
};
//样本列表检索时刷新列表信息
const searchJobs = async (text: string, page: number, size: number) => {
fetchlabPatList()
}
const handleSizeChange = (size: number) => {
queryParams.value.pageSize = size
fetchlabPatList()
}
const handleCurrentChange = (page: number) => {
queryParams.value.pageNum = page
fetchlabPatList()
}
//载入样本列表(右边labpatlist.vue组件)
const fetchlabPatList = () => {
// if (!queryParams.value.jyrq) {
// queryParams.value.jyrq = lastRow.value.jyrq
// return ElMessage.warning('请选择检验日期')
// }
loading.value = true;
wswsamplelistpage(queryParams.value).then((res: any) => {
if (res.code == 200) {
labPatList.value = res.rows;
originalLabPatList.value = res.rows;
total.value = res.total;
loading.value = false;
if (res.rows.length > 0) {
highlightRowIndex.value = 0;
setTimeout(() => { labPatListRef.value.setCurrentRow(res.rows[0]) }, 10)
selectJob(res.rows[0])
}
}
})
}
// 计算样本数
const getTotals = () => {
ybs.value = labPatList.value.length
ws.value = labPatList.value.filter((item: any) => item.jgbz != 2).length
wjs.value = labPatList.value.filter((item: any) => item.alarmflag == 1).length
}
loadinstrGroupOptions()
fetchlabPatList()
interface DictData {
PT?: Array<any>;
AU?: Array<any>;
SX?: Array<any>;
DP?: Array<any>;
BT?: Array<any>;
SRD?: Array<any>;
HOS?: Array<any>;
ST?: Array<any>;
[key: string]: any[] | undefined; // 添加索引签名以支持动态访问
}
// 字典数据存储
const dictData = ref<DictData>({});
const labInputcolList = ref([])
const resultConfig = ref([])
const instrdComOpt = ref({}) //仪器通用配置
// 获取参数配置
const getSysList = () => {
instrdconfig({ yq: queryParams.value.yq }).then((res: any) => {
if (res.code == 0) {
labInputcolList.value = res.data.labInputcolList.filter((item: any) => item.mrts != "年龄单位" && item.mrts != "!")
resultConfig.value = res.data.ResultConfig
instrdComOpt.value = res.data.instrdComOpt
}
});
mbStore.setLxsrList([]);
}
getSysList()
const userList = ref([]);
onMounted(async () => {
const data = { status: 0, del_flag: 0, pageSize: 1000, pageNum: 1 }
listUser(data).then((res: any) => {
userList.value = res.rows;
});
// 加载病人来源字典
const dictRefs = await comDict('PT', 'AU', 'SX', 'DP', 'BT', 'SRD', 'HOS', 'ST', 'germclass', 'GMC');
// 从 ref 中获取实际数据
dictData.value = {
PT: toRaw(dictRefs.PT.value) || [],
AU: toRaw(dictRefs.AU.value) || [],
SX: toRaw(dictRefs.SX.value) || [],
DP: toRaw(dictRefs.DP.value) || [],
BT: toRaw(dictRefs.BT.value) || [],
SRD: toRaw(dictRefs.SRD.value) || [],
HOS: toRaw(dictRefs.HOS.value) || [],
ST: toRaw(dictRefs.ST.value) || [],
germclass: toRaw(dictRefs.germclass.value) || [],
GMC: toRaw(dictRefs.GMC.value) || [],
};
// 初始化Socket
initSocket()
});
const initSocket = () => {
initWebSocket({
fullUrl: `ws://47.97.125.165:8904/ws/instr/${mbStore.fingerprint}`,
// fullUrl: `ws://192.168.1.151:9801/ws/instr/${mbStore.fingerprint}`,
onOpen: () => {
console.log('WebSocket连接成功');
},
onMessage: (data) => {
console.log(`收到消息: `, JSON.parse(data));
},
onError: (error) => {
console.log(`连接错误: ${error.type}`);
},
onClose: () => {
console.log('WebSocket连接已关闭');
},
reconnectInterval: 3000 // 重连间隔(毫秒)
});
}
// 页面卸载时清理
onUnmounted(() => {
closeWebSocket();
});
// 发送消息
const sendMessage = () => {
const isSuccess = sendWebSocketMessage({ yq: queryParams.value.yq });
if (isSuccess) {
console.log(`发送消息`);
} else {
console.log('发送失败:连接未建立');
}
};
</script>
<style scoped></style>
<style scoped lang="scss">
.app-container {
background: #F0F3F8;
}
:deep(.el-tabs--card>.el-tabs__header) {
height: 1.875rem !important;
margin-bottom: 0px;
font-size: .875rem;
.el-tabs__item {
height: 1.875rem !important;
padding: 0 .625rem;
&.is-active {
border-bottom: .125rem solid #409eff !important;
background-color: #e9f1fb;
}
}
}
.box-shadow {
box-shadow: 2px 2px 4px 0px rgba(206, 217, 234, 0.7);
border-radius: .75rem;
padding: .5rem;
background-color: #fff;
}
.radio_box {
display: flex;
align-items: center;
margin: .125rem 0;
.el-radio {
margin-right: .3125rem;
}
}
.right_box {
height: calc(90vh - 3.4rem);
}
.compact-form {
border-bottom: 1px solid #E1E9F7;
margin-bottom: 0.5rem;
.el-form-item--default {
margin-bottom: .3125rem !important;
}
.el-form-item--small {
margin-bottom: .3125rem !important;
}
}
.card-content {
max-height: 28.125rem;
/* 设置最大高度 */
overflow-y: auto;
/* 超出高度时显示垂直滚动条 */
padding: .3125rem;
/* 保持与卡片默认一致的内边距 */
}
.button-group {
// display: flex;
// justify-content: space-around;
// font-family: SourceHanSansCN, SourceHanSansCN;
// font-weight: 500;
// font-size: 1rem;
// color: #28BDBB;
width: 100%;
margin-top: .1875rem;
text-align: right;
.text2 {
color: #1F33FF;
}
.text3 {
color: #FF0000;
}
}
</style>

View File

@ -0,0 +1,501 @@
<template>
<div class="labpat_box">
<div class="flex-between mb5">
<el-input v-model="sqhValue" placeholder="条码号" ref="sqhRef" :size="aotuSize" class="mr10" style="width:100%"
@keyup.enter="handleInputFocus" />
<el-button type="primary" :size="aotuSize" @click="batchHandle">扫码</el-button>
</div>
<el-form :model="labPat" label-width="5rem" class="compact-form" label-position="right">
<div :class="['sh_box', getColor(lastJgbz)]" v-if="lastJgbz != null && lastJgbz != 0 && lastJgbz != 'C'">
<div class="text">{{ getLableType(lastJgbz) }}</div>
</div>
<template v-for="v in labSysList" :key="v.xh">
<el-row :gutter="10" v-if="v.mrts == '病人来源'">
<el-col :span="18">
<el-form-item :label="v.zdts" v-if="v.kj == '1'">
<SelectTable v-model:data="labPat[v.zdmc]" :fields="brlyFields" :dictType="v.dict" placeholder=""
label="label" value="value" objKey="value" :border="true" size="small"
@getDataValue="handleFieldChange" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-checkbox v-model="labPat.jzbz" true-value="1" class="check_box"> 急诊 </el-checkbox>
<!-- :disabled="v.kybj == '0'" -->
</el-col>
</el-row>
<el-form-item :label="v.zdts" v-if="v.kj == '1' && !v.dict && v.mrts != '年龄'">
<el-input v-if="v.zdlb == '1'" v-model="labPat[v.zdmc]" @change="handleFieldChange" size="small" />
<el-date-picker v-if="v.zdlb == '3'" v-model="labPat[v.zdmc]" type="datetime" format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss" @change="handleFieldChange" size="small" style="width: 100%;" />
</el-form-item>
<el-form-item :label="v.zdts" v-if="v.kj == '1' && v.mrts == '年龄'">
<el-col :span="14" v-if="v.mrts == '年龄'">
<el-input v-model="labPat[v.zdmc]" @change="handleFieldChange" style="width:100%" size="small" />
</el-col>
<el-col :span="10">
<SelectTable v-model:data="labPat.nldw" :fields="ksdhFields" dictType="AU" label="label" value="value"
objKey="value" :border="true" size="small" @getDataValue="handleFieldChange" placeholder="" />
</el-col>
</el-form-item>
<el-form-item :label="v.zdts"
v-if="v.dict && v.kj == '1' && v.mrts != '病人来源' && v.mrts != '年龄单位' && v.mrts != '检验医师' && v.mrts != '核对医师'">
<SelectTable v-model:data="labPat[v.zdmc]" :fields="ksdhFields" :dictType="v.dict" label="label" value="value"
objKey="value" :border="true" size="small" @getDataValue="handleFieldChange" placeholder="" />
</el-form-item>
<el-form-item :label="v.zdts" v-if="v.mrts == '检验医师' && v.kj == '1'">
<SelectTable v-model:data="labPat[v.zdmc]" :fields="ysFields" :tableData="userList || []" label="nickName"
value="userName" objKey="userName" :border="true" size="small" @getDataValue="getJyysData" placeholder="" />
</el-form-item>
<el-form-item :label="v.zdts" v-if="v.mrts == '核对医师' && v.kj == '1'">
<SelectTable v-model:data="labPat[v.zdmc]" :fields="ysFields" :tableData="userList || []" label="nickName"
value="userName" objKey="userName" :border="true" size="small" @getDataValue="getHdysData" placeholder="" />
</el-form-item>
</template>
</el-form>
<!-- 医生校验 -->
<YhVerification ref="formRef" :form-value="form" :labPatKey="labPatKey" @confirm="handleConfirm"
@cancel="handleCancel" />
</div>
</template>
<script setup lang="ts">
import { ref, reactive, watch, toRaw, computed, onMounted, nextTick } from 'vue';
import { changepatcolumn, updateLabPat, checkYsUser } from "@/api/liswork/work/LisWork";
import SelectTable from '@/components/SelectTable/index.vue';
import YhVerification from '../work/components/yhVerification.vue';
import emitter from '@/utils/mitt';
import { classCom } from '@/utils/classCom';
import Labpat from '../work/components/labpat.vue';
const aotuSize = classCom.useAutoSize();
interface LabSysItem {
kj: string;
dict: string;
kybj: string;
zdlb: string;
zdmc: string;
zdts: string;
xh: number;
mrts: string;
}
const props = defineProps({
labSysList: {
type: Array as PropType<LabSysItem[]>,
required: true
},
labPat: {
type: Object,
required: true
},
//结果主键
labPatKey: {
type: Object,
default: () => { }
},
userList: {
type: Array as PropType<object[]>,
default: () => []
}
});
const lastJgbz = ref();
const sqhValue = ref(''); // 条码号
const sqhRef = ref();
watch(() => props.labPat, (newVal) => {
// console.log('newVal==>', newVal);
lastValue.value = JSON.stringify(newVal);
lastJgbz.value = newVal?.jgbz;
sqhValue.value = '';
})
const emit = defineEmits(['update:labPat', 'changeStatus', 'batchShow']);
const lastValue = ref('');
const brlyFields = ref([
{ prop: 'value', label: '代号', width: 80, enablePinyinSearch: true },
{ prop: 'label', label: '名称', width: 120, enablePinyinSearch: true },
])
const ksdhFields = ref([
{ prop: 'value', label: '代号', width: 80, enablePinyinSearch: true },
{ prop: 'label', label: '名称', width: 150, enablePinyinSearch: true },
])
const ysFields = ref([
{ prop: 'userName', label: '用户代号', width: 80, enablePinyinSearch: true },
{ prop: 'nickName', label: '用户姓名', width: 150, enablePinyinSearch: true },
])
const form = ref({
yhdh: '',
userName: '',
mm: '',
type: 1,
zdmc: '',
ybh1: '',
ybh2: '',
});
const sqhFlag = ref(false);
const handleInputFocus = () => {
sqhFlag.value = true;
props.labPat.sqh = sqhValue.value;
handleFieldChange();
};
// 表单引用
const formRef = ref();
// 批量扫码
const batchHandle = () => {
emit('batchShow')
};
// 处理确定按钮点击
const handleConfirm = async () => {
form.value.mm = ''
handleFieldChange()
};
// 处理取消按钮点击
const handleCancel = () => {
if (form.value.zdmc = 'yhdh') {
props.labPat.yhdh = JSON.parse(lastValue.value).yhdh
}
if (form.value.zdmc = 'hdys') {
props.labPat.hdys = JSON.parse(lastValue.value).hdys
}
};
// 医生校验
const getJyysData = (data: any) => {
if (data.userName == JSON.parse(lastValue.value).yhdh) return
form.value.yhdh = data.userName;
form.value.userName = data.nickName;
form.value.zdmc = 'yhdh';
nextTick(() => {
formRef.value?.open()
})
}
const getHdysData = (data: any) => {
if (data.userName == JSON.parse(lastValue.value).hdys) return
form.value.yhdh = data.userName;
form.value.userName = data.nickName;
form.value.zdmc = 'hdys';
nextTick(() => {
formRef.value?.open()
})
}
/**
* 通用字段变化处理(失焦、回车触发)
*/
const handleFieldChange = async () => {
// 将当前labPat转为字符串用于比较
const currentValue = JSON.stringify(props.labPat);
// 对比与上一次保存的值是否有变化
if (currentValue !== lastValue.value) {
emitter.emit('saveLab');
// 找出变化的字段
const oldObj = JSON.parse(lastValue.value);
const newObj = props.labPat;
const changedField = getChangedField(oldObj, newObj);
if (changedField) {
// 这里可以添加实际的更新逻辑,比如调用接口
try {
saveLabPat(changedField)
} catch (error) {
console.error('更新失败:', error);
// 失败时可以恢复旧值
emit('update:labPat', oldObj);
lastValue.value = JSON.stringify(oldObj);
}
}
}
};
// 保存病人信息
const saveLabPat = async (changedField: any) => {
if (props.labPat.id) {
updateLabPat({ ...props.labPatKey, ...props.labPat }).then((res: any) => {
if (res.code == 0) {
if (sqhFlag.value) {
sqhValue.value = ''
sqhRef.value.focus()
}
if (res.data) {
emit('update:labPat', res.data)
emit("changeStatus", res.data, sqhFlag.value);
} else {
emit("changeStatus", props.labPat, sqhFlag.value);
}
sqhFlag.value = false
}
})
} else {
if (!changedField) return
const data = {
...props.labPatKey,
jyrq: props.labPat.jyrq,
ybh: props.labPat.ybh,
column: changedField?.field,
value: changedField?.newValue
}
changepatcolumn(data).then((res: any) => {
if (res.code == 0) {
if (sqhFlag.value) {
sqhValue.value = ''
sqhRef.value.focus()
}
if (res.data) {
emit('update:labPat', res.data)
emit("changeStatus", props.labPat, sqhFlag.value);
} else {
emit("changeStatus", props.labPat, sqhFlag.value);
}
sqhFlag.value = false
}
})
}
};
// 完善字段变化检测方法
const getChangedField = (oldObj: { [key: string]: any }, newObj: { [key: string]: any }) => {
const oldKeys = Object.keys(oldObj);
for (const key of oldKeys) {
const oldVal = oldObj[key];
const newVal = newObj[key];
if (oldVal instanceof Date && newVal instanceof Date) {
if (oldVal.getTime() !== newVal.getTime()) {
return { field: key, oldValue: oldVal, newValue: newVal };
}
} else if (oldVal !== newVal) {
return { field: key, oldValue: oldVal, newValue: newVal };
}
}
const newKeys = Object.keys(newObj);
for (const key of newKeys) {
if (!(key in oldObj)) {
return { field: key, oldValue: undefined, newValue: newObj[key] };
}
}
return null;
};
const getLableType = (type: string) => {
switch (type) {
case '1':
return '初审';
case '2':
return '已审核';
case '3':
return '初报';
case '4':
return '二报';
case '5':
return '已锁定';
default:
return '';
}
}
const getColor = (type: string) => {
switch (type) {
case '1':
return 'cs_color';
case '2':
return 'sh_color';
case '3':
return 'cb_color';
case '4':
return 'eb_color';
case '5':
return 'sd_color';
default:
return 'default';
}
}
onMounted(() => {
// 监听保存病人结果
emitter.on('wswSaveResult', () => {
saveLabPat(null)
})
})
</script>
<style scoped lang="scss">
.labpat_box {
height: calc(90vh - 4.375rem);
display: flex;
flex-direction: column;
overflow: hidden;
.check_box {
:deep(.el-checkbox__input.is-checked+.el-checkbox__label) {
color: #f00 !important;
}
}
:deep(.el-input__wrapper) {
box-shadow: 0 0 0 1px #96B8D9 inset;
background-color: rgba(236, 244, 251, 0.5);
color: #08355E;
.is-focus {
box-shadow: 0 0 0 1px #1f6dd3 inset !important;
}
&:hover {
box-shadow: 0 0 0 1px #1f6dd3 inset !important;
}
// .el-input__placeholder {
// color: none !important;
// }
}
:deep(.el-select__wrapper) {
box-shadow: 0 0 0 1px #96B8D9 inset;
background-color: rgba(236, 244, 251, 0.5);
color: #08355E;
.is-focus {
box-shadow: 0 0 0 1px #1f6dd3 inset !important;
}
&:hover {
box-shadow: 0 0 0 1px #1f6dd3 inset !important;
}
.el-select__placeholder {
color: #08355E !important;
}
}
:deep(.el-input__inner) {
color: #08355E !important;
-webkit-text-fill-color: #08355E;
}
:deep(.el-select__input) {
color: #08355E !important;
}
.compact-form {
flex: 1;
position: relative;
height: 100%;
overflow-y: auto;
overflow-x: hidden;
.el-form-item {
margin-bottom: 0px;
}
.el-form-item__label {
padding-bottom: 0px;
color: #08355E;
font-size: 12px;
}
:deep(.el-form-item--default .el-form-item__label) {
height: 27px !important;
line-height: 27px !important;
}
:deep(.el-form-item--default .el-form-item__content) {
line-height: 27px !important;
}
// pointer-events: none;
:deep(.el-radio__label) {
color: #08355E;
}
}
:deep(.el-switch__label) {
color: #08355E;
}
}
.sh_box {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0);
z-index: 9;
display: flex;
justify-content: center;
align-items: center;
writing-mode: vertical-rl;
font-weight: 500;
font-size: 100px;
.text {
font-style: italic;
}
// pointer-events: none;
}
.cs_color {
color: rgba(40, 189, 187, 0.25);
}
.sh_color {
color: rgba(238, 8, 8, 0.25);
}
.cb_color {
color: rgba(0, 128, 0, 0.25);
}
.eb_color {
color: rgba(255, 165, 0, 0.25);
}
.sd_color {
color: rgb(233, 126, 32, .25);
}
.default {
color: rgba(40, 189, 187, 0.25);
}
</style>

View File

@ -0,0 +1,276 @@
<template>
<div class="table-container">
<ContextMenu :items="contextMenuItems" @select="handleMenuSelect" menu-width="200">
<CommonTable :table-data="labPatList" :loading="loading" :columns="tableColumns"
:row-config="{ isHover: true, keyField: 'ybh' }" @current-change="handleRowClick" size="small"
:row-style="rowStyle" :cell-style="cellStyle" class="mytable-style" ref="tableRef" :enable-column-drag="true"
@column-drag-end="handleColumnDragEnd">
<!-- 完成状态列 -->
<template #finish="{ row }">
<el-checkbox :model-value="row.finish == '1'" readonly />
</template>
<template #alarmflag="{ row }">
<el-checkbox :model-value="row.alarmflag == '1'" readonly />
</template>
<template #jgbz="{ row }">
{{ getLableType(row.jgbz) }}
</template>
<template #brly="{ row }">
{{ formatDict(row.brly, 'PT') }}
</template>
<template #brxm="{ row }">
<span :style="{ color: row.jzbz == '1' ? '#f00' : '' }">{{ row.brxm }}</span>
</template>
<template #brxb="{ row }">
{{ formatDict(row.brxb, 'SX') }}
</template>
<template #nldw="{ row }">
{{ formatDict(row.nldw, 'AU') }}
</template>
<template #yblx="{ row }">
{{ formatDict(row.yblx, 'BT') }}
</template>
<template #ksdh="{ row }">
{{ formatDict(row.ksdh, 'DP') }}
</template>
<template #yhdh="{ row }">
{{ formatDict(row.yhdh, 'SRD') }}
</template>
<template #autojgbz="{ row }">
<el-checkbox :model-value="row.autojgbz === '1'" readonly />
</template>
<template #dybz="{ row }">
<el-checkbox :model-value="row.dybz === '1'" readonly />
</template>
<template #yljg="{ row }">
{{ formatDict(row.yljg, 'HOS') }}
</template>
</CommonTable>
</ContextMenu>
<el-dialog v-model="show" title="操作" width="300" :close-on-click-modal="false" :draggable="true"
@close="closeHandle">
<div class="form-box">
<div class="item">
<span>仪器:</span>
<yqSelectTable v-model:data="fcYq" :instrGroup="tableKey.instrGroup" />
</div>
<div class="mt10">请输入复查的样本号:</div>
<el-input v-model="fcYbh" @keyup.enter="subHandle()" />
</div>
<div class="mt10" style="text-align: center; width: 100%;">
<el-button type="primary" @click="subHandle()"> 确认 </el-button>
<el-button @click="closeHandle">取消</el-button>
</div>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { ref, nextTick, onMounted, watch } from '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';
import { setredoSample } from '@/api/liswork/work/LisWork'
import { ElMessage } from 'element-plus';
const props = defineProps({
labPatList: {
type: Array,
default: () => []
},
loading: {
type: Boolean,
default: true
},
dictData: {
type: Object,
default: () => ({})
},
tableKey: {
type: Object,
default: () => { }
}
})
const emits = defineEmits(['select'])
const show = ref(false)
const fcYbh = ref('')
const fcYq = ref('')
const subHandle = () => {
if (!fcYbh.value.trim()) return ElMessage.warning('请输入复查的样本号')
const data = {
newybh: fcYbh.value,
newyq: fcYq.value,
...props.tableKey
}
setredoSample(data).then((res: any) => {
if (res.code == 0) {
ElMessage.success('操作成功')
closeHandle()
}
})
}
const closeHandle = () => {
fcYbh.value = ''
show.value = false
}
const contextMenuItems = computed<ContextMenuItem[]>(() => [
{ label: '本标本结果作其复查结果', action: 'view' }
]);
const handleMenuSelect = ((item: ContextMenuItem) => {
show.value = true
fcYq.value = props.tableKey.yq
})
// 表格列配置
const tableColumns = ref([
{ field: 'jyrq', title: '录入时间', width: 80, align: 'center', resizable: true },
{ field: 'finish', title: '药敏', width: 30, align: 'center', slotName: 'finish', resizable: true },
{ field: 'alarmflag', title: '警', width: 30, align: 'center', slotName: 'alarmflag', resizable: true },
{ field: 'cp_pyzq', title: '培养周期', width: 60, align: 'center', resizable: true },
{ field: 'jgbz', title: '状态', width: 50, align: 'center', resizable: true, slotName: 'jgbz' },
{ field: 'ybh', title: '样本号', width: 100, align: 'center', resizable: true },
{ field: 'brxm', title: '姓名', width: 40, align: 'center', resizable: true, slotName: 'brxm' },
{ field: 'brdh', title: '病历号', width: 80, align: 'center', resizable: true },
{ field: 'ch', title: '床号', width: 40, align: 'center', resizable: true },
{ field: 'brxb', title: '性别', width: 40, align: 'center', slotName: 'brxb', resizable: true },
{ field: 'nl', title: '年', width: 30, align: 'center', resizable: true },
{ field: 'nldw', title: '龄', width: 20, align: 'center', slotName: 'nldw', resizable: true },
{ field: 'ksdh', title: '科室', width: 80, align: 'center', slotName: 'ksdh', resizable: true },
{ field: 'yblx', title: '标本', width: 50, align: 'center', resizable: true, slotName: 'yblx' },
{ field: 'sqh', title: '申请号/条码', width: 100, align: 'center', resizable: true, },
{ field: 'jymd', title: '检验目的', width: 120, align: 'center', resizable: true },
{ field: 'yhdh', title: '检验医生', width: 60, align: 'center', resizable: true, slotName: 'yhdh' },
{ field: 'brly', title: '类型', width: 50, align: 'center', slotName: 'brly', resizable: true },
{ field: 'dybz', title: '印', width: 30, align: 'center', slotName: 'dybz', resizable: true },
{ field: 'shcs', title: '次数', width: 40, align: 'center', resizable: true },
])
const getLableType = (type: string) => {
switch (type) {
case '0':
return '';
case '1':
return '初审';
case '2':
return '终报';
case '3':
return '初报';
case '4':
return '二报';
case '5':
return '已锁定';
default:
return '';
}
}
// 更新列配置
const handleColumnDragEnd = (data: any) => {
// 先清空再赋值,强制触发重新渲染
tableColumns.value = [];
// 使用nextTick确保DOM更新后再设置新值
nextTick(() => {
tableColumns.value = [...data.columns];
});
}
const handleRowClick = (row: any) => {
emits('select', row)
}
const tableRef = ref()
const setCurrentRow = (row: any) => {
tableRef.value.setCurrentRow(row)
}
const clearCurrentRow = () => {
tableRef.value.clearCurrentRow()
}
const cellStyle = ({ row, column }: any) => {
if (column.title == "警" && row.alarmflag == 1) {
return { background: '#f00 !important' };
}
if (column.title == "状态" && row.jgbz == '2') {
return {
background: 'pink !important',
};
}
if (column.title == "状态" && row.jgbz == '3') {
return {
background: '#00ff64 !important',
};
}
if (column.title == "状态" && row.jgbz == '4') {
return { background: '#ffff64 !important' };
}
if (column.title == "类型" && row.brly == '1') { //门诊
return { background: '#e9e930 !important' };
}
if (column.title == "类型" && row.brly == '3') { // 住院
return { background: '#8bdaf1 !important' };
}
if (column.title == "类型" && row.brly == '4') { //体检
return { background: '#9ae382 !important' };
}
}
const rowStyle = ({ row }: any) => {
if (row.dybz == '1') {
return { background: '#C0C0C0 !important' };
}
if (row.lstd == '1') {
return { background: '#ed4ced !important' };
}
if (row.jgbz == '2') {
return { background: '#C0FFC0 !important' };
}
}
// 引入公共组件的字典格式化方法
const formatDict = (v: string, dictType: string) => {
return props.dictData[dictType]?.find((item: any) => item.value == v)?.label || v;
}
onMounted(() => {
const row = props.labPatList.find((item: any) => item.ybh == props.tableKey.ybh)
if (!row) return
setTimeout(() => { setCurrentRow(row) }, 100)
})
// 暴露公共方法
defineExpose({
setCurrentRow,
clearCurrentRow,
tableRef,
})
</script>
<style lang="scss" scoped>
.table-container {
height: 72vh;
.form-box {
font-family: SourceHanSansCN, SourceHanSansCN;
.item {
display: flex;
align-items: center;
span {
display: inline-block;
width: 3.75rem;
}
}
}
}
</style>

View File

@ -0,0 +1,92 @@
<template>
<div>
<div class="top-btns">
<el-button type="primary" plain size="small" @click="printHandle">打印培养基条码</el-button> &nbsp;
<el-checkbox v-model="checked">自动打印培养基条码</el-checkbox>
</div>
<CustomTable ref="tableRef" :data="tableData" :columns="columns" :config="tableConfig" :enable-column-drag="true"
@column-drag-end="handleColumnDragEnd" @selection-change="handleSelectionChange">
<template #mediumname="{ column }">
培养基 {{ tableData.length }}个
</template>
</CustomTable>
</div>
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue';
import { getmediumList } from '@/api/liswork/micro/index';
const props = defineProps({
labPat: {
type: Object,
required: true
},
//结果主键
labPatKey: {
type: Object,
default: () => { }
},
});
const { labPat, labPatKey } = toRefs(props);
const checked = ref(false);
const tableRef = ref();
const tableData = ref([]);
const columns = ref([
{ type: "selection", width: 40, align: 'center', visible: true },
{ label: "培养基", prop: "mediumname", align: 'center', visible: true, width: 80, headerSlot: 'mediumname' },
{ label: "接种时间", prop: "sheetdate", align: 'center', visible: true, width: 120 },
{ label: "接种人", prop: "sheetuser", align: 'center', visible: true, width: 60 },
{ label: "培养基结果", prop: "mediu", align: 'center', visible: true, },
{ label: "转种类型", prop: "comments", align: 'center', visible: true, },
{ label: "培养周期(小时)", prop: "conidtions", align: 'center', visible: true, width: 100 },
{ label: "观察间隔(小时)", prop: "watchinterval", align: 'center', visible: true, width: 100 },
]);
const tableConfig = ref({
border: true,
height: '74vh',
})
const handleColumnDragEnd = (data: any) => {
columns.value = data.columns;
}
const handleSelectionChange = (selection: any) => {
console.log(selection);
}
const printHandle = () => {
console.log('打印培养基条码');
}
const getbyjList = () => {
const data = {
jyrq: labPat.value.jyrq,
yq: labPat.value.yq,
ybh: labPat.value.ybh,
}
getmediumList(data).then((res: any) => {
if (res.code == 0) {
tableData.value = res.data
}
})
}
watch(() => props.labPat, (newValue) => {
if (newValue.jyrq && newValue.ybh && newValue.yq) {
getbyjList()
}
})
</script>
<style scoped lang="scss">
.top-btns {
margin-bottom: .3125rem;
display: flex;
align-items: center;
}
</style>

View File

@ -0,0 +1,648 @@
<template>
<div>
<div class="title">
<div>
<span>初报人:</span>{{ formatUser(cbInfo?.confirmer) }} &nbsp;&nbsp; <span>报告时间:</span>{{ cbInfo?.confirmdt
}}&nbsp;&nbsp;
</div>
<div><span>{{ cbInfo?.jgbz == '2' ? '已初报' : '' }}</span></div>
</div>
<div>
<el-button class="btn_green btns_box" :size="autoSize" v-if="cbInfo?.jgbz != 2"
@click="handleCheck(3)">初报审核</el-button>
<el-button class="btns_box" :size="autoSize" v-if="cbInfo?.jgbz == 2" @click="handleCheck(-3)">取消审核</el-button>
<el-button class="btns_box" type="primary" :size="autoSize" plain :disabled="cbInfo?.jgbz == '2'"
@click="openItemDictDialog(1)">新增</el-button>
<el-button class="btns_box" type="danger" :size="autoSize" :disabled="cbInfo?.jgbz == '2'" plain
@click="handleBatchDelete(1)">删除</el-button>
<el-button class="btn_green btns_box" :size="autoSize" :disabled="cbInfo?.jgbz == '2'"
@click="zhHandel(1)">组合项目</el-button>
<el-button type="primary" plain class=" btns_box" @click="printHandle(1)">打印</el-button>
<el-button type="primary" plain class=" btns_box" @click="previewHandle(2)">预览</el-button>
</div>
<CustomTable :data="tableData" :columns="columns" :config="tableConfig" :enable-column-drag="true"
@column-drag-end="handleColumnDragEnd" @row-click="cbRowClick">
<template #xmdh="{ column }">
细菌/结果({{ tableData.length }})项
</template>
<template #od="{ row }">
<el-input v-model="row.od" v-if="cbInfo?.jgbz != '2'" size="small" class="full-width-input foucs-input"
@change="handleCsjgEnter(row, 1)" />
<span v-else>{{ row.od }}</span>
</template>
<template #csjg="{ row }">
<el-input v-model="row.csjg" v-if="cbInfo?.jgbz != '2'" size="small" class="full-width-input"
@change="handleCsjgEnter(row, 1)" @dblclick="handleInputFocus(row, 1)" />
<span v-else>{{ row.csjg }}</span>
</template>
<template #jgbz="{ row }">
<el-select v-model="row.jgbz" class="full-width-input" v-if="cbInfo?.jgbz != '2'" placeholder=""
@change="handleCsjgEnter(row, 1)">
<el-option label="阳性" value="P" />
<el-option label="阴性" value="N" />
</el-select>
<span v-else> {{ formatJgbz(row.jgbz) }}</span>
</template>
<template #cutoff="{ row }">
<el-input v-model="row.cutoff" v-if="cbInfo?.jgbz != '2'" size="small" class="full-width-input"
@change="handleCsjgEnter(row, 1)" />
<span v-else>{{ row.cutoff }}</span>
</template>
<template #alarm_flag="{ row }">
<el-select v-model="row.alarm_flag" class="full-width-input" v-if="cbInfo?.jgbz != '2'" placeholder=""
@change="handleCsjgEnter(row, 1)">
<el-option label="危急值" value="H" />
<el-option label="无" value="" />
</el-select>
<span v-else> {{ row.alarm_flag == 'H' ? '危急值' : '' }}</span>
</template>
<template #germclass="{ row }">
{{ formatDict(row.germclass, 'germclass') }}
</template>
</CustomTable>
<div class="title ertext">
<div>
<span>二报人:</span>{{ formatUser(erInfo?.confirmer) }} &nbsp;&nbsp; <span>报告时间:</span>{{ erInfo?.confirmdt
}}&nbsp;&nbsp;
</div>
<div><span>{{ erInfo?.jgbz == '2' ? '已二报' : '' }}</span></div>
</div>
<div>
<el-button class="btn_green btns_box" :size="autoSize" v-if="erInfo?.jgbz != 2"
@click="handleCheck(4)">二报审核</el-button>
<el-button class="btns_box" :size="autoSize" v-if="erInfo?.jgbz == 2" @click="handleCheck(-4)">取消审核</el-button>
<el-button class="btns_box" type="primary" :size="autoSize" plain :disabled="erInfo?.jgbz == '2'"
@click="openItemDictDialog(2)">新增</el-button>
<el-button class="btns_box" type="danger" :size="autoSize" :disabled="erInfo?.jgbz == '2'" plain
@click="handleBatchDelete(2)">删除</el-button>
<el-button class="btn_green btns_box" :size="autoSize" :disabled="erInfo?.jgbz == '2'"
@click="zhHandel(2)">组合项目</el-button>
<el-button type="primary" plain class=" btns_box" @click="printHandle(2)">打印</el-button>
<el-button type="primary" plain class=" btns_box" @click="previewHandle(2)">预览</el-button>
</div>
<CustomTable :data="tableData2" :columns="columns" :config="tableConfig" :enable-column-drag="true"
@column-drag-end="handleColumnDragEnd" @row-click="erbRowClick">
<template #xmdh="{ column }">
细菌/结果({{ tableData2.length }})项
</template>
<template #od="{ row }">
<el-input v-model="row.od" v-if="erInfo?.jgbz != '2'" size="small" class="full-width-input foucs-input"
@change="handleCsjgEnter(row, 2)" />
<span v-else>{{ row.od }}</span>
</template>
<template #csjg="{ row }">
<el-input v-model="row.csjg" v-if="erInfo?.jgbz != '2'" size="small" class="full-width-input"
@change="handleCsjgEnter(row, 2)" @dblclick="handleInputFocus(row, 2)" />
<span v-else>{{ row.csjg }}</span>
</template>
<template #jgbz="{ row }">
<el-select v-model="row.jgbz" class="full-width-input" v-if="erInfo?.jgbz != '2'" placeholder=""
@change="handleCsjgEnter(row, 2)">
<el-option label="阳性" value="P" />
<el-option label="阴性" value="N" />
</el-select>
<span v-else> {{ formatJgbz(row.jgbz) }}</span>
</template>
<template #cutoff="{ row }">
<el-input v-model="row.cutoff" v-if="erInfo?.jgbz != '2'" size="small" class="full-width-input"
@change="handleCsjgEnter(row, 2)" />
<span v-else>{{ row.cutoff }}</span>
</template>
<template #alarm_flag="{ row }">
<el-select v-model="row.alarm_flag" class="full-width-input" v-if="erInfo?.jgbz != '2'" placeholder=""
@change="handleCsjgEnter(row, 2)">
<el-option label="危急值" value="H" />
<el-option label="无" value="" />
</el-select>
<span v-else> {{ row.alarm_flag == 'H' ? '危急值' : '' }}</span>
</template>
<template #germclass="{ row }">
{{ formatDict(row.germclass, 'germclass') }}
</template>
</CustomTable>
<!-- 新增明细 -->
<ProjectDetails ref="itemDictRef" :dialog-title="'选择检验项目'" :tableKey="labPatKey" @select="handleItemSelect" />
<!-- 测试结果项目常用结果选择 -->
<projectsJg ref="csjgRef" :tableData='csjgTableData' :dialog-title="'项目常用结果选择'" @selectItem="selectItem"
label="qz" />
<!-- 组合项目 -->
<Combined ref="combinedRef" :queryParams="labPatKey" @dbMbHandle="combinedHandel" />
<!-- 校验用户 -->
<CheckUser ref="checkUserRef" :title="checktitle" @onConfirm="handleCheckUserConfirm" />
<!-- 取消审核操作原因 -->
<Unconfirmlog ref="unconfirmlogRef" :reasonText="reasonText" :tableKey="labPatKey" @onConfirm="proceedCheck" />
<!-- 危急值结果上报 -->
<UploadWarning ref="uploadwarningRef" :warningMsgdata="warningMsgdata" :tableKey="labPatKey"
@onupload="proceedCheck" />
</div>
</template>
<script setup lang="ts">
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";
import CheckUser from "../../work/components/CheckUser.vue";
import Unconfirmlog from "../../work/components/unconfirmlog.vue";
import UploadWarning from "../../work/components/uploadwarning.vue";
// @ts-ignore
import ProjectDetails from "@/components/projectDetails/index.vue";
import projectsJg from "@/components/projectsjg/index.vue";
// @ts-ignore
import Combined from "./components/combinedDialog.vue";
import emitter from '@/utils/mitt';
import { ElMessage, ElMessageBox } from 'element-plus';
import { useCommonStore } from "@/store/modules/commonStore";
import { classCom } from '@/utils/classCom';
const autoSize = classCom.useAutoSize();
const props = defineProps({
labPat: {
type: Object,
required: true
},
//结果主键
labPatKey: {
type: Object,
default: () => { }
},
// 主键仪器参数
instrdComOpt: {
type: Object,
required: true
},
dictData: {
type: Object,
default: () => { }
},
userList: {
type: Array as () => Array<any>,
default: () => []
},
})
const { labPat, labPatKey, instrdComOpt, userList } = toRefs(props);
const tableData = ref<LabResultItem[]>([])
const tableData2 = ref<LabResultItem[]>([])
const cbInfo = ref<any>({})
const erInfo = ref<any>({})
const mbStore = useCommonStore();
watch(labPat, (newVal: any) => {
//获取结果列表
getResultList()
// 获取病人信息
getLabPatInfo()
})
watch(() => tableData, (newValue) => {
// 模板数据
if (labPat.value.jgbz != null && labPat.value.jgbz != 0 && labPat.value.jgbz != 'C') return;
mbList(1)
})
watch(() => tableData2, (newValue) => {
// 模板数据
if (labPat.value.jgbz != null && labPat.value.jgbz != 0 && labPat.value.jgbz != 'C') return;
mbList(2)
})
const getLabPatInfo = () => {
queryLabPat({ jyrq: labPat.value.jyrq, yq: instrdComOpt.value.yq1, ybh: labPat.value.ybh, }).then((response: any) => {
cbInfo.value = response.data;
})
queryLabPat({ jyrq: labPat.value.jyrq, yq: instrdComOpt.value.yq2, ybh: labPat.value.ybh, }).then((response: any) => {
erInfo.value = response.data;
})
}
const getResultList = () => {
// 初级数据
sampleMedInfo({ jyrq: labPat.value.jyrq, yq: instrdComOpt.value.yq1, ybh: labPat.value.ybh, }).then((res: any) => {
if (res.code == 0) {
tableData.value = res.data.map((item: any) => {
return {
...item,
zhxmdh: item.xmdh + ' ' + item.xmmc,
}
})
}
});
// 二级数据
sampleMedInfo({ jyrq: labPat.value.jyrq, yq: instrdComOpt.value.yq2, ybh: labPat.value.ybh, }).then((res: any) => {
if (res.code == 0) {
tableData2.value = res.data.map((item: any) => {
return {
...item,
zhxmdh: item.xmdh + ' ' + item.xmmc,
}
})
}
});
}
const mbList = (type: number) => {
const targetTable = type === 1 ? tableData.value : tableData2.value;
if (mbStore.lxsrs.length > 0) {
mbStore.lxsrs.forEach((mbmc) => {
const data = {
...labPatKey.value,
mbmc: mbmc,
}
setinputmdl(data).then((res: any) => {
if (res.code == 0) {
const existingNames = new Set(targetTable.map((item: any) => item.xmdh))
res.data?.forEach((item: any) => {
if (!existingNames.has(item.xmdh)) {
targetTable.push({ ...item, jyrq: labPat.value.jyrq, zhxmdh: item.xmdh + ' ' + item.xmmc })
existingNames.add(item.xmdh)
}
})
emitter.emit('clearLxsrList')
}
});
});
}
}
// 事件定义
const emits = defineEmits([
'fetchLabResults',
'changeStatus',
'previewHandle',
'update:labPatKey'
]);
const columns = ref([
{ label: "细菌/结果", prop: "zhxmdh", visible: true, headerSlot: 'xmdh', width: 150 },
{ label: "菌落计数", prop: "od", align: 'center', visible: true, slot: 'od' },
{ label: "检验结果", prop: "csjg", align: 'center', visible: true, slot: 'csjg' },
{ label: "阴阳性", prop: "jgbz", align: 'center', visible: true, slot: 'jgbz', showOverflowTooltip: false },
{ label: "危急值", prop: "alarm_flag", align: 'center', visible: true, slot: 'alarm_flag', showOverflowTooltip: false },
{ label: "菌属", prop: "germclass", align: 'center', visible: true, slot: 'germclass' },
{ label: "鉴定率", prop: "cutoff", align: 'center', visible: true, slot: 'cutoff' },
{ label: "抗生素组", prop: "bz1", align: 'center', visible: true, width: 120 },
])
const CellStyleHd = ({ row, column, rowIndex, columnIndex }: {
row: any;
column: any;
rowIndex: number;
columnIndex: number;
}) => {
if (column.label == "细菌/结果" && (row.alarm_flag ?? "").trim().length > 0) {
return { background: '#f00 !important', color: '#FFF' };
}
if (column.label == "危急值" && (row.alarm_flag ?? "").trim().length > 0) {
return { background: '#f00 !important', color: '#FFF' };
}
if (column.label == "检验结果" && row.jgbz == "H") {
return { background: '#ffc0c0 !important', color: '#606266' };
}
if (column.label == "检验结果" && row.jgbz == "L") {
return { background: '#8080ff !important', color: '#fff' };
}
if (column.label == "检验结果" && row.jgbz == "P") {
return { background: '#ffc0c0 !important', color: '#606266' };
}
if (column.label == "检验结果" && row.jgbz == "Q") {
return { background: '#ffff80 !important', color: '#606266' };
}
if (column.label == "阴阳性" && row.jgbz == "H") {
return { background: '#ffc0c0 !important', color: '#606266' };
}
if (column.label == "阴阳性" && row.jgbz == "L") {
return { background: '#8080ff !important', color: '#fff' };
}
if (column.label == "阴阳性" && row.jgbz == "P") {
return { background: '#ffc0c0 !important', color: '#606266' };
}
if (column.label == "阴阳性" && row.jgbz == "Q") {
return { background: '#ffff80 !important', color: '#606266' };
}
};
const tableConfig = ref({
height: '32vh',
border: true,
highlightCurrentRow: true,
cellStyle: CellStyleHd
});
const handleColumnDragEnd = (data: any) => {
columns.value = data.columns;
}
const checktitle = ref('');
const shType = ref('') // 审核类型 cb初报 erb二报
const bgType = ref(1) // 报告类型 1初报 2二报
const checkUserRef = ref();
const unconfirmlogRef = ref();
const uploadwarningRef = ref();
const runnextstepname = ref(-1);
const reasonText = ref('');
const warningMsgdata = ref('');
const handleCheck = (checkType: number,) => {
runnextstepname.value = checkType
labPatKey.value.problemId = 0;
if (!labPatKey.value.yhdh) {
checktitle.value = '审核人工号密码验证'
checkUserRef.value.open()
} else {
proceedCheck()
}
};
const handleCheckUserConfirm = (info: { yhdh: string, mm: string }) => {
checkuser({ yhdh: info.yhdh, mm: info.mm }).then((response: any) => {
if (response.code == 0) {
emits('update:labPatKey', {
...labPatKey.value,
yhdh: info.yhdh
});
proceedCheck()
}
})
}
const proceedCheck = () => {
const data = {
yq: labPat.value.yq,
yhdh: labPat.value.yhdh,
ybh: labPat.value.ybh,
jyrq: labPat.value.jyrq,
jgbz: runnextstepname.value,
}
cbebCheck(data).then((res: any) => {
if (res.code == "4" && res.problemId === 4) {
labPatKey.value.problemId = res.problemId;
warningMsgdata.value = res.msg;
uploadwarningRef.value.open();
}
if (res.code == "4") {
labPatKey.value.problemId = res.problemId;
reasonText.value = res.msg;
unconfirmlogRef.value.open();
}
emits("changeStatus", labPat.value);
})
};
const selectedRows = ref<LabResultItem[]>([])
const erbRowClick = (row: LabResultItem) => {
bgType.value = 2
selectedRows.value = [row];
}
const cbRowClick = (row: LabResultItem) => {
bgType.value = 1
selectedRows.value = [row];
}
const handleBatchDelete = (type: number) => {
if (selectedRows.value.length === 0) return ElMessage.warning("请先选择要删除的记录");
ElMessageBox.confirm(
`确定要删除选中的 ${selectedRows.value.length} 条记录吗?`,
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
).then(() => {
deleteresult(selectedRows.value).then((res: any) => {
if (res.code == 0) {
ElMessage.success('删除成功');
getResultList()
selectedRows.value = []
}
})
}).catch(() => {
});
}
// 项目结果保存
const handleCsjgEnter = async (row: any, type: number) => {
bgType.value = type
const yq = type === 1 ? instrdComOpt.value.yq1 : instrdComOpt.value.yq2
const targetTable = type === 1 ? tableData.value : tableData2.value;
// 判断数据中包含模板新增的数据 flag
if (targetTable.length == 0) return
const flag = targetTable.some((item: any) => item.changeflag == 2)
if (flag) {
saveresult(targetTable).then((res: any) => {
if (res.code == 0) {
getResultList()
}
})
} else {
if (!row) return
if (row && row.id) {
newresult({ ...row, ybh: labPat.value.ybh, jyrq: labPat.value.jyrq, yq }).then((response: any) => {
ElMessage.success("结果保存成功");
getResultList()
}).catch((error: any) => {
getResultList()
});
} else {
changeresult(row).then((response: any) => {
ElMessage.success("结果保存成功");
getResultList()
}).catch((error: any) => {
getResultList()
});
}
// nextTick(() => {
// const input = document.activeElement;
// if (input?.tagName === "INPUT") input?.blur();
// });
}
};
const printHandle = (type: number) => {
const yq = type === 1 ? instrdComOpt.value.yq1 : instrdComOpt.value.yq2
const data = {
jyrq: labPat.value.jyrq,
yq: yq,
ybh: labPat.value.ybh,
sqh: labPat.value.sqh
}
printListwork(data).then((res: any) => {
if (res.code == 0) {
classCom.printBase64PDF(res.data)
}
})
};
const previewHandle = (type: number) => {
const yq = type === 1 ? instrdComOpt.value.yq1 : instrdComOpt.value.yq2
const data = {
jyrq: labPat.value.jyrq,
yq: yq,
ybh: labPat.value.ybh,
sqh: labPat.value.sqh
}
printListwork(data).then((res: any) => {
if (res.code == 0) {
emits('previewHandle', res.data);
}
})
};
const itemDictRef = ref();
const openItemDictDialog = (type: number) => {
bgType.value = type
itemDictRef.value.openDictSelector();
};
const handleItemSelect = async (selectedItem: any) => {
const yq = bgType.value === 1 ? instrdComOpt.value.yq1 : instrdComOpt.value.yq2
const targetTable = bgType.value === 1 ? tableData.value : tableData2.value;
// 1. 构造新增行数据
const newRow = {
id: `temp_${Date.now()}_${Math.random().toString(36).substr(2, 8)}`,
xmdh: selectedItem.value,
xmmc: selectedItem.label,
dw: selectedItem.dw || "",
refs: selectedItem.refs || "",
jyrq: labPatKey.value.jyrq,
yq: yq,
ybh: labPatKey.value.ybh,
od: '',
csjg: "",
jgbz: "",
alarm_flag: '',
cutoff: '',
qz: '',
zhxmdh: selectedItem.value + ' ' + selectedItem.label,
};
const isDuplicate = targetTable.some((item: any) => item.xmdh === newRow.xmdh);
if (isDuplicate) return ElMessage.warning(`项目【${newRow.xmmc}】已存在`);
targetTable.push(newRow);
newresult({ ...newRow, ybh: labPat.value.ybh, jyrq: labPat.value.jyrq, yq })
// 5. 自动聚焦
// nextTick(() => {
// selectedRows.value = [newRow];
// tableRef.value.setCurrentRow(newRow);
// tableRef.value.setScrollTo(targetTable.length - 1)
// // 聚焦到新行的输入框
// const inputs = Array.from(document.querySelectorAll('.foucs-input .el-input__inner'))
// .filter(el => el instanceof HTMLElement) as HTMLElement[];
// if (inputs.length > 0) {
// inputs[inputs.length - 1].focus();
// }
// });
// ElMessage.success(`已新增项目:${newRow.xmmc}`);
};
const csjgRef = ref()
const csjgTableData = ref([])
const handleInputFocus = (row: any, type: number) => {
bgType.value = type
// dbRow.value = row
queryXmVal({ yq: labPatKey.value.yq, xmdh: row.xmdh }).then((res: any) => {
if (res.code == 0) {
csjgTableData.value = res.data
}
nextTick(() => {
csjgRef.value.open()
})
})
};
const selectItem = (row: any) => {
const targetTable = bgType.value === 1 ? tableData.value : tableData2.value;
// 查找修改行
const index = targetTable.findIndex((item: any) => item.xmdh == row.xmdh)
targetTable[index].csjg = row.qz
handleCsjgEnter(targetTable[index], bgType.value)
};
// 组合项目
const combinedRef = ref()
const zhHandel = (type: number) => {
bgType.value = type
combinedRef.value.open()
};
const combinedHandel = (row: any) => {
const targetTable = bgType.value === 1 ? tableData.value : tableData2.value;
const yq = bgType.value === 1 ? instrdComOpt.value.yq1 : instrdComOpt.value.yq2;
const data = {
...labPatKey.value,
mbmc: row.mbmc,
}
setinputmdl(data).then((res: any) => {
if (res.code == 0) {
const existingNames = new Set(targetTable.map((item: any) => item.xmdh))
res.data?.forEach((item: any) => {
if (!existingNames.has(item.xmdh)) {
targetTable.push({ ...item, jyrq: labPat.value.jyrq, zhxmdh: item.xmdh + ' ' + item.xmmc, yq })
existingNames.add(item.xmdh)
}
})
handleCsjgEnter(null, bgType.value)
emitter.emit('clearLxsrList')
}
});
};
const formatDict = (v: string, dictType: string) => {
return props.dictData[dictType]?.find((item: any) => item.value == v)?.label || v;
}
const formatJgbz = (v: string) => {
return v == 'H' ? '高' : v == 'L' ? '低' : v == 'N' ? '阴性' : v == 'P' ? '阳性' : v == 'Q' ? '弱阳性' : v == 'M' ? '正常' : ''
}
const formatUser = (yhdh: string) => {
return userList.value.find((item: any) => item.userName == yhdh)?.nickName || yhdh
}
</script>
<style scoped lang="scss">
.title {
border-bottom: 1px solid #e8e8e8;
display: flex;
justify-content: space-between;
padding: 3px 0;
font-family: SourceHanSansCN, SourceHanSansCN;
span {
color: #057c34;
}
}
.ertext {
margin-top: 10px;
span {
color: #e2e20c;
}
}
</style>

View File

@ -0,0 +1,82 @@
<template>
<el-dialog :title="dialogTitle" v-model="csjgVisible" width="30vw" :close-on-click-modal="false" :draggable="true">
<div class="bination_box">
<CustomTable ref="tableRef" :data="tableData" :columns="columns" :config="tableConfig"
@row-dblclick="handleRowDblclick">
</CustomTable>
</div>
</el-dialog>
</template>
<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 emitter from '@/utils/mitt'
import { useCommonStore } from '@/store/modules/commonStore';
const props = defineProps({
// 主键
queryParams: {
type: Object,
default: {}
},
dialogTitle: {
type: String,
default: '检验项目选择'
},
})
const csjgVisible = ref(false)
const emit = defineEmits(['dbMbHandle'])
const mbStore = useCommonStore();
const { queryParams } = toRefs(props);
const tableData: any = ref([])
const columns = ref([
{ prop: 'mbmc', label: '批输入模板', visible: true, align: 'center', },
{ prop: 'yblx', label: '标本类型', visible: true, align: 'center', },
{ prop: 'srbh', label: '输入编号', visible: true, align: 'center', },
])
// 左侧表格配置
const tableConfig = ref({
border: true, // 边框
height: '40vh', // 高度
highlightCurrentRow: true, // 高亮当前行
})
const getCombination = () => {
inputmdl(queryParams.value).then((res: any) => {
if (res.code == 0) {
tableData.value = res.data?.map((item: any) => {
return {
...item,
lxsr: mbStore.lxsrs.includes(item.mbmc) ? true : false,
}
})
}
})
};
const open = () => {
csjgVisible.value = true;
nextTick(() => {
getCombination();
});
}
const handleRowDblclick = (row: any) => {
emit('dbMbHandle', row);
csjgVisible.value = false;
}
defineExpose({
open
})
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,159 @@
<template>
<div class="dict-input-wrapper">
<!-- 字典选择弹窗 -->
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="30vw" :close-on-click-modal="false" :draggable="true"
@close="handleDialogClose">
<el-input ref="inputRef" v-model="searchKey" placeholder="搜索(支持名称、编码、简拼)..." class="mb10" clearable
@clear="filterDictData" @input="filterDictData" />
<el-table :data="filteredDictData" height="300px" border @row-dblclick="selectItem" highlight-current-row>
<!-- <el-table-column prop="value" label="抗生素组" align="center" width="150" /> -->
<el-table-column prop="label" label="抗生素组" align="center" show-overflow-tooltip />
<el-table-column prop="pinyin" label="简拼" align="center" width="150" /> <!-- 显示简拼便于调试 -->
</el-table>
</el-dialog>
</div>
</template>
<script setup>
import { ref, computed, watch, onMounted } from 'vue';
import { getmedgroupList } from '@/api/liswork/micro/index';
import { getFirstLetter } from '@/utils/pinyin.js'; // 引入拼音处理工具
// 组件参数
const props = defineProps({
modelValue: { type: [String, Number], default: '' },
dictType: { type: String },
placeholder: { type: String, default: '请输入或双击选择' },
clearable: { type: Boolean, default: true },
disabled: { type: Boolean, default: false },
dialogTitle: { type: String, default: '选择字典项' },
tableKey: { type: Object, default: () => { } },
});
// 组件事件
const emit = defineEmits(['select']);
const dictData = ref([]); // 存储带简拼的字典数据
const filteredDictData = ref([]);
const isDictLoading = ref(false);
const dialogVisible = ref(false);
const searchKey = ref('');
// 加载字典数据(并添加简拼字段)
const loadDictData = async () => {
try {
isDictLoading.value = true;
const response = await getmedgroupList();
const rawData = response.data.map((item, index) => {
return {
value: item.ywzmc || `未知编码_${index}`, // 确保value存在
label: item.ywzmc || `未知名称_${index}`, // 确保label存在
};
});
// 为每个字典项添加简拼字段
dictData.value = (rawData || []).map(item => ({
...item,
pinyin: getFirstLetter(item.label) // 新增pinyin字段存储简拼
}));
filteredDictData.value = [...dictData.value];
} catch (error) {
console.error(`加载${props.dictType}字典失败:`, error);
dictData.value = [];
filteredDictData.value = [];
} finally {
isDictLoading.value = false;
}
};
// 核心搜索逻辑(支持模糊搜索+简拼搜索)
const filterDictData = () => {
const key = searchKey.value.trim().toLowerCase();
if (!key) {
filteredDictData.value = [...dictData.value];
return;
}
filteredDictData.value = dictData.value.filter(item => {
// 1. 模糊搜索:匹配label(名称)或value(编码)
const matchLabel = item.label.toLowerCase().includes(key);
const matchValue = String(item.value).toLowerCase().includes(key);
// 2. 简拼搜索:匹配首字母简拼
const matchPinyin = item.pinyin.toLowerCase().includes(key);
// 满足任一条件即匹配
return matchLabel || matchValue || matchPinyin;
});
};
const inputRef = ref()
// 关键修改:打开弹窗时重新加载数据
const openDictSelector = async () => {
if (props.disabled || isDictLoading.value) {
return;
}
// 打开弹窗前先加载数据(确保每次打开都是最新的)
await loadDictData();
// 数据加载完成后再显示弹窗
dialogVisible.value = true;
searchKey.value = '';
nextTick(() => {
setTimeout(() => {
inputRef.value.focus();
}, 100);
});
filterDictData();
};
// 选择字典项
const selectItem = (item) => {
emit('select', item);
dialogVisible.value = false;
};
const handleDialogClose = () => {
dialogVisible.value = false;
};
defineExpose({
openDictSelector, // 暴露打开弹窗的方法
// 可选:暴露其他可能需要的方法(如刷新字典数据)
loadDictData
});
</script>
<style scoped>
/* 样式保持不变 */
.dict-input-wrapper {
position: relative;
}
.select-icon {
cursor: pointer;
color: #666;
margin-left: 5px;
}
.select-icon:hover {
color: #409eff;
}
:deep(.el-input__suffix) {
gap: 4px;
}
</style>

View File

@ -0,0 +1,159 @@
<template>
<div class="dict-input-wrapper">
<!-- 字典选择弹窗 -->
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="30vw" :close-on-click-modal="false" :draggable="true"
@close="handleDialogClose">
<el-input ref="inputRef" v-model="searchKey" placeholder="搜索(支持名称、编码、简拼)..." class="mb10" clearable
@clear="filterDictData" @input="filterDictData" />
<el-table :data="filteredDictData" height="300px" border @row-dblclick="selectItem" highlight-current-row>
<el-table-column prop="value" label="编码" align="center" width="150" />
<el-table-column prop="label" label="名称" align="center" show-overflow-tooltip />
<el-table-column prop="pinyin" label="简拼" align="center" width="150" /> <!-- 显示简拼便于调试 -->
</el-table>
</el-dialog>
</div>
</template>
<script setup>
import { ref, computed, watch, onMounted } from 'vue';
import { getmeddictList } from '@/api/liswork/micro/index';
import { getFirstLetter } from '@/utils/pinyin.js'; // 引入拼音处理工具
// 组件参数
const props = defineProps({
modelValue: { type: [String, Number], default: '' },
dictType: { type: String },
placeholder: { type: String, default: '请输入或双击选择' },
clearable: { type: Boolean, default: true },
disabled: { type: Boolean, default: false },
dialogTitle: { type: String, default: '选择字典项' },
tableKey: { type: Object, default: () => { } },
});
// 组件事件
const emit = defineEmits(['select']);
const dictData = ref([]); // 存储带简拼的字典数据
const filteredDictData = ref([]);
const isDictLoading = ref(false);
const dialogVisible = ref(false);
const searchKey = ref('');
// 加载字典数据(并添加简拼字段)
const loadDictData = async () => {
try {
isDictLoading.value = true;
const response = await getmeddictList();
const rawData = response.data.map((item, index) => {
return {
value: item.ywdh || `未知编码_${index}`, // 确保value存在
label: item.ywmc || `未知名称_${index}`, // 确保label存在
};
});
// 为每个字典项添加简拼字段
dictData.value = (rawData || []).map(item => ({
...item,
pinyin: getFirstLetter(item.label) // 新增pinyin字段存储简拼
}));
filteredDictData.value = [...dictData.value];
} catch (error) {
console.error(`加载${props.dictType}字典失败:`, error);
dictData.value = [];
filteredDictData.value = [];
} finally {
isDictLoading.value = false;
}
};
// 核心搜索逻辑(支持模糊搜索+简拼搜索)
const filterDictData = () => {
const key = searchKey.value.trim().toLowerCase();
if (!key) {
filteredDictData.value = [...dictData.value];
return;
}
filteredDictData.value = dictData.value.filter(item => {
// 1. 模糊搜索:匹配label(名称)或value(编码)
const matchLabel = item.label.toLowerCase().includes(key);
const matchValue = String(item.value).toLowerCase().includes(key);
// 2. 简拼搜索:匹配首字母简拼
const matchPinyin = item.pinyin.toLowerCase().includes(key);
// 满足任一条件即匹配
return matchLabel || matchValue || matchPinyin;
});
};
const inputRef = ref()
// 关键修改:打开弹窗时重新加载数据
const openDictSelector = async () => {
if (props.disabled || isDictLoading.value) {
return;
}
// 打开弹窗前先加载数据(确保每次打开都是最新的)
await loadDictData();
// 数据加载完成后再显示弹窗
dialogVisible.value = true;
searchKey.value = '';
nextTick(() => {
setTimeout(() => {
inputRef.value.focus();
}, 100);
});
filterDictData();
};
// 选择字典项
const selectItem = (item) => {
emit('select', item);
dialogVisible.value = false;
};
const handleDialogClose = () => {
dialogVisible.value = false;
};
defineExpose({
openDictSelector, // 暴露打开弹窗的方法
// 可选:暴露其他可能需要的方法(如刷新字典数据)
loadDictData
});
</script>
<style scoped>
/* 样式保持不变 */
.dict-input-wrapper {
position: relative;
}
.select-icon {
cursor: pointer;
color: #666;
margin-left: 5px;
}
.select-icon:hover {
color: #409eff;
}
:deep(.el-input__suffix) {
gap: 4px;
}
</style>

View File

@ -0,0 +1,61 @@
<template>
<div>
<CustomTable :data="tableData" :columns="columns" :config="tableConfig"></CustomTable>
</div>
</template>
<script setup lang="ts">
import CustomTable from "@/components/elTable/index.vue"
import { getComLog } from "@/api/liswork/micro/index"
const props = defineProps({
labPat: {
type: Object,
required: true
},
//结果主键
labPatKey: {
type: Object,
default: () => { }
},
});
const { labPat, labPatKey } = toRefs(props);
const tableData = ref([])
const columns = ref([
{ label: "操作时间", prop: "rzdt", align: 'center', visible: true },
{ label: "操作", prop: "rzbz", align: 'center', visible: true },
{ label: "操作人", prop: "yhdh", align: 'center', visible: true },
{ label: "操作电脑", prop: "dnmc", align: 'center', visible: true },
{ label: "操作记录", prop: "rznr", align: 'center', visible: true },
{ label: "备注", prop: "bz", align: 'center', visible: true },
])
const tableConfig = ref({
border: true,
height: '78vh'
})
const getRecordList = () => {
const data = {
jyrq: labPat.value.jyrq,
yq: labPat.value.yq,
ybh: labPat.value.ybh,
}
getComLog(data).then((res: any) => {
if (res.code == 0) {
tableData.value = res.data
}
})
}
watch(() => props.labPat, (newValue) => {
if (newValue.jyrq && newValue.ybh && newValue.yq) {
getRecordList()
}
})
</script>
<style scoped></style>

View File

@ -0,0 +1,820 @@
<template>
<div>
<div>
<el-button class="btn_green btns_box" :size="autoSize" v-if="labPat.jgbz != 2"
@click="handleCheck(2)">审核</el-button>
<el-button class="btns_box" :size="autoSize" v-if="labPat.jgbz == 2" @click="handleCheck(3)">取消审核</el-button>
<el-button class="btns_box" type="primary" :size="autoSize" plain
:disabled="labPat.jgbz != null && labPat.jgbz != 0" @click="openItemDictDialog">新增</el-button>
<el-button class="btns_box" type="danger" :size="autoSize" :disabled="labPat.jgbz != null && labPat.jgbz != 0"
plain @click="handleBatchDelete">删除</el-button>
<el-button class="btn_green btns_box" :size="autoSize" @click="zhHandel">组合项目</el-button>
</div>
<CustomTable ref="tableRef" :data="tableData" :columns="columns" :config="tableConfig" :enable-column-drag="true"
@column-drag-end="handleColumnDragEnd" @row-click="rowHandle">
<template #xmdh="{ column }">
细菌/结果({{ tableData.length }})项
</template>
<template #od="{ row }">
<el-input v-model="row.od" v-if="labPat.jgbz == 0 || labPat.jgbz == null" size="small"
class="full-width-input foucs-input" @change="handleCsjgEnter(row)" />
<span v-else>{{ row.od }}</span>
</template>
<template #csjg="{ row }">
<el-input v-model="row.csjg" v-if="labPat.jgbz == 0 || labPat.jgbz == null" size="small"
class="full-width-input" @change="handleCsjgEnter(row)" @dblclick="handleInputFocus(row)" />
<span v-else>{{ row.csjg }}</span>
</template>
<template #jgbz="{ row }">
<el-select v-model="row.jgbz" class="full-width-input" v-if="labPat.jgbz == 0 || labPat.jgbz == null"
placeholder="" @change="handleCsjgEnter(row)">
<el-option label="阳性" value="P" />
<el-option label="阴性" value="N" />
</el-select>
<span v-else> {{ formatJgbz(row.jgbz) }}</span>
</template>
<template #cutoff="{ row }">
<el-input v-model="row.cutoff" v-if="labPat.jgbz == 0 || labPat.jgbz == null" size="small"
class="full-width-input" @change="handleCsjgEnter(row)" />
<span v-else>{{ row.cutoff }}</span>
</template>
<template #alarm_flag="{ row }">
<el-select v-model="row.alarm_flag" class="full-width-input" v-if="labPat.jgbz == 0 || labPat.jgbz == null"
placeholder="" @change="handleCsjgEnter(row)">
<el-option label="危急值" value="H" />
<el-option label="无" value="" />
</el-select>
<span v-else> {{ row.alarm_flag == 'H' ? '危急值' : '' }}</span>
</template>
<template #germclass="{ row }">
{{ formatDict(row.germclass, 'germclass') }}
</template>
</CustomTable>
<div class="tabs_btns">
<el-tabs v-model="activeName2" type="card" class="demo-tabs" :size="autoSize">
<el-tab-pane label="药敏结果" name="first">
<CustomTable ref="ymTableRef" :data="ymTableData" :columns="ymColumns" :config="ymTableConfig"
:enable-column-drag="true" @row-click="ymRowHandle" @column-drag-end="ymHandleColumnDragEnd">
<template #ywdhHead="{ column }">
抗生素({{ ymTableData.length }})项
</template>
<template #mic="{ row }">
<el-input v-model="row.mic" v-if="labPat.jgbz == 0 || labPat.jgbz == null" size="small"
class="ymFoucs full-width-input" @change="ymHandleEnter(row)" />
<span v-else>{{ row.mic }}</span>
</template>
<template #rad="{ row }">
<el-input v-model="row.rad" v-if="labPat.jgbz == 0 || labPat.jgbz == null" size="small"
class="full-width-input" @change="ymHandleEnter(row)" />
<span v-else>{{ row.rad }}</span>
</template>
<template #csjg="{ row }">
<el-input v-model="row.csjg" v-if="labPat.jgbz == 0 || labPat.jgbz == null" size="small"
class="full-width-input" @change="ymHandleEnter(row)" />
<span v-else>{{ row.csjg }}</span>
</template>
<template #jgbz="{ row }">
<el-radio-group v-model="row.jgbz" :disabled="labPat.jgbz == 0 || labPat.jgbz == null ? false : true"
@change="(val: string) => { jgbzHandle(val, row) }">
<el-radio value="R">R</el-radio>
<el-radio value="I">I</el-radio>
<el-radio value="S">S</el-radio>
<el-radio value="N">N</el-radio>
<el-radio value="D">SDD</el-radio>
</el-radio-group>
</template>
<template #bz="{ row }">
<el-input v-model="row.bz" v-if="labPat.jgbz == 0 || labPat.jgbz == null" size="small"
class="full-width-input" @change="ymHandleEnter(row)" />
<span v-else>{{ row.bz }}</span>
</template>
<template #txtresult="{ row }">
<el-input v-model="row.txtresult" v-if="labPat.jgbz == 0 || labPat.jgbz == null" size="small"
class="full-width-input" @change="ymHandleEnter(row)" />
<span v-else>{{ row.txtresult }}</span>
</template>
<template #cp_bz="{ row }">
<el-input v-model="row.cp_bz" v-if="labPat.jgbz == 0 || labPat.jgbz == null" size="small"
class="full-width-input" @change="ymHandleEnter(row)" />
<span v-else>{{ row.cp_bz }}</span>
</template>
</CustomTable>
</el-tab-pane>
<el-tab-pane label="专家评语" name="second">
<el-input v-model="textarea" style="width: 100%" :rows="20" type="textarea" />
</el-tab-pane>
</el-tabs>
<div class="btns anchor">
<template v-if="activeName2 == 'first'">
<el-button class="btns_box" type="primary" :size="autoSize" plain
:disabled="labPat.jgbz != null && labPat.jgbz != 0" @click="addMed">新增</el-button>
<el-button class="btns_box" type="danger" :size="autoSize" :disabled="labPat.jgbz != null && labPat.jgbz != 0"
plain @click="delMed">删除</el-button>
<el-button type="primary" class="btns_box" plain :size="autoSize" @click="changeKss">更换抗生素组</el-button>
<el-button type="primary" class="btns_box" plain :size="autoSize" @click="addKss">添加抗生素组</el-button>
</template>
<template v-if="activeName2 == 'second'">
<el-button type="primary" class="btns_box" plain :size="autoSize" @click="handleTextareaEnter">确定</el-button>
<el-button type="primary" class="btns_box" plain :size="autoSize" @click="textarea = ''">清除</el-button>
</template>
</div>
</div>
<!-- 新增明细 -->
<ProjectDetails ref="itemDictRef" :dialog-title="'选择检验项目'" :tableKey="labPatKey" @select="handleItemSelect" />
<!-- 测试结果项目常用结果选择 -->
<projectsJg ref="csjgRef" :tableData='csjgTableData' :dialog-title="'项目常用结果选择'" @selectItem="selectItem"
label="qz" />
<!-- 组合项目 -->
<Combined ref="combinedRef" :queryParams="labPatKey" @dbMbHandle="combinedHandel" />
<!-- 药敏字典 -->
<Meddict ref="medDictRef" :dialog-title="'抗生素选择'" :tableKey="labPatKey" @select="medSelect" />
<!-- 抗生素组模板 -->
<kssMb ref="kssMbRef" :dialog-title="'抗生素组选择'" :tableKey="labPatKey" @select="kssSelect" />
<!-- 校验用户 -->
<CheckUser ref="checkUserRef" :title="checktitle" @onConfirm="handleCheckUserConfirm" />
<!-- 取消审核操作原因 -->
<Unconfirmlog ref="unconfirmlogRef" :reasonText="reasonText" :tableKey="labPatKey" @onConfirm="unShHandle" />
<!-- 危急值结果上报 -->
<UploadWarning ref="uploadwarningRef" :warningMsgdata="warningMsgdata" :tableKey="labPatKey"
@onupload="shHandleCheck" />
</div>
</template>
<script setup lang="ts">
import CustomTable from "@/components/elTable/index.vue";
import { classCom } from "@/utils/classCom";
import {
getresultmedList, savetestResult, changeresult, saveresult, newresult, getmeddictList, savemedresult,
savemedresultall, deletemedresult, getmedgroupMbList
} from '@/api/liswork/micro/index';
import { check2, uncheck2, unconfirmlog, checkuser, deleteresult, queryXmVal, setinputmdl, } from "@/api/liswork/work/LisWork";
import { useCommonStore } from "@/store/modules/commonStore";
import CheckUser from "../../work/components/CheckUser.vue";
import Unconfirmlog from "../../work/components/unconfirmlog.vue";
import UploadWarning from "../../work/components/uploadwarning.vue";
// @ts-ignore
import ProjectDetails from "@/components/projectDetails/index.vue";
import projectsJg from "@/components/projectsjg/index.vue";
// @ts-ignore
import kssMb from "./components/kssMb.vue";
import Combined from "./components/combinedDialog.vue";
// @ts-ignore
import Meddict from "./components/meddict.vue";
import { ElMessage, ElMessageBox } from "element-plus";
import emitter from "@/utils/mitt";
const autoSize = classCom.useAutoSize();
import { LabResultItem, ymTableDataItem } from '@/types/index';
const props = defineProps({
labPat: {
type: Object,
required: true
},
//结果主键
labPatKey: {
type: Object,
default: () => { }
},
labResutsData: {
type: Array as PropType<LabResultItem[]>,
default: () => []
},
dictData: {
type: Object,
default: () => { }
}
});
const { labPat, labPatKey, labResutsData, dictData } = toRefs(props);
// 事件定义
const emits = defineEmits([
'fetchLabResults',
'changeStatus',
'previewHandle',
'update:labPatKey'
]);
const activeName2 = ref('first')
const textarea = ref('')
const columns = ref([
{ label: "细菌/结果", prop: "zhxmdh", visible: true, headerSlot: 'xmdh', width: 150 },
{ label: "菌落计数", prop: "od", align: 'center', visible: true, slot: 'od' },
{ label: "检验结果", prop: "csjg", align: 'center', visible: true, slot: 'csjg' },
{ label: "阴阳性", prop: "jgbz", align: 'center', visible: true, slot: 'jgbz', showOverflowTooltip: false },
{ label: "危急值", prop: "alarm_flag", align: 'center', visible: true, slot: 'alarm_flag', showOverflowTooltip: false },
{ label: "菌属", prop: "germclass", align: 'center', visible: true, slot: 'germclass' },
{ label: "鉴定率", prop: "cutoff", align: 'center', visible: true, slot: 'cutoff' },
{ label: "抗生素组", prop: "bz1", align: 'center', visible: true, width: 120 },
])
const CellStyleHd = ({ row, column, rowIndex, columnIndex }: {
row: any;
column: any;
rowIndex: number;
columnIndex: number;
}) => {
if (column.label == "细菌/结果" && (row.alarm_flag ?? "").trim().length > 0) {
return { background: '#f00 !important', color: '#FFF' };
}
if (column.label == "危急值" && (row.alarm_flag ?? "").trim().length > 0) {
return { background: '#f00 !important', color: '#FFF' };
}
if (column.label == "检验结果" && row.jgbz == "H") {
return { background: '#ffc0c0 !important', color: '#606266' };
}
if (column.label == "检验结果" && row.jgbz == "L") {
return { background: '#8080ff !important', color: '#fff' };
}
if (column.label == "检验结果" && row.jgbz == "P") {
return { background: '#ffc0c0 !important', color: '#606266' };
}
if (column.label == "检验结果" && row.jgbz == "Q") {
return { background: '#ffff80 !important', color: '#606266' };
}
if (column.label == "阴阳性" && row.jgbz == "H") {
return { background: '#ffc0c0 !important', color: '#606266' };
}
if (column.label == "阴阳性" && row.jgbz == "L") {
return { background: '#8080ff !important', color: '#fff' };
}
if (column.label == "阴阳性" && row.jgbz == "P") {
return { background: '#ffc0c0 !important', color: '#606266' };
}
if (column.label == "阴阳性" && row.jgbz == "Q") {
return { background: '#ffff80 !important', color: '#606266' };
}
};
const tableConfig = ref({
height: '24vh',
border: true,
highlightCurrentRow: true,
cellStyle: CellStyleHd
});
const handleColumnDragEnd = (data: any) => {
columns.value = data.columns;
}
const reasonText = ref('');
const warningMsgdata = ref('');
const checktitle = ref('');
const checkUserRef = ref();
const runnextstepname = ref(-1);
const handleCheck = (checkType: number) => {
runnextstepname.value = checkType
labPatKey.value.problemId = 0;
if (!labPatKey.value.yhdh) {
checktitle.value = '审核人工号密码验证'
checkUserRef.value.open()
} else {
proceedCheck(checkType)
}
};
const handleCheckUserConfirm = (info: { yhdh: string, mm: string }) => {
checkuser({ yhdh: info.yhdh, mm: info.mm }).then((response: any) => {
if (response.code == 0) {
emits('update:labPatKey', {
...labPatKey.value,
yhdh: info.yhdh
});
proceedCheck(runnextstepname.value)
}
})
}
const proceedCheck = (type: number) => {
switch (type) {
case 2: // 审核
labPatKey.value.problemId = 0
shHandleCheck()
break;
case 3: // 取消审核
labPatKey.value.problemId = 0
unShHandle()
break;
default:
break;
}
}
const uploadwarningRef = ref();
const shHandleCheck = () => {
check2({ ...labPatKey.value, jyrq: labPat.value.jyrq, yhdh: props.labPat.yhdh }).then((res: any) => {
emits("changeStatus", props.labPat);
if (res.code == "4" && res.problemId === 4) {
labPatKey.value.problemId = res.problemId;
warningMsgdata.value = res.msg;
uploadwarningRef.value.open();
}
})
};
const unconfirmlogRef = ref();
const unShHandle = () => {
uncheck2({ ...labPatKey.value, jyrq: labPat.value.jyrq, yhdh: props.labPat.yhdh }).then((res: any) => {
if (res.code == "4") {
labPatKey.value.problemId = res.problemId;
reasonText.value = res.msg;
unconfirmlogRef.value.open();
}
emits("changeStatus", props.labPat);
})
};
const itemDictRef = ref();
const openItemDictDialog = () => {
itemDictRef.value.openDictSelector();
};
const handleItemSelect = async (selectedItem: any) => {
// 1. 构造新增行数据
const newRow = {
id: `temp_${Date.now()}_${Math.random().toString(36).substr(2, 8)}`,
xmdh: selectedItem.value,
xmmc: selectedItem.label,
dw: selectedItem.dw || "",
refs: selectedItem.refs || "",
jyrq: labPatKey.value.jyrq,
yq: labPatKey.value.yq,
ybh: labPatKey.value.ybh,
};
addRowFromDict(newRow);
// ElMessage.success(`已新增项目:${newRow.xmmc}`);
};
const selectedRows: any = ref([])
const tableRef = ref()
// 新增行核心方法:接收父组件传递的项目数据
const addRowFromDict = async (rowData: any) => {
if (!rowData.xmdh) return ElMessage.error("新增失败:项目编码不能为空");
const isDuplicate = tableData.value.some((item: any) => item.xmdh === rowData.xmdh);
if (isDuplicate) return ElMessage.warning(`项目【${rowData.xmmc}】已存在`);
const newRow = {
...rowData,
od: '',
csjg: "",
jgbz: "",
alarm_flag: '',
cutoff: '',
};
tableData.value.push(newRow);
newresult({ ...newRow, ybh: labPat.value.ybh, jyrq: labPat.value.jyrq, yq: labPat.value.yq })
// 5. 自动聚焦
nextTick(() => {
selectedRows.value = [newRow];
tableRef.value.setCurrentRow(newRow);
tableRef.value.setScrollTo(tableData.value.length - 1)
// 聚焦到新行的输入框
const inputs = Array.from(document.querySelectorAll('.foucs-input .el-input__inner'))
.filter(el => el instanceof HTMLElement) as HTMLElement[];
if (inputs.length > 0) {
inputs[inputs.length - 1].focus();
}
});
};
const handleBatchDelete = () => {
if (selectedRows.value.length === 0) return ElMessage.warning("请先选择要删除的记录");
const arr = selectedRows.value.filter((row: any) => !row.id);
ElMessageBox.confirm(
`确定要删除选中的 ${selectedRows.value.length} 条记录吗?`,
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
).then(() => {
if (arr.length == 0) {
const index = tableData.value.findIndex((item: any) => item.xmdh === selectedRows.value[0].xmdh);
if (index > -1) tableData.value.splice(index, 1);
selectedRows.value = [];
} else {
deleteresult(arr).then((res: any) => {
if (res.code == 0) {
ElMessage.success('删除成功');
emits('fetchLabResults');
}
})
}
}).catch(() => {
});
};
const mbStore = useCommonStore();
const tableData: any = ref([])
watch(labResutsData, (newVal: any) => {
if (newVal.length) {
tableData.value = newVal.map((item: any) => {
return {
...item,
zhxmdh: item.xmdh + ' ' + item.xmmc,
}
})
rowHandle(newVal[0])
textarea.value = newVal[0]?.textresult
} else {
textarea.value = ''
rowInfo.value = {}
tableData.value = []
selectedRows.value = []
ymTableData.value = []
ymselectedRows.value = []
}
if (props.labPat.jgbz != null && props.labPat.jgbz != 0 && props.labPat.jgbz != 'C') return;
// console.log('mbStore==>', mbStore.lxsrs);
if (mbStore.lxsrs.length > 0) {
mbStore.lxsrs.forEach((mbmc) => {
const data = {
...labPatKey.value,
mbmc: mbmc,
}
setinputmdl(data).then((res: any) => {
if (res.code == 0) {
const existingNames = new Set(tableData.value.map((item: any) => item.xmdh))
res.data?.forEach((item: any) => {
if (!existingNames.has(item.xmdh)) {
tableData.value.push({ ...item, jyrq: labPat.value.jyrq, zhxmdh: item.xmdh + ' ' + item.xmmc })
existingNames.add(item.xmdh)
}
})
emitter.emit('clearLxsrList')
}
});
});
}
})
const handleTextareaEnter = () => {
if (!rowInfo.value.xmdh) return
savetestResult({ ...rowInfo.value, textresult: textarea.value }).then((res: any) => {
if (res.code == 0) {
ElMessage.success('保存成功');
}
});
};
const rowInfo: any = ref({})
const rowHandle = (row: any) => {
selectedRows.value = [row];
emitter.emitWithCache('refreshClinical', row);
rowInfo.value = row
const data = {
ybh: labPat.value.ybh,
yq: labPat.value.yq,
jyrq: labPat.value.jyrq,
xmdh: row.xmdh
}
getresultmedList(data).then((res: any) => {
if (res.code == 0) {
ymTableData.value = res.data.map((item: any) => {
return {
...item,
zhywdh: item.ywdh + ' ' + item.ywmc
}
})
}
})
}
// 项目结果保存
const handleCsjgEnter = async (row: any) => {
// 判断数据中包含模板新增的数据 flag
if (tableData.value.length == 0) return
const flag = tableData.value.some((item: any) => item.changeflag == 2)
if (flag) {
saveresult(tableData.value).then((res: any) => {
if (res.code == 0) {
emitter.emit('wswSaveResult');
}
})
} else {
if (!row) return
if (row && row.id) {
emitter.emit('wswSaveResult');
newresult({ ...row, ybh: labPat.value.ybh, jyrq: labPat.value.jyrq, yq: labPat.value.yq }).then((response: any) => {
ElMessage.success("结果保存成功");
emits('fetchLabResults');
}).catch((error: any) => {
emits('fetchLabResults');
});
} else {
changeresult(row).then((response: any) => {
ElMessage.success("结果保存成功");
emits('fetchLabResults');
}).catch((error: any) => {
emits('fetchLabResults');
});
}
// nextTick(() => {
// const input = document.activeElement;
// if (input?.tagName === "INPUT") input?.blur();
// });
}
};
const csjgRef = ref()
const csjgTableData = ref([])
const handleInputFocus = (row: any) => {
// dbRow.value = row
queryXmVal({ yq: labPatKey.value.yq, xmdh: row.xmdh }).then((res: any) => {
if (res.code == 0) {
csjgTableData.value = res.data
}
nextTick(() => {
csjgRef.value.open()
})
})
};
const selectItem = (row: any) => {
// 查找修改行
const index = tableData.value.findIndex((item: any) => item.xmdh == row.xmdh)
tableData.value[index].csjg = row.qz
handleCsjgEnter(tableData.value[index])
};
// 组合项目
const combinedRef = ref()
const zhHandel = () => {
combinedRef.value.open()
};
const combinedHandel = (row: any) => {
if (props.labPat.jgbz != null && props.labPat.jgbz != 0 && props.labPat.jgbz != 'C') return ElMessage.warning('已审核结果不可添加模板项目');
const data = {
...labPatKey.value,
mbmc: row.mbmc,
}
setinputmdl(data).then((res: any) => {
if (res.code == 0) {
const existingNames = new Set(tableData.value.map((item: any) => item.xmdh))
res.data?.forEach((item: any) => {
if (!existingNames.has(item.xmdh)) {
tableData.value.push({ ...item, jyrq: labPat.value.jyrq, zhxmdh: item.xmdh + ' ' + item.xmmc })
existingNames.add(item.xmdh)
}
})
handleCsjgEnter(null)
emitter.emit('clearLxsrList')
}
});
};
const ymTableRef = ref()
const ymTableData = ref<ymTableDataItem[]>([]);
const ymColumns = ref([
{ label: "抗生素", prop: "zhywdh", visible: true, width: 120, headerSlot: 'ywdhHead' },
{ label: "Mic", prop: "mic", align: 'center', visible: true, width: 60, slot: 'mic' },
{ label: "KB", prop: "rad", align: 'center', visible: true, width: 50, slot: 'rad' },
{ label: "结果", prop: "csjg", align: 'center', visible: true, width: 60, slot: 'csjg' },
{ label: "结果标志", prop: "jgbz", align: 'center', visible: true, slot: 'jgbz', width: 200, showOverflowTooltip: false },
{ label: "折点", prop: "ckz", align: 'center', visible: true, },
{ label: "分组", prop: "bz", align: 'center', visible: true, slot: 'bz' },
{ label: "专家值", prop: "txtresult", align: 'center', visible: true, slot: 'txtresult' },
{ label: "引用说明", prop: "cp_bz", align: 'center', visible: true, slot: 'cp_bz' },
])
const ymCellStyleHd = ({ row, column, rowIndex, columnIndex }: {
row: any;
column: any;
rowIndex: number;
columnIndex: number;
}) => {
if (column.label == "结果" && row.jgbz == "R") {
return { background: '#ffc0c0 !important', color: '#606266' };
}
if (column.label == "结果" && row.jgbz == "I") {
return { background: '#ffff80 !important', color: '#606266' };
}
}
const ymTableConfig = ref({
height: '48vh',
border: true,
highlightCurrentRow: true,
cellStyle: ymCellStyleHd,
});
const ymHandleColumnDragEnd = (data: any) => {
ymColumns.value = data.columns;
}
const ymselectedRows = ref<ymTableDataItem[]>([]);
const ymRowHandle = (row: any) => {
ymselectedRows.value = [row];
}
const medDictRef = ref()
const kssMbRef = ref()
const kssType = ref('')
// 更换抗生素组
const changeKss = () => {
kssMbRef.value.openDictSelector();
kssType.value = '1'
}
// 添加抗生素组
const addKss = () => {
kssMbRef.value.openDictSelector();
kssType.value = '2'
}
const kssSelect = (row: any) => {
getmedgroupMbList({ mbmc: row.value }).then((res: any) => {
if (res.code == 0) {
if (kssType.value == '1') {
ymTableData.value = []
res.data?.forEach((item: any, index: number) => {
ymTableData.value.push({ ...item, zhywdh: item.ywdh + ' ' + item.ywmc, xh: index + 1 })
})
} else {
const existingNames = new Set(ymTableData.value.map((item: any) => item.ywdh))
res.data?.forEach((item: any) => {
if (!existingNames.has(item.ywdh)) {
ymTableData.value.push({ ...item, zhywdh: item.ywdh + ' ' + item.ywmc, xh: ymTableData.value.length + 1 })
existingNames.add(item.ywdh)
}
})
}
ymTableData.value.forEach((item: any) => {
item.ybh = labPatKey.value.ybh
item.yq = labPatKey.value.yq
item.jyrq = labPat.value.jyrq
item.xmdh = selectedRows.value[0].xmdh
})
savemedresultall(ymTableData.value).then((res: any) => {
if (res.code == 0) {
rowHandle(selectedRows.value[0])
}
})
}
})
}
const addMed = () => {
medDictRef.value.openDictSelector();
}
const delMed = () => {
if (ymselectedRows.value.length === 0) return ElMessage.warning("请先选择要删除的记录");
const arr = ymselectedRows.value.filter((row: any) => !row.id);
if (arr.length) {
deletemedresult(ymselectedRows.value[0]).then((res: any) => {
if (res.code == 0) {
ElMessage.success('删除成功');
rowHandle(selectedRows.value[0])
}
})
} else {
const index = ymTableData.value.findIndex((item: any) => item.ywdh === ymselectedRows.value[0].ywdh);
if (index > -1) ymTableData.value.splice(index, 1);
}
ymselectedRows.value = [];
}
const medSelect = (row: any) => {
console.log('row==>', row);
const ymFlag = tableData.value.some((item: any) => item.ywdh === row.value);
if (ymFlag) return ElMessage.warning(`抗生素【${row.label}】已存在`);
// 1. 构造新增行数据
const newRow = {
id: `temp_${Date.now()}_${Math.random().toString(36).substr(2, 8)}`,
zhywdh: row.value + ' ' + row.label,
ywdh: row.value,
ywmc: row.label,
mic: '',
rad: '',
csjg: '',
jgbz: '',
ckz: '',
bz: '',
txtresult: '',
cp_bz: '',
xh: ymTableData.value.length + 1,
...labPatKey.value,
jyrq: labPat.value.jyrq,
xmdh: selectedRows.value[0].xmdh
};
ymTableData.value.push(newRow);
savemedresult(newRow)
nextTick(() => {
ymselectedRows.value = [newRow];
ymTableRef.value.setCurrentRow(newRow);
ymTableRef.value.setScrollTo(ymTableData.value.length - 1)
// 聚焦到新行的输入框
const inputs = Array.from(document.querySelectorAll('.ymFoucs .el-input__inner'))
.filter(el => el instanceof HTMLElement) as HTMLElement[];
if (inputs.length > 0) {
inputs[inputs.length - 1].focus();
}
});
};
// 药敏结果保存
const ymHandleEnter = async (row: any) => {
if (!row) return
savemedresult({ ...row, ybh: labPat.value.ybh, jyrq: labPat.value.jyrq, yq: labPat.value.yq, xmdh: selectedRows.value[0].xmdh }).then((res: any) => {
if (res.code == 0) {
ElMessage.success('保存成功');
rowHandle(selectedRows.value[0])
}
});
};
const jgbzHandle = (val: string, row: any) => {
const obj: any = {
R: '耐药',
I: '中介',
S: '敏感',
N: '非敏感',
D: '剂量依赖性敏感'
}
row.csjg = obj[val]
ymHandleEnter(row)
};
onMounted(() => {
// 获取模板项目
emitter.on('dbMbHandle', (info: any) => {
combinedHandel(info)
})
});
const formatDict = (v: string, dictType: string) => {
return props.dictData[dictType]?.find((item: any) => item.value == v)?.label || v;
}
const formatJgbz = (v: string) => {
return v == 'H' ? '高' : v == 'L' ? '低' : v == 'N' ? '阴性' : v == 'P' ? '阳性' : v == 'Q' ? '弱阳性' : v == 'M' ? '正常' : ''
}
</script>
<style scoped lang="scss">
.btns {
display: flex;
align-items: center;
span {
color: #1f6dd3;
margin-left: 15px;
}
}
.el-radio {
margin-right: .3125rem;
:deep(.el-radio__label) {
padding-left: 2px !important;
}
}
.tabs_btns {
position: relative;
.anchor {
position: absolute;
top: 0;
right: 0;
}
}
</style>

View File

@ -1,89 +1,33 @@
<template>
<!-- 遮罩层 -->
<div
v-if="visible"
class="dialog-mask"
@click="handleCancel"
></div>
<!-- 弹窗主体 -->
<div
v-if="visible"
class="dialog-container"
>
<div class="dialog-box">
<!-- 标题区域 -->
<div class="dialog-header">
<h3 class="dialog-title">{{ title }}</h3>
<button
class="dialog-close"
@click="handleCancel"
aria-label="关闭"
>
<span>×</span>
</button>
</div>
<!-- 内容区域 -->
<div class="dialog-body">
<!-- 工号输入 -->
<div class="form-item">
<label class="form-label">用户工号</label>
<input
type="text"
v-model.trim="userId"
class="form-input"
placeholder="请输入用户工号"
@keyup.enter="handleConfirm"
>
</div>
<!-- 密码输入 -->
<div class="form-item">
<label class="form-label">密码</label>
<input
type="password"
v-model="password"
class="form-input"
placeholder="请输入密码"
@keyup.enter="handleConfirm"
>
</div>
<!-- 错误提示 -->
<p v-if="errorMsg" class="error-message">{{ errorMsg }}</p>
</div>
<!-- 按钮区域 -->
<div class="dialog-footer">
<button
class="btn btn-cancel"
@click="handleCancel"
>
取消
</button>
<button
class="btn btn-confirm"
@click="handleConfirm"
:disabled="!userId || !password"
>
确认验证
</button>
</div>
<div>
<el-dialog v-model="checkShow" :title="title" width="500" :close-on-click-modal="false" :draggable="true"
@close="handleCancel">
<el-form ref="ruleFormRef" style="max-width: 600px" :model="ruleForm" :rules="rules" label-width="auto">
<el-form-item label="用户工号:" prop="yhdh">
<el-input ref="yhdhRef" v-model.trim="ruleForm.yhdh" placeholder="请输入用户工号" maxlength="20"
@keyup.enter="handleConfirm" />
</el-form-item>
<el-form-item label="密码:" prop="mm">
<el-input v-model.trim="ruleForm.mm" placeholder="请输入密码" type="mm" maxlength="20" show-password
@keyup.enter="handleConfirm" />
</el-form-item>
<el-form-item>
<div style="text-align: center; width: 100%;">
<el-button type="primary" @click="handleConfirm()"> 确认 </el-button>
<el-button @click="handleCancel">取消</el-button>
</div>
</el-form-item>
</el-form>
</el-dialog>
</div>
</template>
<script setup>
<script setup lang="ts">
import { set } from '@vueuse/core';
import { defineProps, defineEmits, ref, watch } from 'vue';
// 组件属性
const props = defineProps({
// 控制弹窗显示/隐藏
visible: {
type: Boolean,
default: false
},
// 弹窗标题(由外部参数控制)
title: {
type: String,
@ -103,221 +47,59 @@ const props = defineProps({
// 组件事件
const emit = defineEmits([
'update:visible', // 控制弹窗显示状态
'onConfirm', // 验证成功回调
'onCancel' // 取消验证回调
]);
// 表单数据
const userId = ref('');
const password = ref('');
const errorMsg = ref('');
const ruleForm = ref({
yhdh: '',
mm: '',
});
// 监听弹窗显示状态,重置表单
watch(
() => props.visible,
(newVal) => {
if (newVal) {
// 打开弹窗时重置表单
userId.value = '';
password.value = '';
errorMsg.value = '';
}
const rules = ref(
{
yhdh: [{ required: true, message: "请输入用户工号", trigger: "blur" },
{ min: 3, max: 20, message: "长度在 3 到 20 个字符", trigger: "blur" }
],
mm: [{ required: true, message: "请输入密码", trigger: "blur" },
{ min: 6, max: 20, message: "长度在 6 到 20 个字符", trigger: "blur" }
]
}
);
const yhdhRef = ref();
const open = () => {
checkShow.value = true;
nextTick(() => {
setTimeout(() => {
yhdhRef.value.focus();
}, 100);
});
};
const checkShow = ref(false);
const ruleFormRef = ref();
// 处理确认验证
const handleConfirm = () => {
// 基础验证
if (!userId.value) {
errorMsg.value = '请输入用户工号';
return;
ruleFormRef.value.validate((valid: boolean) => {
if (valid) {
emit('onConfirm', { yhdh: ruleForm.value.yhdh, mm: ruleForm.value.mm });
checkShow.value = false;
} else {
return false;
}
if (!password.value) {
errorMsg.value = '请输入密码';
return;
}
// 应用外部传入的验证规则
if (userId.value.length < props.validationRules.userIdMinLength) {
errorMsg.value = `工号长度不能少于${props.validationRules.userIdMinLength}位`;
return;
}
if (password.value.length < props.validationRules.passwordMinLength) {
errorMsg.value = `密码长度不能少于${props.validationRules.passwordMinLength}位`;
return;
}
// 验证通过,返回用户工号
emit('onConfirm', {
userId: userId.value,
password: password.value
});
// 关闭弹窗
emit('update:visible', false);
};
// 处理取消
const handleCancel = () => {
emit('onCancel');
emit('update:visible', false);
checkShow.value = false;
ruleForm.value.yhdh = '';
ruleForm.value.mm = '';
ruleFormRef.value.resetFields();
};
defineExpose({
open,
});
</script>
<style scoped>
/* 遮罩层 */
.dialog-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1000;
transition: opacity 0.3s;
}
/* 弹窗容器 */
.dialog-container {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1001;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
/* 弹窗主体 */
.dialog-box {
width: 100%;
max-width: 400px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
overflow: hidden;
}
/* 标题区域 */
.dialog-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 20px;
border-bottom: 1px solid #f0f0f0;
background-color: #f9fafb;
}
.dialog-title {
margin: 0;
font-size: 16px;
font-weight: 600;
color: #333;
}
.dialog-close {
padding: 0;
background: transparent;
border: none;
font-size: 20px;
color: #999;
cursor: pointer;
transition: color 0.2s;
}
.dialog-close:hover {
color: #333;
}
/* 内容区域 */
.dialog-body {
padding: 24px 20px;
}
.form-item {
margin-bottom: 16px;
}
.form-label {
display: block;
margin-bottom: 8px;
font-size: 14px;
color: #666;
}
.form-input {
width: 100%;
padding: 10px 12px;
border: 1px solid #dcdfe6;
border-radius: 4px;
font-size: 14px;
box-sizing: border-box;
transition: border-color 0.2s;
}
.form-input:focus {
outline: none;
border-color: #4096ff;
box-shadow: 0 0 0 2px rgba(64, 150, 255, 0.2);
}
.error-message {
margin: 8px 0 0;
color: #f56c6c;
font-size: 12px;
line-height: 1.5;
}
/* 按钮区域 */
.dialog-footer {
display: flex;
justify-content: flex-end;
padding: 12px 20px;
border-top: 1px solid #f0f0f0;
background-color: #f9fafb;
}
.btn {
padding: 8px 16px;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
transition: all 0.2s;
}
.btn-cancel {
margin-right: 10px;
border: 1px solid #dcdfe6;
background-color: #fff;
color: #606266;
}
.btn-cancel:hover {
background-color: #f5f7fa;
border-color: #c0c4cc;
}
.btn-confirm {
border: 1px solid #4096ff;
background-color: #4096ff;
color: #fff;
}
.btn-confirm:hover {
background-color: #66b1ff;
border-color: #66b1ff;
}
.btn-confirm:disabled {
opacity: 0.6;
cursor: not-allowed;
background-color: #4096ff;
border-color: #4096ff;
}
</style>
<style scoped lang="scss"></style>

View File

@ -194,9 +194,7 @@ defineExpose({
});
onMounted(() => {
for (let index = 0; index < 100; index++) {
tableData.value.push({ ybh: index, sqh: '321421321', brxm: '李是大', brdh: '4332132', jymd: '高蛋白大 大的 ' },);
}
});
</script>

View File

@ -7,7 +7,7 @@
<el-button class="btn_green" :size="aotuSize" v-if="labPat.jgbz == 2" @click="handleCheck(3)">取消审核</el-button>
<el-button type="primary" :size="aotuSize" plain :disabled="labPat.jgbz != null && labPat.jgbz != 0"
@click="openItemDictDialog">新增</el-button>
<el-button type="primary" :size="aotuSize" :disabled="labPat.jgbz != null && labPat.jgbz != 0" plain
<el-button type="danger" :size="aotuSize" :disabled="labPat.jgbz != null && labPat.jgbz != 0" plain
@click="handleBatchDelete">删除</el-button>
</div>
<div>
@ -76,82 +76,13 @@
<ProjectDetails ref="itemDictRef" :dialog-title="'选择检验项目'" :tableKey="tableKey" @select="handleItemSelect" />
<!-- 校验用户 -->
<el-dialog v-model="checkShow" title="用户身份验证" width="500" :close-on-click-modal="false" :draggable="true"
@close="resetForm">
<el-form ref="ruleFormRef" style="max-width: 600px" :model="ruleForm" :rules="rules" label-width="auto">
<el-form-item label="用户工号:" prop="yhdh">
<el-input v-model.trim="ruleForm.yhdh" placeholder="请输入用户工号" maxlength="20" @keyup.enter="submitForm" />
</el-form-item>
<el-form-item label="密码:" prop="mm">
<el-input v-model.trim="ruleForm.mm" placeholder="请输入密码" type="mm" maxlength="20" show-password
@keyup.enter="submitForm" />
</el-form-item>
<el-form-item>
<div style="text-align: center; width: 100%;">
<el-button type="primary" @click="submitForm()"> 确认 </el-button>
<el-button @click="resetForm">取消</el-button>
</div>
</el-form-item>
</el-form>
</el-dialog>
<CheckUser ref="checkUserRef" :title="checktitle" @onConfirm="handleCheckUserConfirm" />
<!-- 危急值结果上报 -->
<el-dialog v-model="showuploadwarning" title="危急值结果上报" width="500" :close-on-click-modal="false" :draggable="true"
@close="warningResetForm">
<div class="red-static-text">{{ warningMsgdata }}</div>
<el-form ref="warningFormRef" style="max-width: 600px" :model="warningForm" :rules="wrules" label-width="auto">
<el-form-item label="上报方式:" prop="uploadTp">
<el-radio-group v-model="warningForm.uploadTp" size="default">
<el-radio value="1">系统通知</el-radio>
<el-radio value="2">电话通知</el-radio>
</el-radio-group>
</el-form-item>
<template v-if="warningForm.uploadTp == 2">
<el-form-item label="电话通知人:" prop="userId">
<el-input v-model.trim="warningForm.userId" class="form-input" placeholder="请输入医生工号" @keyup.enter=" " />
</el-form-item>
<el-form-item label="联系电话:" prop="phone">
<el-input v-model="warningForm.phone" class="form-input" placeholder="请输入联系电话" @keyup.enter=" " />
</el-form-item>
</template>
<el-form-item>
<div style="text-align: center; width: 100%;">
<el-button type="primary" @click="handleWarningSuccess()"> 确认 </el-button>
<el-button @click="warningResetForm">取消</el-button>
</div>
</el-form-item>
</el-form>
</el-dialog>
<UploadWarning ref="uploadwarningRef" :warningMsgdata="warningMsgdata" :tableKey="tableKey"
@onupload="shHandleCheck" />
<!-- 操作原因 -->
<el-dialog v-model="unCheckshow" title="操作原因" width="500" :close-on-click-modal="false" :draggable="true"
@close="unconfirmlogCancel">
<div class="dialog-body mb10">
<p class="reason-text mb5">{{ reasonText }} </p>
<el-form ref="uncheckFormRef" style="max-width: 600px" :model="uncheckForm" :rules="rules" label-width="auto">
<template v-if="tableKey.problemId == 4">
<el-input type="textarea" v-model="uncheckForm.reason" class="reason-input" placeholder="请输入操作原因..."
:rows="4"></el-input>
</template>
<template v-if="tableKey.problemId == 6">
<el-form-item label="用户工号:" prop="yhdh">
<el-input v-model.trim="uncheckForm.yhdh" placeholder="请输入用户工号" maxlength="20"
@keyup.enter="submitForm" />
</el-form-item>
<el-form-item label="密码:" prop="mm">
<el-input v-model.trim="uncheckForm.mm" placeholder="请输入密码" type="mm" maxlength="20" show-password
@keyup.enter="submitForm" />
</el-form-item>
</template>
</el-form>
</div>
<Unconfirmlog ref="unconfirmlogRef" :reasonText="reasonText" :tableKey="tableKey" @onConfirm="unShHandle" />
<div style="text-align: center; width: 100%;">
<el-button type="primary" @click="unconfirmlogConfirm()"> 确认 </el-button>
<el-button @click="unconfirmlogCancel">取消</el-button>
</div>
</el-dialog>
<!-- 合并当前病人其他结果 -->
@ -261,7 +192,6 @@
</el-col>
</el-row>
</el-dialog>
</div>
</template>
@ -280,6 +210,9 @@ import { classCom } from '@/utils/classCom'
import CustomTable from '@/components/elTable/index.vue'
import dayjs from 'dayjs';
import emitter from "@/utils/mitt";
import CheckUser from "./CheckUser.vue";
import Unconfirmlog from './unconfirmlog.vue';
import UploadWarning from "./uploadwarning.vue";
import { useCommonStore } from "@/store/modules/commonStore";
import ContextMenu from "@/components/contextMenu/index.vue";
import ViewBackup from "./viewBackup.vue";
@ -335,6 +268,7 @@ watch(() => props.tableData, (newVal) => {
existingNames.add(item.xmdh)
}
})
emitter.emit('clearLxsrList')
}
});
});
@ -784,53 +718,12 @@ const beforeEnter = (row) => {
lastResult.value = res.data || {}
})
};
const warningForm = ref({
userId: '',
phone: '',
uploadTp: '1'
})
const uncheckForm = ref({
reason: '',
yhdh: '',
mm: '',
})
const wrules = ref({
userId: [{ required: true, message: "请输入用户工号", trigger: "blur" },
{ min: 3, max: 20, message: "长度在 3 到 20 个字符", trigger: "blur" }
],
phone: [{ required: true, message: "请输入联系电话", trigger: "blur" },
{ min: 6, max: 20, message: "长度在 6 到 20 个字符", trigger: "blur" }
]
})
const unCheckshow = ref(false);
const inputValue = ref('');
const reasonText = ref('');
const warningMsgdata = ref('');
const showuploadwarning = ref(false);
const checkuserid = ref()
const checkShow = ref(false);
const ruleForm = ref({
yhdh: '',
mm: ''
});
const rules = ref(
{
yhdh: [{ required: true, message: "请输入用户工号", trigger: "blur" },
{ min: 3, max: 20, message: "长度在 3 到 20 个字符", trigger: "blur" }
],
mm: [{ required: true, message: "请输入密码", trigger: "blur" },
{ min: 6, max: 20, message: "长度在 6 到 20 个字符", trigger: "blur" }
]
}
);
const checktitle = ref('');
const checkUserRef = ref();
const csjgRef = ref();
@ -838,9 +731,32 @@ const itemDictRef = ref(); // DictInput组件引用
const tableRef = ref();
const runnextstepname = ref(-1)
const handleCheck = (checkType) => {
// yhdh = checkuserid.value
runnextstepname.value = checkType
tableKey.value.problemId = 0;
// tableKey.value.yhdh = checkuserid.value
if (!tableKey.value.yhdh) {
checktitle.value = '审核人工号密码验证'
checkUserRef.value.open()
} else {
proceedCheck(checkType)
}
};
const handleCheckUserConfirm = (info) => {
checkuser({ yhdh: info.yhdh, mm: info.mm }).then(response => {
if (response.code == 0) {
emits('update:tableKey', {
...tableKey.value,
yhdh: info.yhdh
});
proceedCheck(runnextstepname.value)
}
})
}
const proceedCheck = (checkType) => {
switch (checkType) {
case 1: // 初审
check1({ ...tableKey.value, yhdh: props.labPat.yhdh }).then(res => {
@ -858,90 +774,34 @@ const handleCheck = (checkType) => {
default:
break;
}
};
}
const uploadwarningRef = ref();
const shHandleCheck = () => {
check2({ ...props.tableKey, yhdh: props.labPat.yhdh }).then(res => {
emits("changeStatus", props.labPat);
if (res.code == "4" && res.problemId === 4) {
tableKey.value.problemId = res.problemId;
warningMsgdata.value = res.msg;
showuploadwarning.value = true;
uploadwarningRef.value.open();
}
})
};
const warningFormRef = ref(null);
const warningResetForm = () => {
warningForm.value.userId = '';
warningForm.value.phone = '';
warningForm.value.uploadTp = '1';
warningFormRef.value.resetFields();
showuploadwarning.value = false;
};
// 处理危急值登记
const handleWarningSuccess = async () => {
if (warningForm.value.uploadTp == 2) {
const valid = await warningFormRef.value.validate().catch(() => { });
if (!valid) return false;
}
reglimit({ ...tableKey.value, qrr: warningForm.value.userId, tzfs: warningForm.value.uploadTp, phone: warningForm.value.phone }).then(response => {
showuploadwarning.value = false;
if (response.code == 0) {
shHandleCheck();
}
if (response.code == 4) {
ElMessageBox.confirm(response.msg, '系统提示', { confirmButtonText: '是', cancelButtonText: '否', type: 'warning' }).then(() => {
tableKey.value.problemId = tableKey.value.problemId + 1;
handleWarningSuccess();
}).catch(() => {
shHandleCheck();
});
}
})
};
const unconfirmlogRef = ref();
const unShHandle = () => {
uncheck2({ ...tableKey.value, yhdh: props.labPat.yhdh }).then(res => {
console.log('res',res);
if (res.code == "4") {
tableKey.value.problemId = res.problemId;
reasonText.value = res.msg;
unCheckshow.value = true;
unconfirmlogRef.value.open();
}
emits("changeStatus", props.labPat);
})
};
const uncheckFormRef = ref();
// 取消审核原因
const unconfirmlogConfirm = async () => {
if (tableKey.value.problemId == 4) {
if (!uncheckForm.value.inputValue) return ElMessage.warning("请输入操作原因")
} else if (tableKey.value.problemId == 6) {
const valid = await uncheckFormRef.value.validate().catch(() => { });
if (!valid) return false;
}
unconfirmlog({ ...tableKey.value, ...uncheckForm.value }).then(response => {
if (response.code == "0") {
unCheckshow.value = false;
unShHandle();
}
})
};
const unconfirmlogCancel = () => {
unCheckshow.value = false;
uncheckForm.value.reason = '';
uncheckForm.value.yhdh = '';
uncheckForm.value.mm = '';
uncheckFormRef.value.resetFields();
}
const ruleFormRef = ref(null);
@ -963,12 +823,7 @@ const submitForm = () => {
}
const resetForm = () => {
checkShow.value = false;
ruleForm.value.userId = '';
ruleForm.value.mm = '';
ruleFormRef.value.resetFields();
};
// 2. 打开项目选择弹窗
const openItemDictDialog = () => {
itemDictRef.value.openDictSelector();
@ -1022,7 +877,8 @@ const addRowFromDict = async (rowData) => {
const emits = defineEmits([
'fetchLabResults',
'changeStatus',
'previewHandle'
'previewHandle',
'update:tableKey'
]);
const csjgTableData = ref([]);
@ -1211,6 +1067,7 @@ onMounted(() => {
}
})
handleCsjgEnter(null)
emitter.emit('clearLxsrList')
}
});
})

View File

@ -1,186 +1,113 @@
<template>
<!-- 遮罩层 -->
<div
v-if="visible"
class="dialog-mask"
@click="handleMaskClick"
></div>
<!-- 弹窗主体 -->
<div
v-if="visible"
class="dialog-wrapper"
>
<div class="dialog-container">
<!-- 标题 -->
<div class="dialog-header">
<h3>操作原因</h3>
<button class="close-btn" @click="handleCancel">×</button>
<div>
<el-dialog v-model="unCheckshow" title="操作原因" width="500" :close-on-click-modal="false" :draggable="true"
@close="unconfirmlogCancel">
<div class="dialog-body mb10">
<p class="reason-text mb5">{{ reasonText }} </p>
<el-form ref="uncheckFormRef" style="max-width: 600px" :model="uncheckForm" :rules="rules" label-width="auto">
<template v-if="tableKey.problemId == 4">
<el-input type="textarea" v-model="uncheckForm.reason" class="reason-input" placeholder="请输入操作原因..."
:rows="4"></el-input>
</template>
<template v-if="tableKey.problemId == 6">
<el-form-item label="用户工号:" prop="yhdh">
<el-input v-model.trim="uncheckForm.yhdh" placeholder="请输入用户工号" maxlength="20"
@keyup.enter="unconfirmlogConfirm" />
</el-form-item>
<el-form-item label="密码:" prop="mm">
<el-input v-model.trim="uncheckForm.mm" placeholder="请输入密码" type="mm" maxlength="20" show-password
@keyup.enter="unconfirmlogConfirm" />
</el-form-item>
</template>
</el-form>
</div>
<!-- 内容区 -->
<div class="dialog-body">
<p class="reason-text">{{ reasonText }}</p>
<textarea
v-model="inputValue"
class="reason-input"
placeholder="请输入操作原因..."
rows="4"
></textarea>
<div style="text-align: center; width: 100%;">
<el-button type="primary" @click="unconfirmlogConfirm()"> 确认 </el-button>
<el-button @click="unconfirmlogCancel">取消</el-button>
</div>
</el-dialog>
<!-- 按钮区 -->
<div class="dialog-footer">
<button class="btn cancel" @click="handleCancel">取消</button>
<button class="btn confirm" @click="handleConfirm">确认</button>
</div>
</div>
</div>
</template>
<script setup>
import { defineProps, defineEmits, ref } from 'vue';
<script setup lang="ts">
import { ElMessage } from 'element-plus';
import { unconfirmlog } from "@/api/liswork/work/LisWork";
// 组件属性
const props = defineProps({
visible: {
type: Boolean,
default: false
},
reasonText: {
type: String,
default: '请填写操作原因'
},
tableKey: {
type: Object,
required: true
}
});
const { tableKey } = toRefs(props);
// 组件事件
const emit = defineEmits(['update:visible', 'onConfirm', 'onCancel']);
const emit = defineEmits(['onConfirm']);
const uncheckForm = ref({
reason: '',
yhdh: '',
mm: '',
})
const rules = ref({
yhdh: [{ required: true, message: "请输入用户工号", trigger: "blur" },
{ min: 3, max: 20, message: "长度在 3 到 20 个字符", trigger: "blur" }
],
mm: [{ required: true, message: "请输入联系电话", trigger: "blur" },
{ min: 6, max: 20, message: "长度在 6 到 20 个字符", trigger: "blur" }
]
})
// 输入框内容
const inputValue = ref('');
// 确认按钮点击
const handleConfirm = () => {
emit('onConfirm', inputValue.value); // 传递输入值
emit('update:visible', false);
inputValue.value = ''; // 重置输入
const unCheckshow = ref(false);
const open = () => {
unCheckshow.value = true;
};
// 取消按钮点击
const handleCancel = () => {
emit('onCancel');
emit('update:visible', false);
inputValue.value = ''; // 重置输入
const uncheckFormRef = ref();
// 取消审核原因
const unconfirmlogConfirm = async () => {
if (tableKey.value.problemId == 4) {
if (!uncheckForm.value.reason) return ElMessage.warning("请输入操作原因")
} else if (tableKey.value.problemId == 6) {
const valid = await uncheckFormRef.value.validate().catch(() => { });
if (!valid) return false;
}
unconfirmlog({ ...tableKey.value, ...uncheckForm.value }).then((response: any) => {
if (response.code == "0") {
emit('onConfirm');
unCheckshow.value = false;
}
})
};
// 遮罩层点击
const handleMaskClick = () => {
handleCancel();
};
const unconfirmlogCancel = () => {
unCheckshow.value = false;
uncheckForm.value.reason = '';
uncheckForm.value.yhdh = '';
uncheckForm.value.mm = '';
uncheckFormRef.value.resetFields();
}
defineExpose({
open,
});
</script>
<style scoped>
/* 基础样式与之前保持一致,确保按钮边框和输入框正常 */
.dialog-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 1000;
}
.dialog-wrapper {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1001;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.dialog-container {
width: 100%;
max-width: 500px;
background: #fff;
border: 1px solid #ddd;
border-radius: 8px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}
.dialog-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 20px;
border-bottom: 1px solid #eee;
}
.dialog-header h3 {
margin: 0;
font-size: 16px;
color: #333;
}
.close-btn {
background: none;
border: none;
font-size: 20px;
color: #999;
cursor: pointer;
}
.dialog-body {
padding: 20px;
}
.reason-text {
margin: 0 0 15px 0;
color: #666;
}
.reason-input {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
resize: vertical;
box-sizing: border-box;
}
.reason-input:focus {
outline: none;
border-color: #4096ff;
}
.dialog-footer {
padding: 15px 20px;
border-top: 1px solid #eee;
text-align: right;
}
.btn {
padding: 6px 16px;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
}
.cancel {
margin-right: 10px;
border: 1px solid #ddd;
background: #fff;
color: #666;
}
.confirm {
border: 1px solid #4096ff;
background: #4096ff;
color: #fff;
}
</style>
<style scoped></style>

View File

@ -1,179 +1,113 @@
<template>
<!-- 遮罩层 -->
<div
v-if="visible"
class="dialog-mask"
@click="handleCancel"
></div>
<!-- 弹窗主体 -->
<div
v-if="visible"
class="dialog-container"
>
<div class="dialog-box">
<!-- 标题区域 -->
<div class="dialog-header">
<h3 class="dialog-title">危急值结果上报</h3>
<button
class="dialog-close"
@click="handleCancel"
aria-label="关闭"
>
<span>×</span>
</button>
</div>
<!-- 内容区域 -->
<div class="dialog-body">
<div class="red-static-text">{{ msgdata }}</div>
<el-col :span="1">
<el-form-item label="上报方式" prop="uploadTp">
<el-radio-group v-model="uploadTp" size="default">
<el-radio v-for="(item, index) in uploadtypeptions" :key="index" :label="item.value"
:disabled="item.disabled">{{item.label}}</el-radio>
<div>
<el-dialog v-model="showuploadwarning" title="危急值结果上报" width="500" :close-on-click-modal="false" :draggable="true"
@close="warningResetForm">
<div class="red-static-text">{{ warningMsgdata }}</div>
<el-form ref="warningFormRef" style="max-width: 600px" :model="warningForm" :rules="wrules" label-width="auto">
<el-form-item label="上报方式:" prop="uploadTp">
<el-radio-group v-model="warningForm.uploadTp" size="default">
<el-radio value="1">系统通知</el-radio>
<el-radio value="2">电话通知</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<div class="form-item" v-if="uploadTp === 2">
<label class="form-label">电话通知人</label>
<input
type="text"
v-model.trim="userId"
class="form-input"
placeholder="请输入医生工号"
@keyup.enter="handleupload"
>
</div>
<div class="form-item" v-if="uploadTp === 2">
<label class="form-label">联系电话</label>
<input
type="text"
v-model="phone"
class="form-input"
placeholder="请输入联系电话"
@keyup.enter="handleupload"
>
</div>
<template v-if="warningForm.uploadTp == '2'">
<el-form-item label="电话通知人:" prop="userId">
<el-input v-model.trim="warningForm.userId" class="form-input" placeholder="请输入医生工号" @keyup.enter=" " />
</el-form-item>
<el-form-item label="联系电话:" prop="phone">
<el-input v-model="warningForm.phone" class="form-input" placeholder="请输入联系电话" @keyup.enter=" " />
</el-form-item>
</template>
<!-- 错误提示 -->
<p v-if="errorMsg" class="error-message">{{ errorMsg }}</p>
<el-form-item>
<div style="text-align: center; width: 100%;">
<el-button type="primary" @click="handleWarningSuccess()"> 确认 </el-button>
<el-button @click="warningResetForm">取消</el-button>
</div>
</el-form-item>
</el-form>
</el-dialog>
<!-- 按钮区域 -->
<div class="dialog-footer">
<button
class="btn btn-cancel"
@click="handleCancel"
>
取消
</button>
<button
class="btn btn-upload"
@click="handleupload"
:disabled="isSubmitDisabled"
>
确认上报
</button>
</div>
</div>
</div>
</template>
<script setup>
import { defineProps, defineEmits, ref, watch } from 'vue';
const uploadtypeptions = ref([{
"label": "系统通知",
"value": 1
}, {
"label": "电话通知",
"value": 2
}])
<script setup lang="ts">
import { reglimit } from "@/api/liswork/work/LisWork";
import { ElMessageBox } from "element-plus";
// 组件属性
const props = defineProps({
// 控制弹窗显示/隐藏
visible: {
type: Boolean,
default: false
tableKey: {
type: Object,
required: true
},
// 弹窗内容
msgdata: {
warningMsgdata: {
type: String,
default: ''
},
// 显示规则
showRules: {
type: Number,
default:1
}
});
const { tableKey, warningMsgdata } = toRefs(props);
// 组件事件
const emit = defineEmits([
'update:visible', // 控制弹窗显示状态
'onupload', // 验证成功回调
'onCancel' // 取消验证回调
]);
const emits = defineEmits(['onupload',]);
const showuploadwarning = ref(false);
// 表单数据
const uploadTp = ref('1');
const userId = ref('');
const phone = ref('');
const errorMsg = ref('');
// 监听弹窗显示状态,重置表单
watch(
() => props.visible,
(newVal) => {
if (newVal) {
// 打开弹窗时重置表单
uploadTp.value = 1; // 打开弹窗时默认选中1
userId.value = '';
phone.value = '';
errorMsg.value = '';
const warningForm = ref({
userId: '',
phone: '',
uploadTp: '1'
})
const wrules = ref({
userId: [{ required: true, message: "请输入用户工号", trigger: "blur" },
{ min: 3, max: 20, message: "长度在 3 到 20 个字符", trigger: "blur" }
],
phone: [{ required: true, message: "请输入联系电话", trigger: "blur" },
{ min: 6, max: 20, message: "长度在 6 到 20 个字符", trigger: "blur" }
]
})
const open = () => {
showuploadwarning.value = true;
}
const warningFormRef = ref();
const warningResetForm = () => {
warningForm.value.userId = '';
warningForm.value.phone = '';
warningForm.value.uploadTp = '1';
warningFormRef.value.resetFields();
showuploadwarning.value = false;
};
// 处理危急值登记
const handleWarningSuccess = async () => {
if (warningForm.value.uploadTp == '2') {
const valid = await warningFormRef.value.validate().catch(() => { });
if (!valid) return false;
}
reglimit({ ...tableKey.value, qrr: warningForm.value.userId, tzfs: warningForm.value.uploadTp, phone: warningForm.value.phone }).then((response: any) => {
showuploadwarning.value = false;
if (response.code == 0) {
emits('onupload');
}
);
const isSubmitDisabled = computed(() => {
// 系统通知(1):无需其他字段,直接可提交
if (uploadTp.value === 1) {
return false;
}
// 电话通知(2):需填写通知人和电话
return !userId.value || !phone.value;
});
// 处理确认验证
const handleupload = () => {
errorMsg.value = ''; // 清空之前的错误提示
// 基础验证
if(uploadTp.value===2) {
if (!userId.value) {
errorMsg.value = '请输入用户工号';
return;
}
if(props.showRules===3) {
if (!phone.value) {
errorMsg.value = '请输入电话';
return;
}
}
}
// 验证通过,返回用户工号
emit('onupload', {
userId: userId.value,
phone: phone.value,
uploadTp:uploadTp.value
if (response.code == 4) {
ElMessageBox.confirm(response.msg, '系统提示', { confirmButtonText: '是', cancelButtonText: '否', type: 'warning' }).then(() => {
tableKey.value.problemId = tableKey.value.problemId + 1;
handleWarningSuccess();
}).catch(() => {
emits('onupload');
});
// 关闭弹窗
emit('update:visible', false);
}
})
};
// 处理取消
const handleCancel = () => {
emit('onCancel');
emit('update:visible', false);
};
defineExpose({
open
});
</script>
<style scoped>
@ -329,10 +263,14 @@ const handleCancel = () => {
background-color: #4096ff;
border-color: #4096ff;
}
.red-static-text {
color: red; /* 字体颜色设为红色 */
white-space: pre-wrap; /* 保留空格和换行(可选,配合 pre 标签或手动换行时使用) */
line-height: 1.6; /* 行高,增强多行可读性 */
color: red;
/* 字体颜色设为红色 */
white-space: pre-wrap;
/* 保留空格和换行(可选,配合 pre 标签或手动换行时使用) */
line-height: 1.6;
/* 行高,增强多行可读性 */
/* 可选:添加其他样式 */
font-size: 14px;
margin: 10px 0;

View File

@ -7,9 +7,21 @@
class="compact-form">
<el-row :gutter="5">
<el-col :span="6">
<el-form-item label="样本号:" prop="ybh">
<el-form-item label="" prop="ybh">
<div class="next_box">
<div class="jtIcon" @click="handlePrev">
<el-icon>
<ArrowUpBold />
</el-icon>
</div>
<el-input v-model="queryParams.ybh" placeholder="样本编号" @keyup.enter="handleQuery"
style="width:100%" />
<div class="jtIcon" @click="handleNext">
<el-icon>
<ArrowDownBold />
</el-icon>
</div>
</div>
</el-form-item>
</el-col>
<el-col :span="6">
@ -52,8 +64,9 @@
</el-col>
<el-col :span="16">
<LabResult ref="labResultRef" :labPat="labPat" :tableData="labResuts" :tableKey="queryParams"
:userList="userList" :resultSysList="resultConfig" @fetchLabResults="resultsHandle" :dictData="dictData"
@changeStatus="changeStatus" @previewHandle="previewHandle" />
@update:tableKey="queryParams = $event" :userList="userList" :resultSysList="resultConfig"
@fetchLabResults="resultsHandle" :dictData="dictData" @changeStatus="changeStatus"
@previewHandle="previewHandle" />
</el-col>
</el-row>
</div>
@ -123,14 +136,14 @@ import { comDict } from '@/utils/dict'
import { queryLabPatList, queryLabResults, loadDefault, queryLabPat, instrdconfig, delSample, getGroupInstrdList } from "@/api/liswork/work/LisWork";
import { getComDicts, queryComDictListService } from "@/api/liswork/dict/ComDict";
import { ElMessage, ElMessageBox } from "element-plus";
import History from './history/index.vue'
import Others from './others/index.vue'
import Reexamination from './reexamination/index.vue'
import Charge from './charge/index.vue'
import Combination from './combination/index.vue'
import Clinical from './clinical/index.vue'
import Sample from './sample/index.vue'
import ResultGraph from './resultGraph/index.vue'
import History from '../components/history/index.vue'
import Others from '../components/others/index.vue'
import Reexamination from '../components/reexamination/index.vue'
import Charge from '../components/charge/index.vue'
import Combination from '../components/combination/index.vue'
import Clinical from '../components/clinical/index.vue'
import Sample from '../components/sample/index.vue'
import ResultGraph from '../components/resultGraph/index.vue'
import { getNextNumber, getPreviousNumber } from "@/utils/getNextNumber";
import { useCommonStore } from '@/store/modules/commonStore';
import { classCom } from '@/utils/classCom';
@ -140,6 +153,7 @@ import BatchCode from './components/batchCode.vue';
import { listUser } from '@/api/system/user.js'
const aotuSize = classCom.useAutoSize();
import { initWebSocket, sendWebSocketMessage, closeWebSocket, getWebSocketState } from '@/utils/webSocket';
const previewShow = ref(false);
const lbFlag = ref(false);
@ -149,7 +163,8 @@ const queryParams = ref({
ybh: '1',
instrGroup: '02',
problemId: 0,
days: 1,
days: 0,
yhdh: ''
})
const ybs = ref(0)
const ws = ref(0)
@ -644,7 +659,45 @@ onMounted(async () => {
HOS: toRaw(dictRefs.HOS.value) || [],
ST: toRaw(dictRefs.ST.value) || [],
};
// 初始化Socket
initSocket()
});
const initSocket = () => {
initWebSocket({
fullUrl: `ws://47.97.125.165:8904/ws/instr/${mbStore.fingerprint}`,
onOpen: () => {
console.log('WebSocket连接成功');
},
onMessage: (data) => {
console.log(`收到消息: `, JSON.parse(data));
},
onError: (error) => {
console.log(`连接错误: ${error.type}`);
},
onClose: () => {
console.log('WebSocket连接已关闭');
},
reconnectInterval: 3000 // 重连间隔(毫秒)
});
}
// 页面卸载时清理
onUnmounted(() => {
closeWebSocket();
});
// 发送消息
const sendMessage = () => {
const isSuccess = sendWebSocketMessage({ yq: queryParams.value.yq });
if (isSuccess) {
console.log(`发送消息`);
} else {
console.log('发送失败:连接未建立');
}
};
</script>
<style scoped lang="scss">

View File

@ -0,0 +1,210 @@
<template>
<!-- 修改界面 -->
<el-dialog v-model="visible" width="600px" @open="open">
<template #header>
{{ title }}
</template>
<span class="text-span">项目信息:</span>
<el-divider style="margin: 5px 0;"/>
<el-form ref="form" :model="formData" size="small" class="form-inline" inline label-width="70px">
<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-item label="助记符" prop="zjf">
<el-input placeholder="助记符" v-model="formData.zjf"></el-input>
</el-form-item>
<el-form-item label="项目类别" prop="xmlb">
<el-input placeholder="项目类别" v-model="formData.xmlb"></el-input>
</el-form-item>
<el-form-item label="所属组" prop="xmz">
<el-input placeholder="所属组" v-model="formData.xmz"></el-input>
</el-form-item>
<el-form-item label="单位" prop="dw">
<el-input placeholder="单位" v-model="formData.dw"></el-input>
</el-form-item>
<el-form-item label="参考上限" prop="cksx">
<el-input placeholder="参考上限" v-model="formData.cksx"></el-input>
</el-form-item>
<el-form-item label="参考下限" prop="ckxx">
<el-input placeholder="参考下限" v-model="formData.ckxx"></el-input>
</el-form-item>
<el-form-item label="打印参考值" prop="dyckz">
<el-input placeholder="打印参考值" v-model="formData.dyckz"></el-input>
</el-form-item>
<el-form-item label="打印序号" prop="dyxh">
<el-input placeholder="打印序号" v-model="formData.dyxh"></el-input>
</el-form-item>
<el-form-item label="计算公式" prop="jsgs">
<el-input placeholder="计算公式" v-model="formData.jsgs"></el-input>
</el-form-item>
<el-form-item label="临床意义" prop="lcyy">
<el-input placeholder="临床意义" v-model="formData.lcyy"></el-input>
</el-form-item>
<el-form-item label="备注" prop="bz">
<el-input placeholder="备注" v-model="formData.bz"></el-input>
</el-form-item>
<el-form-item prop="xsbz">
<el-checkbox v-model="xsbzCheck" label="显示标志"></el-checkbox>
</el-form-item>
</el-form>
<span class="text-span">知识库条目:</span>
<el-divider style="margin: 5px 0;"/>
<CustomTable ref="tableRefRight" :data="dataList" :columns="columnsRight" :enable-column-drag="true" @column-drag-end="handleColumnDragEnd"
:config="tableConfig" :show-overflow-tooltip="true">
<template #reserve="{row}">
{{ reserve(row.reserve) }}
</template>
<template #textresult="{row}">
<el-input v-model="row.textresult" type="textarea" class="full-width-input"></el-input>
</template>
<template #zd="{row}">
<el-input v-model="row.zd" type="textarea" class="full-width-input"></el-input>
</template>
</CustomTable>
<template #footer>
<div class="dialog-footer">
<el-button @click="handleCancel">取 消</el-button>
<el-button type="primary" @click="handleOk">确 定</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import { addService } from '@/api/liswork/xmKnowledge/xmKnowledgeApi'
import { ElMessage } from 'element-plus'
const props = defineProps({
title:{
type: String,
default: ''
},
type: {
type: String,
default: ''
}
})
const visible = defineModel()
const emit = defineEmits(['closeWithReturn'])
const formData = ref({
xmdh: '',
xmmc: '',
zjf: '',
xmlb: '' ,
xmz: '',
dw: '',
cksx: '',
ckxx: '',
dyckz: '',
dyxh: '',
jsgs: '',
lcyy: '',
bz:'',
xsbz: ''
})
const columnsRight = ref([
{ prop: 'reserve', label: '类别', visible: true, align: 'center',slot: 'reserve', width: 50 ,showOverflowTooltip: false},
{ prop: 'textresult', label: '说明', visible: true, align: 'center',slot: 'textresult', width: 300,showOverflowTooltip: false},
{ prop: 'zd', label: '指导建议', visible: true, align: 'center',slot: 'zd', width: 200,showOverflowTooltip: false },
])
const tableConfig = ref({
border: true, // 边框
height: '40vh', // 高度
highlightCurrentRow: true, // 高亮当前行
// cellStyle: cellStyleHd
})
const xsbzCheck = computed({
get() {
return formData.value.xsbz === '1'
},
set(checked){
formData.value.xsbz = checked ? '1' : '0';
}
})
//退拽属性
const handleColumnDragEnd = (data: any) => {
// 更新列配置
columnsRight.value = data.columns;
}
const dataList = ref<any>([])
const reserve = (reserve:string) => {
switch(reserve){
case '1':
return '综述'
case 'H':
return '偏高'
case 'L':
return '偏低'
case 'P':
return '阳性'
case 'Q':
return '弱阳性'
case 'J':
return '危机'
case 'N':
return '阴性'
}
}
const handleCancel = () => {
visible.value = false
}
const handleOk = async () => {
//保存数据
console.log(formData.value)
await addService(formData.value);
ElMessage.success('保存成功!')
visible.value = false
}
const open = () => {
if(props.type === '新增'){
dataList.value = [
{reserve:'1',textresult:'',yxjs:'',cjyy:'',zd:''},
{reserve:'H',textresult:'',yxjs:'',cjyy:'',zd:''},
{reserve:'L',textresult:'',yxjs:'',cjyy:'',zd:''},
{reserve:'P',textresult:'',yxjs:'',cjyy:'',zd:''},
{reserve:'Q',textresult:'',yxjs:'',cjyy:'',zd:''},
{reserve:'J',textresult:'',yxjs:'',cjyy:'',zd:''},
{reserve:'N',textresult:'',yxjs:'',cjyy:'',zd:''},
]
}else{
}
}
</script>
<style scoped lang="scss">
.form-inline {
padding: 10px;
background-color: #f5f7fa;
height: auto;
.el-input {
width: 150px;
}
.el-form-item {
margin-right: 10px;
margin-bottom: 2px;
}
}
</style>

View File

@ -0,0 +1,76 @@
<template>
<CustomTable ref="tableRefRight" :data="dataList" :columns="columnsRight" :enable-column-drag="true" @column-drag-end="handleColumnDragEnd"
:config="tableConfig">
<template #reserve="{row}">
{{ reserve(row.reserve) }}
</template>
</CustomTable>
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
const props = defineProps({
dataList:{
type: Array,
required: false,
default: []
},
styleConfig: {
type: Object,
required: false,
default: {
reserveWidth: 50,
textresultWidth: 200,
zdWidth: 100,
tableHeight: '85vh'
}
}
})
//const dataListRight = ref([]);
const columnsRight = ref([
{ prop: 'reserve', label: '类别', visible: true, align: 'center',slot: 'reserve', width: props.styleConfig.reserveWidth },
{ prop: 'textresult', label: '说明', visible: true, align: 'center', width: props.styleConfig.textresultWidth ,showOverflowTooltip: false},
{ prop: 'zd', label: '指导建议', visible: true, align: 'center', width: props.styleConfig.zdWidth,showOverflowTooltip: false },
])
const tableConfig = ref({
border: true, // 边框
height: props.styleConfig.tableHeight, // 高度
highlightCurrentRow: true, // 高亮当前行
// cellStyle: cellStyleHd
})
//退拽属性
const handleColumnDragEnd = (data: any) => {
// 更新列配置
columnsRight.value = data.columns;
}
const reserve = (reserve:string) => {
switch(reserve){
case '1':
return '综述'
case 'H':
return '偏高'
case 'L':
return '偏低'
case 'P':
return '阳性'
case 'Q':
return '弱阳性'
case 'J':
return '危机'
case 'N':
return '阴性'
}
}
</script>
<style scoped lang="scss">
</style>

View File

@ -0,0 +1,163 @@
<template>
<div class="topForm">
<el-form ref="formRef" :model="formData" inline label-width="80px" class="mb8" @submit.prevent="handleSubmit">
<el-form-item label="检索" prop="js">
<el-input placeholder="项目代号,名称,简拼" v-model="formData.js" style="width: 200px;" @keyup.enter="getList"></el-input>
</el-form-item>
</el-form>
</div>
<el-row>
<el-button type="primary" @click="onQueryClick">查询</el-button>
<el-button type="primary" @click="onAddClick">新增</el-button>
<el-button type="primary" @click="onDelClick">删除</el-button>
</el-row>
<el-row>
<el-col :span="17">
<CustomTable ref="tableRefLeft" :data="dataListLeft" :columns="columnsLeft" :enable-column-drag="true" @column-drag-end="handleColumnDragEnd"
:config="tableConfig" @row-dblclick="onDBClick" @row-click="onClick" :pagination="pagination" @size-change="sizeChange" @page-change="currentChange">
<template #xsbz="{row}">
<el-checkbox :model-value="row.xsbz === '1'"/>
</template>
</CustomTable>
</el-col>
<el-col :span="7">
<TableRight :data-list="dataListRight"/>
</el-col>
</el-row>
<Modify ref="modifyRef" v-model="modifyVisible" :title="modifyTitle" :type="modifyType" @close-with-return="closeWithReturn"/>
</template>
<script setup lang="ts">
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'
import { ElMessage,ElMessageBox } from 'element-plus';
const dataListLeft = ref([]);
const dataListRight = ref([]);
const columnsLeft = ref([
{ prop: 'xmid', label: '知识库ID', visible: true, align: 'center', width: 100 },
{ prop: 'xmdh', label: '项目代号', visible: true, align: 'center', width: 100 },
{ prop: 'xmmc', label: '项目名称', visible: true, align: 'center', width: 200 },
{ prop: 'xsbz', label: '显示标志', visible: true, align: 'center', slot: 'xsbz', width: 100 },
{ prop: 'xmlb', label: '类别', visible: true, align: 'center', width: 100 },
{ prop: 'xmz', label: '所属组', visible: true, align: 'center', width: 100 },
{ prop: 'dw', label: '单位', visible: true, align: 'center', width: 100 },
{ prop: 'cksx', label: '参考上限', visible: true, align: 'center', width: 100 },
{ prop: 'ckxx', label: '参考下限', visible: true, align: 'center', width: 100 },
{ prop: 'dyckz', label: '打印参考值', visible: true, align: 'center', width: 100 },
{ prop: 'dyxh', label: '打印序号', visible: true, align: 'center', width: 100 },
{ prop: 'jsgs', label: '计算公式', visible: true, align: 'center', width: 100 },
{ prop: 'lcyy', label: '临床意义', visible: true, align: 'center', width: 100 },
{ prop: 'zjf', label: '助记符', visible: true, align: 'center', width: 100 },
{ prop: 'bz', label: '备注', visible: true, align: 'center', width: 100 },
]);
const tableConfig = ref({
border: true, // 边框
height: '85vh', // 高度
highlightCurrentRow: true, // 高亮当前行
// cellStyle: cellStyleHd
})
const modifyVisible = ref(false)
const modifyTitle = ref('')
const modifyType = ref('')
const modifyRef = ref()
const selectRow = ref()
//退拽属性
const handleColumnDragEnd = (data: any) => {
// 更新列配置
columnsLeft.value = data.columns;
}
const pagination = ref({
show: true,
total: 0,
pageSize: 20,
currentPage: 1,
})
const currentChange = (page: { currentPage: number, pageSize: number }) => {
//queryParams.value.pageNum = page.currentPage
pagination.value.currentPage = page.currentPage
getList()
}
const sizeChange = (page: { currentPage: number, pageSize: number }) => {
//queryParams.value.pageSize = page.pageSize
pagination.value.pageSize = page.pageSize
getList()
}
const formData = ref({
js: ''
})
const closeWithReturn = () =>{
getList()
}
const handleSubmit = (event: any) => {
event.preventDefault();
}
const onClick = async (row:any) => {
const res = await queryDetailService(row.xmid);
dataListRight.value = res.data
selectRow.value = row
}
const onDBClick = ()=>{
}
const onAddClick = ()=> {
modifyVisible.value = true
modifyTitle.value = '新增'
modifyType.value = '新增'
}
const onDelClick = async () => {
if(selectRow.value){
await ElMessageBox.confirm('是否要删除选中的数据?','警告',{confirmButtonText: '确定',cancelButtonText: '取消',});
await delService(selectRow.value.xmid)
ElMessage.success('删除成功!')
}
}
const onQueryClick = () => {
getList()
}
const getList = async () => {
const data = {pageSize: pagination.value.pageSize, pageNum: pagination.value.currentPage,inputData: formData.value.js }
const res = await queryService(data);
dataListLeft.value = res.rows
pagination.value.total = res.total
dataListRight.value = []
}
onMounted(()=>{
getList()
})
</script>
<style scoped lang="scss">
.el-row {
margin-top: 5px;
margin-bottom: 5px;
}
.topForm {
margin-top: 10px;
}
</style>

View File

@ -0,0 +1,120 @@
<template>
<!--仪器收费项目对照-->
<el-row>
<el-form ref="form" :model="formData" label-width="80px" inline>
<el-form-item label="仪器" prop="yq">
<YQSelectTable v-model:data="formData.yq" width="200px" @getDataValue="getList"/>
</el-form-item>
<el-form-item label="项目检索" prop="item">
<el-input placeholder="名称,简拼" v-model="formData.item" @change="getList"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onQueryClick">查询</el-button>
</el-form-item>
<el-form-item>
<span>说明:双击左侧列表,能删除对照数据,双击右边列表能新增数据到对照当中</span>
</el-form-item>
</el-form>
</el-row>
<el-row>
<el-col :span="5">
<CustomTable ref="tableRefLeft" :data="dataListLeft" :columns="columnsLeft" :enable-column-drag="true" @column-drag-end="handleColumnDragEnd"
:config="tableConfig" @row-dblclick="onDBClickLeft"/>
</el-col>
<el-col :span="19">
<CustomTable ref="tableRefRight" :data="dataListRight" :columns="columnsRight" :enable-column-drag="true" @column-drag-end="handleColumnDragEnd"
:config="tableConfig" @row-dblclick="onDBClickRight"/>
</el-col>
</el-row>
</template>
<script setup lang="ts">
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'
import { ElMessage } from 'element-plus';
const tableConfig = ref({
border: true, // 边框
height: '76vh', // 高度
highlightCurrentRow: true, // 高亮当前行
// cellStyle: cellStyleHd
})
//退拽属性
const handleColumnDragEnd = (data: any) => {
// 更新列配置
columnsLeft.value = data.columns;
columnsRight.value = data.columns;
}
const columnsLeft = ref([
{ prop: 'sfxmmc', label: '当前仪器对应的收费项目', visible: true, align: 'center', width: 300 },
{ prop: 'yq', label: '仪器', visible: false, align: 'center', width: 100 },
]);
const columnsRight = ref([
{ prop: 'xmlb', label: '类别', visible: true, align: 'center', width: 100 },
{ prop: 'sfxmdh', label: '收费项目代号', visible: true, align: 'center', width: 200 },
{ prop: 'sfxmmc', label: '收费项目名称', visible: true, align: 'center', width: 300 },
{ prop: 'dj', label: '单价', visible: true, align: 'center', width: 100 },
{ prop: 'cp_yq', label: '分配了仪器', visible: true, align: 'center', width: 400 }
]);
const dataListLeft = ref([
{'sfxmdh':'','yq':''}
])
const dataListRight = ref([])
const formData = ref({
yq: '',
item: ''
})
//刷新数据
const getList = async () => {
if(!formData.value.yq) formData.value.yq = ''
let res = await queryService({yq: formData.value.yq});
dataListLeft.value = res.data;
res = await queryOneService('HISOPT','sp_gyxmyljg')
let param = res.data.value
//先写固定值,后面再改
if(param && param !== ''){
param = '1'
}else{
param = '1'
}
res = await queryXmService({yljg: param,yq: formData.value.yq,queryValue: formData.value.item});
dataListRight.value = res.data;
};
const onDBClickRight = async (row:any)=> {
//新增数据
await addService({sfxmdh:row.sfxmdh,yq: formData.value.yq})
ElMessage.success('新增成功!')
getList()
}
const onDBClickLeft = async (row:any) => {
//删除数据
await delService({yq: formData.value.yq,sfxmdh: row.sfxmdh})
ElMessage.success('删除成功!')
getList()
}
const onQueryClick = () => {
if(!formData.value.yq) {
ElMessage.error('请先选择仪器!')
return
}
getList()
}
</script>
<style scoped lang="scss">
</style>

View File

@ -5,7 +5,7 @@
<el-row :gutter="10">
<el-col :span="4">
<el-form-item label="委托机构:" prop="SrcHospName">
<SelectTable v-model:data="queryParams.srcHospName" :fields="ksdhFields" :tableData="hosList"
<SelectTable v-model:data="queryParams.SrcHospName" :fields="ksdhFields" :tableData="hosList"
label="label" :size="aotuSize" value="label" objKey="label" :border="true" placeholder="请选择委托机构" />
</el-form-item>
</el-col>
@ -18,12 +18,12 @@
<el-col :span="4">
<el-form-item label="条码号:" prop="Barcode">
<el-input v-model="queryParams.barcode" placeholder="请输入条码号" clearable />
<el-input v-model="queryParams.Barcode" placeholder="请输入条码号" clearable />
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="姓名:" prop="PatName">
<el-input v-model="queryParams.patName" placeholder="请输入姓名" clearable />
<el-input v-model="queryParams.PatName" placeholder="请输入姓名" clearable />
</el-form-item>
</el-col>
<el-col :span="4">
@ -39,13 +39,13 @@
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="采样人:" prop="affirmUserName">
<el-input v-model="queryParams.affirmUserName" placeholder="请输入采样人" clearable />
<el-form-item label="采样人:" prop="AffirmUserName">
<el-input v-model="queryParams.AffirmUserName" placeholder="请输入采样人" clearable />
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="签收人:" prop="signInUserName">
<el-input v-model="queryParams.signInUserName" placeholder="请输入签收人" clearable />
<el-form-item label="签收人:" prop="SignInUserName">
<el-input v-model="queryParams.SignInUserName" placeholder="请输入签收人" clearable />
</el-form-item>
</el-col>
<el-col :span="4">
@ -129,7 +129,7 @@ const columns: any = ref([
{ prop: 'sampleTypeName', label: '标本类型', align: 'center', visible: true, },
{ prop: 'tubeName', label: '采集容器', align: 'center', visible: true, },
{ prop: 'status', label: '标本状态', align: 'center', visible: true, slot: "status" },
{ prop: 'moveStateName', label: '流转状态', align: 'center', visible: true, },
// { prop: 'moveStateName', label: '流转状态', align: 'center', visible: true, },
{ prop: 'affirmUserName', label: '采样人', align: 'center', visible: true, },
{ prop: 'affirmTime', label: '采样时间', align: 'center', visible: true, width: 150 },
{ prop: 'signInUserName', label: '签收人', align: 'center', visible: true, },

View File

@ -5,7 +5,7 @@
<el-row :gutter="10">
<el-col :span="5">
<el-form-item label="委托机构:" prop="SrcHospName">
<SelectTable v-model:data="queryParams.srcHospName" :fields="ksdhFields" :tableData="hosList"
<SelectTable v-model:data="queryParams.SrcHospName" :fields="ksdhFields" :tableData="hosList"
label="label" :size="aotuSize" value="value" objKey="value" :border="true" placeholder="请选择委托机构" />
</el-form-item>
</el-col>
@ -17,12 +17,12 @@
</el-col>
<el-col :span="5">
<el-form-item label="条码号:" prop="Barcode">
<el-input v-model="queryParams.barcode" placeholder="请输入条码号" clearable />
<el-input v-model="queryParams.Barcode" placeholder="请输入条码号" clearable />
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item label="姓名:" prop="PatName">
<el-input v-model="queryParams.patName" placeholder="请输入姓名" clearable />
<el-input v-model="queryParams.PatName" placeholder="请输入姓名" clearable />
</el-form-item>
</el-col>
<el-col :span="5">
@ -58,7 +58,7 @@
<div class="mb10">
<el-button type="primary" @click="qsHandle(50)">标本签收</el-button>
<el-button type="primary" @click="qsHandle(110)">标本拒签</el-button>
<el-button type="primary" plain @click="qsHandle(100)">标本退回</el-button>
<el-button type="primary" plain @click="bbThHandle">标本退回</el-button>
</div>
<CustomTable ref="tableRefs" :data="tableData" :columns="columns" :config="tableConfig" :pagination="pagination"
@ -86,7 +86,7 @@ import { listhospital } from "@/api/regional/dict/hospital.js";
// @ts-ignore
import { listregdict } from "@/api/regional/dict/regdict.js";
import { classCom } from '@/utils/classCom';
import { ElMessage } from 'element-plus';
import { ElMessage, ElMessageBox } from 'element-plus';
const aotuSize = classCom.useAutoSize();
import { useRouter } from 'vue-router'
const router = useRouter()
@ -98,15 +98,15 @@ const tableData: any = ref([])
const columns: any = ref([
{ type: 'selection', align: 'center', visible: true, width: 40 },
{ prop: 'barcode', label: '条码号', align: 'center', visible: true, width: 150 },
{ prop: 'srcHospName', label: '委托机构', align: 'center', visible: true, width: 200 },
{ prop: 'srcHospName', label: '委托机构', align: 'center', visible: true, width: 250 },
{ prop: 'patName', label: '姓名', align: 'center', visible: true, width: 70 },
{ prop: 'patSex', label: '性别', align: 'center', visible: true, width: 60, slot: "patSex" },
{ prop: 'patAge', label: '年龄', align: 'center', visible: true, slot: "patAge", width: 60 },
{ prop: 'checkPUR', label: '申请项目', align: 'center', visible: true, width: 200 },
{ prop: 'checkPUR', label: '申请项目', align: 'center', visible: true, width: 250 },
{ prop: 'sampleTypeName', label: '标本类型', align: 'center', visible: true, },
{ prop: 'tubeName', label: '采集容器', align: 'center', visible: true, },
{ prop: 'status', label: '标本状态', align: 'center', visible: true, slot: "status" },
{ prop: 'moveStateName', label: '流转状态', align: 'center', visible: true, },
// { prop: 'moveStateName', label: '流转状态', align: 'center', visible: true, },
{ prop: 'affirmUserName', label: '采样人', align: 'center', visible: true, },
{ prop: 'affirmTime', label: '采样时间', align: 'center', visible: true, width: 150 },
{ prop: 'dstHospName', label: '检测机构名称', align: 'center', visible: true, width: 150 },
@ -134,12 +134,29 @@ const tableRefs = ref(null)
const handleSelectionChange = (val: any) => {
barcodes.value = val.map((item: any) => item.barcode)
}
const backReasons = ref('')
const bbThHandle = () => {
if (!barcodes.value.length) return ElMessage.warning('请选择数据!')
ElMessageBox.prompt('请输入退回理由:', '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
inputPattern: /\S+/,
inputErrorMessage: '请输入退回理由',
})
.then(({ value }) => {
backReasons.value = value
qsHandle(100)
}).catch(() => {
backReasons.value = ''
});
}
//标本签收
const qsHandle = (val: number) => {
if (!barcodes.value.length) return ElMessage.warning('请选择数据!')
sampleSign({ status: val, barcode: barcodes.value }).then((res: any) => {
sampleSign({ status: val, barcode: barcodes.value, backReasons: backReasons.value }).then((res: any) => {
if (res.code == 0) {
ElMessage.success(res.msg)
ElMessage.success('操作成功!')
backReasons.value = ''
handleQuery()
}
})

View File

@ -5,7 +5,7 @@
<el-row :gutter="10">
<el-col :span="5">
<el-form-item label="委托机构:" prop="SrcHospName">
<SelectTable v-model:data="queryParams.srcHospName" :fields="ksdhFields" :tableData="hosList"
<SelectTable v-model:data="queryParams.SrcHospName" :fields="ksdhFields" :tableData="hosList"
label="label" :size="aotuSize" value="value" objKey="value" :border="true" placeholder="请选择委托机构" />
</el-form-item>
</el-col>
@ -17,12 +17,12 @@
</el-col>
<el-col :span="5">
<el-form-item label="条码号:" prop="Barcode">
<el-input v-model="queryParams.barcode" placeholder="请输入条码号" clearable />
<el-input v-model="queryParams.Barcode" placeholder="请输入条码号" clearable />
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item label="姓名:" prop="PatName">
<el-input v-model="queryParams.patName" placeholder="请输入姓名" clearable />
<el-input v-model="queryParams.PatName" placeholder="请输入姓名" clearable />
</el-form-item>
</el-col>
<el-col :span="5">
@ -93,21 +93,19 @@ const queryParams: any = ref({
})
const tableData: any = ref([])
const columns: any = ref([
{ type: 'selection', align: 'center', visible: true, },
{ prop: 'barcode', label: '处理状态', align: 'center', visible: true, },
{ type: 'selection', align: 'center', visible: true, width: 40 },
{ prop: 'barcode', label: '条码号', align: 'center', visible: true, },
{ prop: 'patName', label: '姓名', align: 'center', visible: true, },
{ prop: 'patName', label: '姓名', align: 'center', visible: true, width: 60 },
{ prop: 'patSex', label: '性别', align: 'center', visible: true, width: 60, slot: "patSex" },
{ prop: 'patAge', label: '年龄', align: 'center', visible: true, slot: "patAge", width: 60 },
{ prop: 'checkPUR', label: '申请项目', align: 'center', visible: true, },
{ prop: 'srcHospName', label: '委托机构', align: 'center', visible: true, },
{ prop: 'srcHospName', label: '检测机构', align: 'center', visible: true, },
{ prop: 'checkPUR', label: '申请项目', align: 'center', visible: true, width: 200 },
{ prop: 'srcHospName', label: '委托机构', align: 'center', visible: true, width: 200 },
{ prop: 'srcHospName', label: '检测机构', align: 'center', visible: true, width: 200 },
{ prop: 'Status', label: '标本状态', align: 'center', visible: true, slot: "status" },
{ prop: '', label: '退回理由', align: 'center', visible: true, },
{ prop: 'affirmTime', label: '采样时间', align: 'center', visible: true, },
{ prop: 'signInUserName', label: '操作人', align: 'center', visible: true, },
{ prop: 'signInTime', label: '操作时间', align: 'center', visible: true, },
{ prop: 'bz', label: '备注', align: 'center', visible: true, },
{ prop: 'backReasons', label: '退回理由', align: 'center', visible: true, width: 150 },
{ prop: 'affirmTime', label: '采样时间', align: 'center', visible: true, width: 150 },
{ prop: 'backUserName', label: '操作人', align: 'center', visible: true, },
{ prop: 'backTime', label: '操作时间', align: 'center', visible: true, width: 150 },
])
const tableConfig = ref({
border: true, // 边框
@ -134,7 +132,7 @@ const thHandle = (val: number) => {
if (!barcodes.value.length) return ElMessage.warning('请选择数据!')
sampleSign({ status: val, barcode: barcodes.value }).then((res: any) => {
if (res.code == 0) {
ElMessage.success('标本签收成功!')
ElMessage.success('操作成功!')
handleQuery()
}
})

View File

@ -5,7 +5,7 @@
<el-row :gutter="10">
<el-col :span="5">
<el-form-item label="委托机构:" prop="SrcHospName">
<SelectTable v-model:data="queryParams.srcHospName" :fields="ksdhFields" :tableData="hosList"
<SelectTable v-model:data="queryParams.SrcHospName" :fields="ksdhFields" :tableData="hosList"
label="label" :size="aotuSize" value="value" objKey="value" :border="true" placeholder="请选择委托机构" />
</el-form-item>
</el-col>
@ -19,12 +19,12 @@
<el-col :span="5">
<el-form-item label="条码号:" prop="Barcode">
<el-input v-model="queryParams.barcode" placeholder="请输入条码号" clearable @change="handleQuery" />
<el-input v-model="queryParams.Barcode" placeholder="请输入条码号" clearable @change="handleQuery" />
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item label="姓名:" prop="PatName">
<el-input v-model="queryParams.patName" placeholder="请输入姓名" clearable @change="handleQuery" />
<el-input v-model="queryParams.PatName" placeholder="请输入姓名" clearable @change="handleQuery" />
</el-form-item>
</el-col>
<el-col :span="5">
@ -61,16 +61,17 @@
<div class="cz_box">
<el-row :gutter="10">
<el-col :span="1.5"> 送检医院:</el-col>
<el-col :span="3">
<SelectTable v-model:data="queryParams.DstHospName" :fields="ksdhFields" :tableData="hosList" label="label"
:size="aotuSize" value="label" objKey="label" :border="true" placeholder="请选择" />
<el-col :span="4">
<SelectTable v-model:data="dstHospCode" :fields="ksdhFields" :tableData="hosList" label="label"
:size="aotuSize" value="value" objKey="value" :border="true" placeholder="请选择" @get-data-value="getValue" />
</el-col>
<el-col :span="1.5"> <el-button type="primary">标本送检</el-button></el-col>
<el-col :span="1.5"> <el-button type="primary">取消送检</el-button></el-col>
<el-col :span="1.5"> <el-button type="primary" :size="aotuSize" @click="sjHandle(30)">标本送检</el-button></el-col>
<el-col :span="1.5"> <el-button type="primary" :size="aotuSize" @click="sjHandle(20)">取消送检</el-button></el-col>
</el-row>
</div>
<CustomTable ref="tableRefs" :data="tableData" :columns="columns" :config="tableConfig" :pagination="pagination">
<CustomTable ref="tableRefs" :data="tableData" :columns="columns" :config="tableConfig" :pagination="pagination"
@selection-change="handleSelectionChange" @size-change="sizeChange" @page-change="currentChange">
<template #patAge="{ row }">
{{ row.patAge }}{{ row.ageUnit }}
</template>
@ -87,13 +88,14 @@
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import { querySample } from '@/api/regional/index'
import { querySample, sampleSign } from '@/api/regional/index'
// @ts-ignore
import { listhospital } from "@/api/regional/dict/hospital.js";
// @ts-ignore
import { listregdict } from "@/api/regional/dict/regdict.js";
import SelectTable from '@/components/SelectTable/index.vue';
import { classCom } from '@/utils/classCom';
import { ElMessage } from 'element-plus';
const aotuSize = classCom.useAutoSize();
const queryParams: any = ref({
@ -103,14 +105,14 @@ const queryParams: any = ref({
})
const tableData: any = ref([])
const columns: any = ref([
{ type: 'selection', align: 'center', visible: true, },
{ type: 'selection', align: 'center', visible: true, width: 40 },
{ prop: 'barcode', label: '条码号', align: 'center', visible: true, },
{ prop: 'srcHospName', label: '委托机构', align: 'center', visible: true, width: 200 },
{ prop: 'srcHospName', label: '委托机构', align: 'center', visible: true, width: 250 },
{ prop: 'patName', label: '姓名', align: 'center', visible: true, width: 60 },
{ prop: 'patSex', label: '性别', align: 'center', visible: true, width: 60, slot: "patSex" },
{ prop: 'patAge', label: '年龄', align: 'center', visible: true, slot: "patAge", width: 60 },
{ prop: 'checkPUR', label: '申请项目', align: 'center', visible: true, width: 200 },
{ prop: 'sampleTypeName', label: '标本类型名称', align: 'center', visible: true, },
{ prop: 'checkPUR', label: '申请项目', align: 'center', visible: true, width: 250 },
{ prop: 'sampleTypeName', label: '标本类型', align: 'center', visible: true, },
{ prop: 'status', label: '标本状态', align: 'center', visible: true, slot: "status" },
{ prop: 'affirmUserName', label: '采样人', align: 'center', visible: true, },
{ prop: 'affirmTime', label: '采样时间', align: 'center', visible: true, width: 150 },
@ -132,15 +134,41 @@ const pagination = ref({
})
const ksdhFields = ref([
{ prop: 'label', label: '名称', enablePinyinSearch: true },
{ prop: 'value', label: '代号', width: 80, enablePinyinSearch: true },
{ prop: 'label', label: '名称', width: 150, enablePinyinSearch: true },
{ prop: 'value', label: '代号', width: 120, enablePinyinSearch: true },
])
const dstHospName = ref('')
const dstHospCode = ref('')
const barcodes = ref([])
const handleSelectionChange = (val: any) => {
barcodes.value = val.map((item: any) => item.barcode)
}
const getValue = (val: any) => {
console.log('val==>', val);
dstHospName.value = val.label
}
const sjHandle = (val: number) => {
if (!barcodes.value.length) return ElMessage.warning('请选择数据!')
if (!dstHospCode.value) return ElMessage.warning('请选择送检医院!')
const params = {
barcode: barcodes.value,
dstHospName: dstHospName.value,
dstHospCode: dstHospCode.value,
status: val
}
sampleSign(params).then((res: any) => {
if (res.code == 0) {
ElMessage.success('操作成功!')
handleQuery()
dstHospCode.value = ''
}
})
}
const currentChange = (page: { currentPage: number, pageSize: number }) => {
queryParams.value.pageNum = page.currentPage
handleQuery()

View File

@ -9,10 +9,9 @@
value-format="YYYY-MM-DD HH:mm:ss" @change="handletime" style="width: 25rem;" />
</el-form-item>
<el-form-item label="医疗机构:" prop="yljg">
<el-select v-model="queryParams.yljg" placeholder="请选择" style="width: 9.37rem;">
<el-option v-for="item in dictData.HOS" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-form-item label="委托机构:" prop="SrcHospName">
<SelectTable v-model:data="queryParams.SrcHospName" :fields="ksdhFields" :tableData="hosList" label="label"
width="12.5rem" :size="aotuSize" value="label" objKey="label" :border="true" placeholder="请选择委托机构" />
</el-form-item>
<el-form-item label="条码状态:" prop="zt">
<el-select v-model="queryParams.zt" placeholder="请选择" style="width: 6.25rem;">
@ -166,9 +165,12 @@ import CustomTable from '@/components/elTable/index.vue'
import { useRouter } from 'vue-router'
import { usePrintStore } from '@/store/modules/printStore'
import { fetchCodeList, addObj, fetchCodeDetail, fetchCodeExec, fetchCodeReqmain } from '@/api/checkCode/index'
// @ts-ignore
import { listhospital } from "@/api/regional/dict/hospital.js";
const aotuSize = classCom.useAutoSize();
//@ts-ignore
import { comDict } from '@/utils/dict'
import SelectTable from '@/components/SelectTable/index.vue';
import { ElMessage, ElMessageBox } from 'element-plus'
const router = useRouter()
const printStore = usePrintStore();
@ -184,6 +186,7 @@ interface QueryParams {
zt: string;
failed4: string;
failed5: string;
SrcHospName: string;
}
// 提交表单数据
const queryParams = reactive<QueryParams>({
@ -191,6 +194,7 @@ const queryParams = reactive<QueryParams>({
// times: [],
yljg: '1',
zt: '',
SrcHospName: '',
failed4: '',
failed5: '',
});
@ -248,7 +252,7 @@ const loading = ref(true);
const tableData = ref([])
// 配置项
const columns = ref([
{ type: 'selection', visible: true, align: 'center', width: 35, label: '多选框' },
{ type: 'selection', visible: true, align: 'center', width: 40, label: '多选框' },
{ prop: 'srcHospName', label: '委托机构', visible: true, align: 'center', width: 200, slot: 'srcHospName' },
{ prop: 'zt', label: '打印', visible: true, align: 'center', slot: 'dy', width: 40 },
{ prop: 'jzbz', label: '急', align: 'center', visible: true, slot: 'jzbz', width: 30 },
@ -297,6 +301,10 @@ const cellStyleHd = ({ row, column, rowIndex, columnIndex }: {
}
};
const ksdhFields = ref([
{ prop: 'label', label: '名称', width: 150, enablePinyinSearch: true },
{ prop: 'value', label: '代号', width: 120, enablePinyinSearch: true },
])
const rowClassNameHd = ({ row, rowIndex }: {
row: any;
@ -535,6 +543,7 @@ const cancelHandle = () => {
}
const hosList = ref([])
onMounted(async () => {
// 初始化3天区间(今天-前两天)
// const end = dayjs().format('YYYY-MM-DD HH:mm:ss');
@ -552,7 +561,17 @@ onMounted(async () => {
HOS: toRaw(dictRefs.HOS.value) || [],
ST: toRaw(dictRefs.ST.value) || [],
};
});
listhospital().then((res: any) => {
hosList.value = res.rows.map((item: any) => {
return {
label: item.hospitalName,
value: item.hospitalCode
}
})
});
})
// 字典格式化方法
const formatDict = (v: string, dictType: string) => {

View File

@ -0,0 +1,238 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch">
<el-form-item label="参数代号" prop="dictCode">
<el-input v-model="queryParams.dictCode" placeholder="请输入" clearable style="width: 200px"
@keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="参数名称" prop="dictName">
<el-input v-model="queryParams.dictName" placeholder="请输入" 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>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="regdictList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="参数代号" align="center" prop="dictCode" />
<el-table-column label="参数名称" align="center" prop="dictName" />
<el-table-column label="参数值" align="center" prop="remark" />
<el-table-column label="排序" align="center" prop="dictSort" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :options="sys_normal_disable" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="180" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<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="500px" append-to-body>
<el-form ref="regdictRef" :model="form" :rules="rules" label-width="150px">
<el-form-item label="参数代号" prop="dictCode">
<el-input v-model="form.dictCode" placeholder="请输入参数代号" />
</el-form-item>
<el-form-item label="参数名称" prop="dictName">
<el-input v-model="form.dictName" placeholder="请输入参数名称" />
</el-form-item>
<el-form-item label="顺序" prop="dictSort">
<el-input-number v-model="form.dictSort" controls-position="right" :min="0" />
</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">{{ dict.label
}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="参数值" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="regdict">
import { listregdict, addregdict, delregdict, getregdict, updateregdict } from "@/api/regional/dict/regdict.js";
const { proxy } = getCurrentInstance();
const { sys_normal_disable } = proxy.useDict("sys_normal_disable");
const route = useRoute();
const regdictList = ref([]);
const open = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const title = ref("");
const menuname = ref("字典");
const data = reactive({
form: {},
queryParams: {
pageNum: 1,
pageSize: 15,
dictCode: undefined,
dictName: undefined,
dictType: undefined,
status: undefined
},
rules: {
dictName: [{ required: true, message: "参数名称不能为空", trigger: "blur" }],
dictCode: [{ required: true, message: "参数代号不能为空", trigger: "blur" }],
dictSort: [{ required: true, message: "顺序不能为空", trigger: "blur" }],
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询字典列表 */
function getList() {
loading.value = true;
listregdict(queryParams.value).then(response => {
regdictList.value = response.rows;
total.value = response.total;
loading.value = false;
});
}
/** 取消按钮 */
function cancel() {
open.value = false;
reset();
}
/** 表单重置 */
function reset() {
form.value = {
dictId: undefined,
dictCode: undefined,
dictName: undefined,
dictType: queryParams.value.dictType,
dictSort: 0,
status: "0",
remark: undefined
};
proxy.resetForm("regdictRef");
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef");
handleQuery();
}
/** 多选框选中数据 */
function handleSelectionChange(selection) {
ids.value = selection.map(item => item.dictId);
single.value = selection.length != 1;
multiple.value = !selection.length;
}
/** 新增按钮操作 */
function handleAdd() {
reset();
open.value = true;
title.value = "添加参数"
}
/** 修改按钮操作 */
function handleUpdate(row) {
reset();
const dictId = row.dictId || ids.value;
getregdict(dictId).then(response => {
form.value = response.data;
open.value = true;
title.value = "修改参数"
});
}
/** 提交按钮 */
function submitForm() {
proxy.$refs["regdictRef"].validate(valid => {
if (valid) {
if (form.value.dictId != undefined) {
updateregdict(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功");
open.value = false;
getList();
});
} else {
addregdict(form.value).then(response => {
proxy.$modal.msgSuccess("新增成功");
open.value = false;
getList();
});
}
}
});
}
/** 删除按钮操作 */
function handleDelete(row) {
const dictIds = row.dictId || ids.value;
proxy.$modal.confirm('是否确认删除参数编号为' + dictIds + '"的数据项?').then(function () {
return delregdict(dictIds);
}).then(() => {
getList();
proxy.$modal.msgSuccess("删除成功");
}).catch(() => { });
}
/** 导出按钮操作 */
function handleExport() {
proxy.download("system/regdict/export", {
...queryParams.value
}, `dict_${new Date().getTime()}.xlsx`);
}
getTypes(route.query && route.query.dictType, route.query && route.query.typeName);
/** 查询字典类型详细 */
function getTypes(dictType, typeName) {
queryParams.value.dictType = dictType;
menuname.value = typeName;
getList();
}
</script>

View File

@ -0,0 +1,175 @@
<template>
<div class="app-container">
<div class="compact-form">
<el-form :model="queryParams" ref="queryRef" label-width="5rem" style="width: 100%;" :size="aotuSize">
<el-row :gutter="10">
<el-col :span="5">
<el-form-item label="所属医院:" prop="DstHospName">
<SelectTable v-model:data="queryParams.DstHospName" :fields="ksdhFields" :tableData="hosList"
label="label" :size="aotuSize" value="label" objKey="label" :border="true" placeholder="请选择" />
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item label="标本类型:" prop="SampleTypeName">
<el-select v-model="queryParams.SampleTypeName" placeholder="请选择" clearable>
<el-option v-for="item in regdictList" :label="item.dictName" :value="item.dictCode" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item label="日期:" prop="times">
<el-date-picker v-model="queryParams.times" type="daterange" range-separator="-" start-placeholder="开始时间"
end-placeholder="结束时间" format="YYYY-MM-DD" value-format="YYYY-MM-DD" />
</el-form-item>
</el-col>
<el-col :span="4">
<el-button type="primary" @click="handleQuery">查询</el-button>
<el-button @click="resetHandle">重置</el-button>
</el-col>
</el-row>
</el-form>
</div>
<div class="mb10">
<!-- <el-button type="primary" @click="thHandle(20)">重新采集</el-button>
<el-button type="primary" @click="thHandle(50)">撤销退回</el-button>
<el-button type="primary" @click="thHandle(90)">申请作废</el-button> -->
</div>
<CustomTable ref="tableRefs" :data="tableData" :columns="columns" :config="tableConfig" :pagination="pagination"
@size-change="sizeChange" @page-change="currentChange">
</CustomTable>
</div>
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
import { sampleTypeCount } from '@/api/regional/index'
import SelectTable from '@/components/SelectTable/index.vue';
import { classCom } from '@/utils/classCom';
// @ts-ignore
import { listhospital } from "@/api/regional/dict/hospital.js";
// @ts-ignore
import { listregdict } from "@/api/regional/dict/regdict.js";
import { ElMessage } from 'element-plus';
const aotuSize = classCom.useAutoSize();
import dayjs from 'dayjs';
const today = dayjs().format('YYYY-MM-DD');
const queryParams: any = ref({
pageSize: 50,
pageNum: 1,
times: [today, today]
})
const tableData: any = ref([])
const columns: any = ref([
{ prop: 'srchospname', label: '所属医院', align: 'center', visible: true, },
{ prop: 'sampletypecode', label: '标本代码', align: 'center', visible: true, },
{ prop: 'sampletypename', label: '标本类别', align: 'center', visible: true, },
{ prop: 'sl', label: '数量(份)', align: 'center', visible: true, },
])
const tableConfig = ref({
border: true, // 边框
height: '75vh', // 高度
highlightCurrentRow: true, // 高亮当前行
summary: true,
summaryField: ['sl'],//计算列总和
sumText: '合计'
})
const pagination = ref({
show: true,
total: 0,
pageSize: 50,
currentPage: 1,
})
const ksdhFields = ref([
{ prop: 'label', label: '名称', width: 150, enablePinyinSearch: true },
{ prop: 'value', label: '代号', width: 120, enablePinyinSearch: true },
])
const barcodes = ref([])
const tableRefs = ref(null)
const handleSelectionChange = (val: any) => {
barcodes.value = val.map((item: any) => item.barcode)
}
const currentChange = (page: { currentPage: number, pageSize: number }) => {
queryParams.value.pageNum = page.currentPage
handleQuery()
}
const sizeChange = (page: { currentPage: number, pageSize: number }) => {
queryParams.value.pageSize = page.pageSize
handleQuery()
}
const handleQuery = () => {
if (queryParams.value.times && queryParams.value.times.length > 0) {
queryParams.value.DateStart = queryParams.value.times[0]
queryParams.value.DateEnd = queryParams.value.times[1]
} else {
queryParams.value.DateStart = ''
queryParams.value.DateEnd = ''
}
getList()
}
const resetHandle = () => {
queryParams.value = {
pageSize: 50,
pageNum: 1,
times: [today, today]
}
handleQuery()
}
const getList = () => {
sampleTypeCount(queryParams.value).then((res: any) => {
tableData.value = res.rows
pagination.value.total = res.total
})
}
const hosList = ref([])
const regdictList: any = ref([])
onMounted(() => {
handleQuery()
listhospital().then((res: any) => {
hosList.value = res.rows.map((item: any) => {
return {
label: item.hospitalName,
value: item.hospitalCode
}
})
})
listregdict({ pageSize: 100, pageNum: 1, dictType: 'BT' }).then((res: any) => {
regdictList.value = res.rows
})
})
const formatDict = (v: string, arr: Array<any>) => {
return arr.find((item: any) => item.dictCode == v)?.dictName || v;
};
</script>
<style scoped lang="scss">
.compact-form {
.el-form-item {
margin-bottom: 5px;
}
}
.btns {
display: flex;
flex-direction: column;
justify-content: space-around;
&>button {
width: 100%;
margin-left: 0;
margin-bottom: 5px;
}
}
</style>

View File

@ -0,0 +1,184 @@
<template>
<div class="app-container">
<div class="compact-form">
<el-form :model="queryParams" ref="queryRef" label-width="5rem" style="width: 100%;" :size="aotuSize">
<el-row :gutter="10">
<el-col :span="5">
<el-form-item label="就诊医院:" prop="SrcHospName">
<SelectTable v-model:data="queryParams.SrcHospName" :fields="ksdhFields" :tableData="hosList"
label="label" :size="aotuSize" value="value" objKey="value" :border="true" placeholder="请选择委托机构" />
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item label="检测医院:" prop="DstHospName">
<SelectTable v-model:data="queryParams.DstHospName" :fields="ksdhFields" :tableData="hosList"
label="label" :size="aotuSize" value="label" objKey="label" :border="true" placeholder="请选择" />
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item label="日期:" prop="times">
<el-date-picker v-model="queryParams.times" type="daterange" range-separator="-" start-placeholder="开始时间"
end-placeholder="结束时间" format="YYYY-MM-DD" value-format="YYYY-MM-DD" />
</el-form-item>
</el-col>
<el-col :span="4">
<el-button type="primary" @click="handleQuery">查询</el-button>
<el-button @click="resetHandle">重置</el-button>
</el-col>
</el-row>
</el-form>
</div>
<div class="mb10">
<!-- <el-button type="primary" @click="thHandle(20)">重新采集</el-button>
<el-button type="primary" @click="thHandle(50)">撤销退回</el-button>
<el-button type="primary" @click="thHandle(90)">申请作废</el-button> -->
</div>
<CustomTable ref="tableRefs" :data="tableData" :columns="columns" :config="tableConfig" :pagination="pagination"
@size-change="sizeChange" @page-change="currentChange">
</CustomTable>
</div>
</template>
<script setup lang="ts">
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';
// @ts-ignore
import { listhospital } from "@/api/regional/dict/hospital.js";
// @ts-ignore
import { listregdict } from "@/api/regional/dict/regdict.js";
import { ElMessage } from 'element-plus';
const aotuSize = classCom.useAutoSize();
import dayjs from 'dayjs';
const today = dayjs().format('YYYY-MM-DD');
const queryParams: any = ref({
pageSize: 50,
pageNum: 1,
times: [today, today]
})
const tableData: any = ref([])
const columns: any = ref([
{ prop: 'SrcHospName', label: '就诊医院', align: 'center', visible: true, },
{ prop: 'SrcOrderItemCode', label: '组合编码', align: 'center', visible: true, },
{ prop: 'SrcOrderItemName', label: '组合名称', align: 'center', visible: true, },
{ prop: 'sl', label: '数量(份)', align: 'center', visible: true, },
{ prop: 'cost', label: '费用', align: 'center', visible: true, },
{ prop: 'DstHospName', label: '检测医院', align: 'center', visible: true, },
])
const tableConfig = ref({
border: true, // 边框
height: '75vh', // 高度
highlightCurrentRow: true, // 高亮当前行
summary: true,
summaryField: ['sl', 'cost'],//计算列总和
sumText: '合计'
})
const pagination = ref({
show: true,
total: 0,
pageSize: 50,
currentPage: 1,
})
const ksdhFields = ref([
{ prop: 'label', label: '名称', width: 150, enablePinyinSearch: true },
{ prop: 'value', label: '代号', width: 120, enablePinyinSearch: true },
])
const barcodes = ref([])
const tableRefs = ref(null)
const thHandle = (val: number) => {
if (!barcodes.value.length) return ElMessage.warning('请选择数据!')
sampleSign({ status: val, barcode: barcodes.value }).then((res: any) => {
if (res.code == 0) {
ElMessage.success('操作成功!')
handleQuery()
}
})
}
const handleSelectionChange = (val: any) => {
barcodes.value = val.map((item: any) => item.barcode)
}
const currentChange = (page: { currentPage: number, pageSize: number }) => {
queryParams.value.pageNum = page.currentPage
handleQuery()
}
const sizeChange = (page: { currentPage: number, pageSize: number }) => {
queryParams.value.pageSize = page.pageSize
handleQuery()
}
const handleQuery = () => {
if (queryParams.value.times && queryParams.value.times.length > 0) {
queryParams.value.DateStart = queryParams.value.times[0]
queryParams.value.DateEnd = queryParams.value.times[1]
} else {
queryParams.value.DateStart = ''
queryParams.value.DateEnd = ''
}
getList()
}
const resetHandle = () => {
queryParams.value = {
pageSize: 50,
pageNum: 1,
times: [today, today]
}
handleQuery()
}
const getList = () => {
sampleitemCount(queryParams.value).then((res: any) => {
tableData.value = res.rows
pagination.value.total = res.total
})
}
const hosList = ref([])
const regdictList: any = ref([])
onMounted(() => {
handleQuery()
listhospital().then((res: any) => {
hosList.value = res.rows.map((item: any) => {
return {
label: item.hospitalName,
value: item.hospitalCode
}
})
})
listregdict({ pageSize: 100, pageNum: 1, dictType: 'ZT' }).then((res: any) => {
regdictList.value = res.rows;
})
})
const formatDict = (v: string, arr: Array<any>) => {
return arr.find((item: any) => item.dictCode == v)?.dictName || v;
};
</script>
<style scoped lang="scss">
.compact-form {
.el-form-item {
margin-bottom: 5px;
}
}
.btns {
display: flex;
flex-direction: column;
justify-content: space-around;
&>button {
width: 100%;
margin-left: 0;
margin-bottom: 5px;
}
}
</style>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,510 @@
@charset "UTF-8";
/* CSS Document */
.bg {
margin: 0 auto;
width: 100%;
min-height: 100vh;
background: url(../images/bg2.jpg) no-repeat;
background-size: 100% 100%;
padding-top: 0rem;
padding: 0rem 3.125rem;
}
/*.conIn{
display:flex;
display: -webkit-flex;}*/
.title {
width: 100%;
font-size: 1.875rem;
line-height: 4.6875rem;
color: rgba(14, 253, 255, 1);
text-align: center;
font-weight: bold;
}
.border_bg_leftTop {
position: absolute;
left: -0.125rem;
top: -0.625rem;
width: 5.78125rem;
height: 0.78125rem;
display: block;
background: #01279d url(../images/title_left_bg.png) no-repeat;
background-size: cover;
}
.border_bg_rightTop {
position: absolute;
right: -0.15625rem;
top: -0.15625rem;
width: 1.5625rem;
height: 1.5625rem;
display: block;
background: url(../images/border_bg.jpg) no-repeat;
background-size: cover;
}
.border_bg_leftBottom {
position: absolute;
left: -0.125rem;
bottom: -0.125rem;
width: 1.5625rem;
height: 1.5625rem;
display: block;
background: url(../images/border_bg.jpg) no-repeat;
background-size: cover;
}
.border_bg_rightBottom {
position: absolute;
right: -0.15625rem;
bottom: -0.15625rem;
width: 1.25rem;
height: 1.25rem;
display: block;
background: url(../images/title_right_bg.png) no-repeat;
background-size: cover;
}
.leftMain {
width: 75%;
float: left;
padding-right: 1.5625rem;
padding-top: 1.5625rem;
}
.rightMain {
width: 25%;
float: left;
padding-top: 1.5625rem;
}
.leftMain_top {
width: 100%;
padding-bottom: 1.5625rem;
}
.leftMain_top ul {
display: flex;
display: -webkit-flex;
}
.leftMain_top ul li {
float: left;
width: 25%;
padding-right: 1.5625rem;
}
.leftMain_top ul li:last-child {
padding: 0;
}
.leftMain_top ul li .liIn {
border: 0.125rem solid rgba(14, 253, 255, 0.5);
width: 100%;
min-height: 3.75rem;
position: relative;
padding: .625rem 1.5625rem;
}
.leftMain_top ul li .liIn h3 {
font-size: 1.25rem;
font-weight: 700;
color: #fff;
}
.leftMain_top ul li .liIn .shu {
font-size: 1.875rem;
color: rgba(14, 253, 255, 1);
font-family: dig;
margin-bottom: 0.3125rem;
}
.leftMain_top ul li .liIn .shu i {
font-size: 1rem;
margin-left: 0.9375rem;
font-style: normal;
}
.leftMain_top ul li .liIn .zi {
font-size: 0.625rem;
color: #fff;
position: relative;
z-index: 10;
}
.leftMain_top ul li .liIn .zi .span1 {
margin-right: 1.5625rem;
}
.leftMain_middle {
width: 100%;
padding-bottom: 1.5625rem;
display: flex;
display: -webkit-flex;
}
.leftMain_middle .leftMain_middle_left {
width: 60%;
padding-right: 1.5625rem;
}
.leftMain_middle .leftMain_middle_left .leftMain_middle_leftIn {
border: 0.125rem solid rgba(14, 253, 255, 0.5);
width: 100%;
min-height: 3.75rem;
position: relative;
padding: .625rem;
}
.leftMain_middle_leftIn_zhe {
margin-top: 2vh;
}
.leftMain_middle .leftMain_middle_left .leftMain_middle_leftIn h3 {
font-size: 1.25rem;
color: #fff;
font-weight: 700;
margin-bottom: 0.78125rem;
}
.leftMain_middle .leftMain_middle_left .leftMain_middle_leftIn .biaoge {
min-height: 12.5rem;
}
.leftMain_middle .leftMain_middle_right {
width: 40%;
}
.leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn {
border: 0.125rem solid rgba(14, 253, 255, 0.5);
width: 100%;
min-height: 3.75rem;
position: relative;
padding: .625rem;
}
.leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn h3 {
font-size: 1.25rem;
color: #fff;
font-weight: 700;
margin-bottom: 0.78125rem;
}
.leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn .biaoge {
min-height: 12.5rem;
}
/*左边中间部分排行榜*/
.leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn .biaoge_pai {
width: 100%;
height: 68vh;
overflow: hidden;
}
/* .leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn .biaoge_pai ul{
height: 68vh;
} */
.leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn .biaoge_pai ul li .liIn {
display: flex;
display: -webkit-flex;
align-items: center;
color: #fff;
font-size: 0.9375rem;
height: 2.8125rem;
}
.leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn .biaoge_pai ul li .liIn .liIn_left {
width: 43%;
position: relative;
padding-left: 1.25rem;
}
.leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn .biaoge_pai ul li .liIn .liIn_left .bot {
width: 1.25rem;
height: 1.25rem;
background: #05d1fc;
border-radius: 62.5rem;
display: block;
position: absolute;
left: 0.3125rem;
top: 0;
bottom: 0;
margin: auto 0;
}
.leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn .biaoge_pai ul li .liIn2 .liIn_left .bot {
background: #e7feb8;
}
.leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn .biaoge_pai ul li .liIn3 .liIn_left .bot {
background: #fdea8a;
}
.leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn .biaoge_pai ul li .liIn4 .liIn_left .bot {
background: #8ff9f8;
}
.leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn .biaoge_pai ul li .liIn5 .liIn_left .bot {
background: #d890fa;
}
.leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn .biaoge_pai ul li .liIn6 .liIn_left .bot {
background: #05d1fc;
}
.leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn .biaoge_pai ul li .liIn .liIn_left zi {
}
.leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn .biaoge_pai ul li .liIn .liIn_line {
width: 40%;
height: 1.25rem;
background: rgba(255, 255, 255, 0.5);
border-radius: 125rem;
overflow: hidden;
position: relative;
}
.leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn .biaoge_pai ul li .liIn .liIn_line .line_lineIn {
width: 100%;
height: 1.25rem;
background: #05d1fc;
border-radius: 125rem;
-webkit-animation: widthMove1 2s ease-in-out;
}
.line_lineIn .per {
position: absolute;
top: 0;
left: 50%;
}
.leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn .biaoge_pai ul li .liIn2 .liIn_line .line_lineIn {
background: #e7feb8;
-webkit-animation: widthMove2 2s ease-in-out;
}
.leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn .biaoge_pai ul li .liIn3 .liIn_line .line_lineIn {
background: #fdea8a;
-webkit-animation: widthMove3 2s ease-in-out;
}
.leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn .biaoge_pai ul li .liIn4 .liIn_line .line_lineIn {
background: #8ff9f8;
-webkit-animation: widthMove4 2s ease-in-out;
}
.leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn .biaoge_pai ul li .liIn5 .liIn_line .line_lineIn {
background: #d890fa;
-webkit-animation: widthMove5 2s ease-in-out;
}
.leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn .biaoge_pai ul li .liIn6 .liIn_line .line_lineIn {
background: #05d1fc;
-webkit-animation: widthMove6 2s ease-in-out;
}
@-webkit-keyframes widthMove1 {
0% {
width: 0%;
}
100% {
width: 98.5%;
}
}
@-webkit-keyframes widthMove2 {
0% {
width: 0%;
}
100% {
width: 88.5%;
}
}
@-webkit-keyframes widthMove3 {
0% {
width: 0%;
}
100% {
width: 68.5%;
}
}
@-webkit-keyframes widthMove4 {
0% {
width: 0%;
}
100% {
width: 40.5%;
}
}
@-webkit-keyframes widthMove5 {
0% {
width: 0%;
}
100% {
width: 22.5%;
}
}
@-webkit-keyframes widthMove6 {
0% {
width: 0%;
}
100% {
width: 10.5%;
}
}
.leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn .biaoge_pai ul li .liIn .num {
width: 18%;
font-family: dig;
padding-left: 0.3125rem;
}
/*左边底部*/
.leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn .biaoge_bi ul {
display: flex;
display: -webkit-flex;
flex-wrap: wrap;
width: 100%;
}
.leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn .biaoge_bi ul li {
width: 33.3%;
text-align: center;
margin-bottom: 0.78125rem;
}
.leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn .biaoge_bi ul li .shu {
font-size: 2.1875rem;
color: rgba(14, 253, 255, 1);
font-family: dig;
padding: 1.875rem 0 0.3125rem;
font-weight: normal;
}
.leftMain_middle .leftMain_middle_right .leftMain_middle_rightIn .biaoge_bi ul li .zi {
font-size: 0.9375rem;
color: #fff;
}
/*右边部分*/
.rightMain .rightMain_top {
width: 100%;
padding-bottom: 1.5625rem;
}
.rightMain .rightMain_topIn {
border: 0.125rem solid rgba(14, 253, 255, 0.5);
width: 100%;
min-height: 3.75rem;
position: relative;
padding: .625rem;
}
.rightMain .rightMain_topIn h3 {
font-size: 1.25rem;
color: #fff;
margin-bottom: 0.78125rem;
font-weight: 700;
}
.rightMain .rightMain_topIn .biaoge {
min-height: 12.5rem;
}
.rightMain .rightMain_bottom {
width: 100%;
}
.rightMain .rightMain_bottomIn {
border: 0.125rem solid rgba(14, 253, 255, 0.5);
width: 100%;
min-height: 3.75rem;
position: relative;
padding: 1.25rem 0.78125rem;
}
.rightMain .rightMain_bottomIn h3 {
font-size: 1.25rem;
color: #fff;
margin-bottom: 0.78125rem;
font-weight: 700;
}
/*右下角表格*/
.rightMain .rightMain_bottomIn .biaoge {
min-height: 12.5rem;
}
.rightMain .rightMain_bottomIn .biaoge_list {
overflow: hidden;
position: relative;
}
.rightMain .rightMain_bottomIn .biaoge_list .biaoge_listIn .ul_list {
overflow: hidden;
position: relative;
}
.rightMain .rightMain_bottomIn .biaoge_list .biaoge_listIn .ul_listIn {
-webkit-animation: 14s gundong linear infinite normal;
animation: 14s gundong linear infinite normal;
position: relative;
}
@keyframes gundong {
0% {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
100% {
-webkit-transform: translate3d(0, -30vh, 0);
transform: translate3d(0, -30vh, 0);
}
}
.rightMain .rightMain_bottomIn .biaoge_list ul {
display: flex;
display: -webkit-flex;
width: 100%;
}
.rightMain .rightMain_bottomIn .biaoge_list .ul_title {
background: linear-gradient(left, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.1));
background: -ms-linear-gradient(left, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.1));
background: -webkit-linear-gradient(left, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.1));
background: -moz-linear-gradient(left, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.1));
}
.rightMain .rightMain_bottomIn .biaoge_list .ul_con {
border-bottom: 0.125rem solid rgba(14, 253, 255, 0.5);
}
.rightMain .rightMain_bottomIn .biaoge_list ul li {
width: 20%;
text-align: center;
color: #fff;
font-size: 0.9375rem;
height: 3.125rem;
line-height: 3.125rem;
}
.rightMain .rightMain_bottomIn .biaoge_list ul li:frist-child {
text-align: left;
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1,524 @@
<template>
<div class="bg">
<div class="title">区域检验数据中心</div>
<div class="leftMain">
<div class="leftMain_top">
<div class="leftMain_topIn">
<ul>
<li v-for="item in source">
<div class="liIn">
<h3>{{ item.name }}</h3>
<p class="shu"><span class="shu1">{{ item.num }}</span><i>{{ item.unit }}</i></p>
<span class="border_bg_leftTop"></span>
<span class="border_bg_rightTop"></span>
<span class="border_bg_leftBottom"></span>
<span class="border_bg_rightBottom"></span>
</div>
</li>
</ul>
</div>
</div>
<div class="leftMain_middle">
<div class="leftMain_middle_left">
<div class="leftMain_middle_leftIn">
<h3>委托机构当月送检标本数量</h3>
<!-- 为ECharts准备一个具备大小(宽高)的Dom -->
<div class="biaoge" style="width:100%; height:30vh" ref="chartmain" id="chartmain"></div>
<span class="border_bg_leftTop"></span>
<span class="border_bg_rightTop"></span>
<span class="border_bg_leftBottom"></span>
<span class="border_bg_rightBottom"></span>
</div>
<div class="leftMain_middle_leftIn leftMain_middle_leftIn_zhe">
<h3>近一个月送检标本数量趋势图</h3>
<div class="biaoge" style="width:100%; height:30vh" ref="chartmain_zhe" id="chartmain_zhe"></div>
<span class="border_bg_leftTop"></span>
<span class="border_bg_rightTop"></span>
<span class="border_bg_leftBottom"></span>
<span class="border_bg_rightBottom"></span>
</div>
</div>
<div class="leftMain_middle_right">
<div class="leftMain_middle_rightIn">
<h3>委托机构当月送检标本占比</h3>
<div class="biaoge biaoge_pai">
<div class="biaoge_paiIn">
<ul>
<!-- <Vue3SeamlessScroll :list="listData" :step="0.5 as any" :hover="true as any" :key="listData.length"
:limitMoveNum="14"> -->
<li v-for="(item, i) in listData">
<div class="liIn">
<div class="liIn_left"><span class="zi">{{ item.groupname }}</span></div>
<div class="liIn_line">
<div class="line_lineIn" :style="{ width: ` ${item.percentage}` }">
<div class="per">{{ item.percentage }}</div>
</div>
</div>
<p class="num">{{ item.groupsum }}</p>
</div>
</li>
<!-- </Vue3SeamlessScroll> -->
</ul>
</div>
</div>
<span class="border_bg_leftTop"></span>
<span class="border_bg_rightTop"></span>
<span class="border_bg_leftBottom"></span>
<span class="border_bg_rightBottom"></span>
</div>
</div>
</div>
</div>
<div class="rightMain">
<div class="rightMain_top">
<div class="rightMain_topIn">
<h3>当日送检样本情况</h3>
<div class="biaoge" style="width:100%; height:35vh" ref="chartmain_bing" id="chartmain_bing"></div>
<span class="border_bg_leftTop"></span>
<span class="border_bg_rightTop"></span>
<span class="border_bg_leftBottom"></span>
<span class="border_bg_rightBottom"></span>
</div>
</div>
<div class="rightMain_bottom">
<div class="rightMain_bottomIn">
<h3>送检项目分类占比</h3>
<div class="biaoge biaoge_list" ref="sjRef" style="width:100%; height:34vh">
</div>
<span class="border_bg_leftTop"></span>
<span class="border_bg_rightTop"></span>
<span class="border_bg_leftBottom"></span>
<span class="border_bg_rightBottom"></span>
</div>
</div>
</div>
<div style="clear:both;"></div>
</div>
</template>
<script setup lang="ts">
import * as echarts from 'echarts';
import { Vue3SeamlessScroll } from 'vue3-seamless-scroll'
import { getallcount } from '@/api/regional'
const source = ref([
{ name: '区域机构', num: 0, unit: '家', pre: 'jgs' },
{ name: '检验人数', num: 0, unit: '人', pre: 'rs' },
{ name: '检验管数', num: 0, unit: '个', pre: 'gs' },
{ name: '检验报告数', num: 0, unit: '份', pre: 'bgs' },
{ name: '检验项目数', num: 0, unit: '个', pre: 'xms' },
])
const listData: any = ref([])
const chartmain = ref()
const getEcharts1 = (data: any) => {
const Intance = echarts.init(chartmain.value);
var dataAxis = data.map((item: any) => item.daynum + '日')
var data = data.map((item: any) => item.sl)
const option = {
title: {
text: '',
subtext: ''
},
grid: {
x: 40,
y: 40,
x2: 20,
y2: 50,
},
tooltip: {
trigger: 'axis'
},
xAxis: {
data: dataAxis,
axisLabel: {
/*inside: true,*/
interval: 0,
color: '#fff',
fontSize: 12
},
axisTick: {
show: false,
},
axisLine: {
show: true,
symbol: ['none', 'arrow'],
symbolOffset: 12,
lineStyle: {
color: '#fff',
}
},
lineStyle: {
color: '#fff',
},
z: 10
},
dataZoom: [{
type: 'slider',
show: true, //flase直接隐藏图形
xAxisIndex: [0],
textStyle: {
color: '#0efdff', // 文字颜色(如白色,根据主题调整)
fontSize: 12, // 文字大小
fontWeight: 'normal' // 文字粗细
},
left: '9%', //滚动条靠左侧的百分比
bottom: 0,
start: 0,//滚动条的起始位置
end: 70 //滚动条的截止位置(按比例分割你的柱状图x轴长度)
}],
yAxis: {
type: 'value',
name: '单位:个',
axisLine: {
show: true,
symbol: ['none', 'arrow'],
symbolOffset: 12,
lineStyle: {
color: '#fff',
}
},
axisTick: {
show: false
},
axisLabel: {
color: '#fff',
fontSize: 12
}
},
series: [
{
type: 'bar',
itemStyle: {
color: new echarts.graphic.LinearGradient(
0, 0, 0, 1,
[
{ offset: 0, color: '#0efdff' },
{ offset: 0.5, color: '#188df0' },
{ offset: 1, color: '#188df0' }
]
)
},
emphasis: {
itemStyle: {
color: new echarts.graphic.LinearGradient(
0, 0, 0, 1,
[
{ offset: 0, color: '#2378f7' },
{ offset: 0.7, color: '#2378f7' },
{ offset: 1, color: '#0efdff' }
]
)
}
},
data: data
}
]
};
Intance.setOption(option);
}
const chartmain_bing = ref()
const getEcharts2 = (data: any) => {
const names = data.map((item: any) => item.name)
const Intance = echarts.init(chartmain_bing.value);
const option = {
title: {
text: '数据情况统计',
subtext: '',
left: 'right',
textStyle: {
color: '#fff',
fontSize: 12
}
},
tooltip: {
trigger: 'item',
formatter: '{b} : {c} ({d}%)'
},
legend: {
// orient: 'vertical',
// top: 'middle',
type: 'scroll',
orient: 'vertical',
right: 10,
top: 40,
bottom: 20,
left: 'right',
data: names,
textStyle: {
color: '#fff',
fontSize: 12
}
},
grid: {
x: '-10%',
y: 40,
x2: 20,
y2: 20,
},
color: ['#09d0fb', '#f88cfb', '#95f8fe', '#f9f390', '#ecfeb7'],
series: [
{
type: 'pie',
radius: '65%',
center: ['45%', '50%'],
selectedMode: 'single',
data: data,
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
};
Intance.setOption(option);
}
const chartmain_zhe = ref()
const getEcharts3 = () => {
const Intance = echarts.init(chartmain_zhe.value);
const xData = listData.value[0].dayline.map((item: any) => item.daynum + '日')
const tooltips = listData.value.map((item: any) => item.groupname)
const colors = ['#ff7f50', '#87cefa', '#da70d6', '#32cd32', '#6495ed', '#ff69b4', '#ba55d3', '#cd5c5c', '#ffa500', '#40e0d0',
'#1e90ff', '#ff6347', '#7b68ee', '#d0648a', '#ffd700', '#6b8e23', '#4ea397', '#3cb371', '#b8860b']
const arr = listData.value.map((item: any, i: number) => {
return {
name: item.groupname,
type: 'line',
data: item.dayline.map((v: any) => v.sl),
itemStyle: {
color: colors[i],
},
lineStyle: {
color: colors[i],
width: 2,
}
}
})
const option = {
title: {
text: ''
},
tooltip: {
trigger: 'axis', // 或 'item',根据图表类型选择
},
legend: {
type: 'scroll', // 开启滚动
textStyle: {
color: '#fff', // 文字颜色(保持与你的主题一致)
fontSize: 12
},
// 滚动箭头样式(兼容写法)
pageIcon: 'circle', // 箭头形状(可选:'arrow'/'circle'等)
pageIconColor: '#0efdff', // 箭头颜色(核心配置,替代pageButtonItemStyle)
pageIconSize: 12, // 箭头大小
pageIconInactiveColor: '#666666', // 首尾不可滚动时的箭头颜色
pageTextStyle: {
color: '#0efdff' // 分页文字颜色(若显示数字分页)
},
data: tooltips
},
grid: {
x: 40,
y: 40,
x2: 20,
y2: 50,
},
toolbox: {
feature: {
//saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
axisLabel: {
/*inside: true,*/
interval: 0,
color: '#fff',
fontSize: 12
},
axisTick: {
show: false,
},
axisLine: {
show: true,
symbol: ['none', 'arrow'],
symbolOffset: 12,
lineStyle: {
color: '#fff',
}
},
data: xData
},
dataZoom: [{
type: 'slider',
show: true, //flase直接隐藏图形
xAxisIndex: [0],
textStyle: {
color: '#0efdff', // 文字颜色(如白色,根据主题调整)
fontSize: 12, // 文字大小
fontWeight: 'normal' // 文字粗细
},
left: '9%', //滚动条靠左侧的百分比
bottom: 0,
start: 0,//滚动条的起始位置
end: 70 //滚动条的截止位置(按比例分割你的柱状图x轴长度)
}],
yAxis: {
type: 'value',
axisLine: {
show: true,
symbol: ['none', 'arrow'],
symbolOffset: 12,
lineStyle: {
color: '#fff',
}
},
axisTick: {
show: false
},
axisLabel: {
color: '#fff',
fontSize: 12
}
},
series: arr
};
Intance.setOption(option);
}
const sjRef = ref()
const getEcharts4 = (data: any) => {
const names = data.map((item: any) => item.name)
const Intance = echarts.init(sjRef.value);
const option = {
title: {
text: '数据情况统计',
subtext: '',
left: 'right',
textStyle: {
color: '#fff',
fontSize: 12
}
},
tooltip: {
trigger: 'item',
formatter: '{b} : {c} ({d}%)'
},
legend: {
// orient: 'vertical',
// top: 'middle',
type: 'scroll',
orient: 'vertical',
right: 10,
top: 40,
bottom: 20,
left: 'right',
data: names,
textStyle: {
color: '#fff',
fontSize: 12
},
// 滚动箭头样式(兼容写法)
pageIcon: 'circle', // 箭头形状(可选:'arrow'/'circle'等)
pageIconColor: '#0efdff', // 箭头颜色(核心配置,替代pageButtonItemStyle)
pageIconSize: 12, // 箭头大小
pageIconInactiveColor: '#666666', // 首尾不可滚动时的箭头颜色
pageTextStyle: {
color: '#0efdff' // 分页文字颜色(若显示数字分页)
},
},
grid: {
x: '-10%',
y: 40,
x2: 20,
y2: 20,
},
color: ['#09d0fb', '#f88cfb', '#95f8fe', '#f9f390', '#ecfeb7'],
series: [
{
type: 'pie',
radius: '65%',
center: ['45%', '50%'],
selectedMode: 'single',
data: data,
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
};
Intance.setOption(option);
}
const getDataInfo = () => {
getallcount().then((res: any) => {
source.value.forEach(item => {
item.num = res.data.regStatAll[item.pre]
})
listData.value = res.data.regStatHospMonth
// nextTick(() => {
// // 数据更新后强制重绘
// (document.querySelector('.Vue3SeamlessScroll') as any)?._init();
// })
const data2 = res.data.regStatStatus.map((item: any) => {
return {
name: item.dict_name,
value: item.sl,
}
})
const data4 = res.data.regStatSample.map((item: any) => {
return {
name: item.SampleTypeName,
value: item.sl,
}
})
getEcharts1(res.data.regStatMonth)
getEcharts2(data2)
getEcharts3()
getEcharts4(data4)
})
}
onMounted(() => {
getDataInfo()
})
</script>
<style scoped>
@import './css/icon.css';
@import './css/index.css';
@import './css/public.css';
</style>