This commit is contained in:
jiangs 2025-12-02 18:14:05 +08:00
commit dde3c944ed
20 changed files with 1436 additions and 563 deletions

View File

@ -36,6 +36,7 @@
"select2": "^4.1.0-rc.0", "select2": "^4.1.0-rc.0",
"socket.io-client": "^4.8.1", "socket.io-client": "^4.8.1",
"sortablejs": "^1.14.0", "sortablejs": "^1.14.0",
"three": "^0.181.2",
"vue": "3.5.23", "vue": "3.5.23",
"vue-cropper": "1.1.1", "vue-cropper": "1.1.1",
"vue-plugin-hiprint": "^0.0.60", "vue-plugin-hiprint": "^0.0.60",

View File

@ -180,3 +180,11 @@ export function cbebCheck(data?: Object) {
params: data params: data
}) })
} }
//修改样本检验日期
export function changepatjyrq(data?: Object) {
return request({
url: '/lisworkgerm/changepatjyrq',
method: 'get',
params: data
})
}

View File

@ -0,0 +1,511 @@
<script setup lang="ts">
// @ts-ignore
import { Clock, Mesh, OrthographicCamera, PlaneGeometry, Scene, ShaderMaterial, Vector2, Vector3, WebGLRenderer } from 'three';
import { onBeforeUnmount, onMounted, ref, useTemplateRef, watch, type CSSProperties } from 'vue';
const vertexShader = `
precision highp float;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;
const fragmentShader = `
precision highp float;
uniform float iTime;
uniform vec3 iResolution;
uniform float animationSpeed;
uniform bool enableTop;
uniform bool enableMiddle;
uniform bool enableBottom;
uniform int topLineCount;
uniform int middleLineCount;
uniform int bottomLineCount;
uniform float topLineDistance;
uniform float middleLineDistance;
uniform float bottomLineDistance;
uniform vec3 topWavePosition;
uniform vec3 middleWavePosition;
uniform vec3 bottomWavePosition;
uniform vec2 iMouse;
uniform bool interactive;
uniform float bendRadius;
uniform float bendStrength;
uniform float bendInfluence;
uniform bool parallax;
uniform float parallaxStrength;
uniform vec2 parallaxOffset;
uniform vec3 lineGradient[8];
uniform int lineGradientCount;
const vec3 BLACK = vec3(0.0);
const vec3 PINK = vec3(233.0, 71.0, 245.0) / 255.0;
const vec3 BLUE = vec3(47.0, 75.0, 162.0) / 255.0;
mat2 rotate(float r) {
return mat2(cos(r), sin(r), -sin(r), cos(r));
}
vec3 background_color(vec2 uv) {
vec3 col = vec3(0.0);
float y = sin(uv.x - 0.2) * 0.3 - 0.1;
float m = uv.y - y;
col += mix(BLUE, BLACK, smoothstep(0.0, 1.0, abs(m)));
col += mix(PINK, BLACK, smoothstep(0.0, 1.0, abs(m - 0.8)));
return col * 0.5;
}
vec3 getLineColor(float t, vec3 baseColor) {
if (lineGradientCount <= 0) {
return baseColor;
}
vec3 gradientColor;
if (lineGradientCount == 1) {
gradientColor = lineGradient[0];
} else {
float clampedT = clamp(t, 0.0, 0.9999);
float scaled = clampedT * float(lineGradientCount - 1);
int idx = int(floor(scaled));
float f = fract(scaled);
int idx2 = min(idx + 1, lineGradientCount - 1);
vec3 c1 = lineGradient[idx];
vec3 c2 = lineGradient[idx2];
gradientColor = mix(c1, c2, f);
}
return gradientColor * 0.5;
}
float wave(vec2 uv, float offset, vec2 screenUv, vec2 mouseUv, bool shouldBend) {
float time = iTime * animationSpeed;
float x_offset = offset;
float x_movement = time * 0.1;
float amp = sin(offset + time * 0.2) * 0.3;
float y = sin(uv.x + x_offset + x_movement) * amp;
if (shouldBend) {
vec2 d = screenUv - mouseUv;
float influence = exp(-dot(d, d) * bendRadius);
float bendOffset = (mouseUv.y - screenUv.y) * influence * bendStrength * bendInfluence;
y += bendOffset;
}
float m = uv.y - y;
return 0.0175 / max(abs(m) + 0.01, 1e-3) + 0.01;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 baseUv = (2.0 * fragCoord - iResolution.xy) / iResolution.y;
baseUv.y *= -1.0;
if (parallax) {
baseUv += parallaxOffset;
}
vec3 col = vec3(0.0);
vec3 b = lineGradientCount > 0 ? vec3(0.0) : background_color(baseUv);
vec2 mouseUv = vec2(0.0);
if (interactive) {
mouseUv = (2.0 * iMouse - iResolution.xy) / iResolution.y;
mouseUv.y *= -1.0;
}
if (enableBottom) {
for (int i = 0; i < bottomLineCount; ++i) {
float fi = float(i);
float t = fi / max(float(bottomLineCount - 1), 1.0);
vec3 lineCol = getLineColor(t, b);
float angle = bottomWavePosition.z * log(length(baseUv) + 1.0);
vec2 ruv = baseUv * rotate(angle);
col += lineCol * wave(
ruv + vec2(bottomLineDistance * fi + bottomWavePosition.x, bottomWavePosition.y),
1.5 + 0.2 * fi,
baseUv,
mouseUv,
interactive
) * 0.2;
}
}
if (enableMiddle) {
for (int i = 0; i < middleLineCount; ++i) {
float fi = float(i);
float t = fi / max(float(middleLineCount - 1), 1.0);
vec3 lineCol = getLineColor(t, b);
float angle = middleWavePosition.z * log(length(baseUv) + 1.0);
vec2 ruv = baseUv * rotate(angle);
col += lineCol * wave(
ruv + vec2(middleLineDistance * fi + middleWavePosition.x, middleWavePosition.y),
2.0 + 0.15 * fi,
baseUv,
mouseUv,
interactive
);
}
}
if (enableTop) {
for (int i = 0; i < topLineCount; ++i) {
float fi = float(i);
float t = fi / max(float(topLineCount - 1), 1.0);
vec3 lineCol = getLineColor(t, b);
float angle = topWavePosition.z * log(length(baseUv) + 1.0);
vec2 ruv = baseUv * rotate(angle);
ruv.x *= -1.0;
col += lineCol * wave(
ruv + vec2(topLineDistance * fi + topWavePosition.x, topWavePosition.y),
1.0 + 0.2 * fi,
baseUv,
mouseUv,
interactive
) * 0.1;
}
}
fragColor = vec4(col, 1.0);
}
void main() {
vec4 color = vec4(0.0);
mainImage(color, gl_FragCoord.xy);
gl_FragColor = color;
}
`;
const MAX_GRADIENT_STOPS = 8;
type WavePosition = {
x: number;
y: number;
rotate: number;
};
type FloatingLinesProps = {
linesGradient?: string[];
enabledWaves?: Array<'top' | 'middle' | 'bottom'>;
lineCount?: number | number[];
lineDistance?: number | number[];
topWavePosition?: WavePosition;
middleWavePosition?: WavePosition;
bottomWavePosition?: WavePosition;
animationSpeed?: number;
interactive?: boolean;
bendRadius?: number;
bendStrength?: number;
mouseDamping?: number;
parallax?: boolean;
parallaxStrength?: number;
mixBlendMode?: CSSProperties['mixBlendMode'];
};
const props = withDefaults(defineProps<FloatingLinesProps>(), {
enabledWaves: () => ['top', 'middle', 'bottom'],
lineCount: () => [6],
lineDistance: () => [5],
bottomWavePosition: () => ({ x: 2.0, y: -0.7, rotate: -1 }),
animationSpeed: 1,
interactive: true,
bendRadius: 5.0,
bendStrength: -0.5,
mouseDamping: 0.05,
parallax: true,
parallaxStrength: 0.2,
mixBlendMode: 'screen'
});
function hexToVec3(hex: string): Vector3 {
let value = hex.trim();
if (value.startsWith('#')) {
value = value.slice(1);
}
let r = 255;
let g = 255;
let b = 255;
if (value.length === 3) {
r = parseInt(value[0] + value[0], 16);
g = parseInt(value[1] + value[1], 16);
b = parseInt(value[2] + value[2], 16);
} else if (value.length === 6) {
r = parseInt(value.slice(0, 2), 16);
g = parseInt(value.slice(2, 4), 16);
b = parseInt(value.slice(4, 6), 16);
}
return new Vector3(r / 255, g / 255, b / 255);
}
const containerRef = useTemplateRef('containerRef');
const targetMouseRef = ref<Vector2>(new Vector2(-1000, -1000));
const currentMouseRef = ref<Vector2>(new Vector2(-1000, -1000));
const targetInfluenceRef = ref<number>(0);
const currentInfluenceRef = ref<number>(0);
const targetParallaxRef = ref<Vector2>(new Vector2(0, 0));
const currentParallaxRef = ref<Vector2>(new Vector2(0, 0));
let cleanup: (() => void) | null = null;
const setup = () => {
if (!containerRef.value) return;
const getLineCount = (waveType: 'top' | 'middle' | 'bottom'): number => {
if (typeof props.lineCount === 'number') return props.lineCount;
if (!props.enabledWaves.includes(waveType)) return 0;
const index = props.enabledWaves.indexOf(waveType);
return props.lineCount[index] ?? 6;
};
const getLineDistance = (waveType: 'top' | 'middle' | 'bottom'): number => {
if (typeof props.lineDistance === 'number') return props.lineDistance;
if (!props.enabledWaves.includes(waveType)) return 0.1;
const index = props.enabledWaves.indexOf(waveType);
return props.lineDistance[index] ?? 0.1;
};
const topLineCount = props.enabledWaves.includes('top') ? getLineCount('top') : 0;
const middleLineCount = props.enabledWaves.includes('middle') ? getLineCount('middle') : 0;
const bottomLineCount = props.enabledWaves.includes('bottom') ? getLineCount('bottom') : 0;
const topLineDistance = props.enabledWaves.includes('top') ? getLineDistance('top') * 0.01 : 0.01;
const middleLineDistance = props.enabledWaves.includes('middle') ? getLineDistance('middle') * 0.01 : 0.01;
const bottomLineDistance = props.enabledWaves.includes('bottom') ? getLineDistance('bottom') * 0.01 : 0.01;
const scene = new Scene();
const camera = new OrthographicCamera(-1, 1, 1, -1, 0, 1);
camera.position.z = 1;
const renderer = new WebGLRenderer({ antialias: true, alpha: false });
renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 2));
renderer.domElement.style.width = '100%';
renderer.domElement.style.height = '100%';
containerRef.value.appendChild(renderer.domElement);
const uniforms = {
iTime: { value: 0 },
iResolution: { value: new Vector3(1, 1, 1) },
animationSpeed: { value: props.animationSpeed },
enableTop: { value: props.enabledWaves.includes('top') },
enableMiddle: { value: props.enabledWaves.includes('middle') },
enableBottom: { value: props.enabledWaves.includes('bottom') },
topLineCount: { value: topLineCount },
middleLineCount: { value: middleLineCount },
bottomLineCount: { value: bottomLineCount },
topLineDistance: { value: topLineDistance },
middleLineDistance: { value: middleLineDistance },
bottomLineDistance: { value: bottomLineDistance },
topWavePosition: {
value: new Vector3(
props.topWavePosition?.x ?? 10.0,
props.topWavePosition?.y ?? 0.5,
props.topWavePosition?.rotate ?? -0.4
)
},
middleWavePosition: {
value: new Vector3(
props.middleWavePosition?.x ?? 5.0,
props.middleWavePosition?.y ?? 0.0,
props.middleWavePosition?.rotate ?? 0.2
)
},
bottomWavePosition: {
value: new Vector3(
props.bottomWavePosition?.x ?? 2.0,
props.bottomWavePosition?.y ?? -0.7,
props.bottomWavePosition?.rotate ?? 0.4
)
},
iMouse: { value: new Vector2(-1000, -1000) },
interactive: { value: props.interactive },
bendRadius: { value: props.bendRadius },
bendStrength: { value: props.bendStrength },
bendInfluence: { value: 0 },
parallax: { value: props.parallax },
parallaxStrength: { value: props.parallaxStrength },
parallaxOffset: { value: new Vector2(0, 0) },
lineGradient: {
value: Array.from({ length: MAX_GRADIENT_STOPS }, () => new Vector3(1, 1, 1))
},
lineGradientCount: { value: 0 }
};
if (props.linesGradient && props.linesGradient.length > 0) {
const stops = props.linesGradient.slice(0, MAX_GRADIENT_STOPS);
uniforms.lineGradientCount.value = stops.length;
stops.forEach((hex, i) => {
const color = hexToVec3(hex);
uniforms.lineGradient.value[i].set(color.x, color.y, color.z);
});
}
const material = new ShaderMaterial({
uniforms,
vertexShader,
fragmentShader
});
const geometry = new PlaneGeometry(2, 2);
const mesh = new Mesh(geometry, material);
scene.add(mesh);
const clock = new Clock();
const setSize = () => {
const el = containerRef.value!;
const width = el.clientWidth || 1;
const height = el.clientHeight || 1;
renderer.setSize(width, height, false);
const canvasWidth = renderer.domElement.width;
const canvasHeight = renderer.domElement.height;
uniforms.iResolution.value.set(canvasWidth, canvasHeight, 1);
};
setSize();
const ro = typeof ResizeObserver !== 'undefined' ? new ResizeObserver(setSize) : null;
if (ro && containerRef.value) {
ro.observe(containerRef.value);
}
const handlePointerMove = (event: PointerEvent) => {
const rect = renderer.domElement.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
const dpr = renderer.getPixelRatio();
targetMouseRef.value.set(x * dpr, (rect.height - y) * dpr);
targetInfluenceRef.value = 1.0;
if (props.parallax) {
const centerX = rect.width / 2;
const centerY = rect.height / 2;
const offsetX = (x - centerX) / rect.width;
const offsetY = -(y - centerY) / rect.height;
targetParallaxRef.value.set(offsetX * props.parallaxStrength, offsetY * props.parallaxStrength);
}
};
const handlePointerLeave = () => {
targetInfluenceRef.value = 0.0;
};
if (props.interactive) {
renderer.domElement.addEventListener('pointermove', handlePointerMove);
renderer.domElement.addEventListener('pointerleave', handlePointerLeave);
}
let raf = 0;
const renderLoop = () => {
uniforms.iTime.value = clock.getElapsedTime();
if (props.interactive) {
currentMouseRef.value.lerp(targetMouseRef.value, props.mouseDamping);
uniforms.iMouse.value.copy(currentMouseRef.value);
currentInfluenceRef.value += (targetInfluenceRef.value - currentInfluenceRef.value) * props.mouseDamping;
uniforms.bendInfluence.value = currentInfluenceRef.value;
}
if (props.parallax) {
currentParallaxRef.value.lerp(targetParallaxRef.value, props.mouseDamping);
uniforms.parallaxOffset.value.copy(currentParallaxRef.value);
}
renderer.render(scene, camera);
raf = requestAnimationFrame(renderLoop);
};
renderLoop();
cleanup = () => {
cancelAnimationFrame(raf);
if (ro && containerRef.value) {
ro.disconnect();
}
if (props.interactive) {
renderer.domElement.removeEventListener('pointermove', handlePointerMove);
renderer.domElement.removeEventListener('pointerleave', handlePointerLeave);
}
geometry.dispose();
material.dispose();
renderer.dispose();
if (renderer.domElement.parentElement) {
renderer.domElement.parentElement.removeChild(renderer.domElement);
}
};
};
onMounted(() => {
setup();
});
onBeforeUnmount(() => {
cleanup?.();
});
watch(
() => [
props.linesGradient,
props.enabledWaves,
props.lineCount,
props.lineDistance,
props.topWavePosition,
props.middleWavePosition,
props.bottomWavePosition,
props.animationSpeed,
props.interactive,
props.bendRadius,
props.bendStrength,
props.mouseDamping,
props.parallax,
props.parallaxStrength
],
() => {
cleanup?.();
setup();
},
{
deep: true
}
);
</script>
<template>
<div ref="containerRef" class="relative w-full h-full overflow-hidden floating-lines-container" :style="{
mixBlendMode: mixBlendMode
}" />
</template>

View File

@ -15,9 +15,10 @@
</div> </div>
</template> </template>
<script setup> <script setup lang="ts">
import { ref, computed, watch, onMounted } from 'vue'; import { ref, computed, watch, onMounted } from 'vue';
import { queryXmInfo } from '@/api/liswork/work/LisWork' import { queryXmInfo } from '@/api/liswork/work/LisWork'
// @ts-ignore
import { getFirstLetter } from '@/utils/pinyin.js'; // 引入拼音处理工具 import { getFirstLetter } from '@/utils/pinyin.js'; // 引入拼音处理工具
// 组件参数 // 组件参数
const props = defineProps({ const props = defineProps({
@ -55,7 +56,7 @@ const loadDictData = async () => {
}; };
const response = await queryXmInfo(requestParams); const response = await queryXmInfo(requestParams);
const rawData = response.data.map((item, index) => { const rawData = response.data.map((item: any, index: number) => {
return { return {
value: item.xmdh || `未知编码_${index}`, // 确保value存在 value: item.xmdh || `未知编码_${index}`, // 确保value存在
label: item.xmmc || `未知名称_${index}`, // 确保label存在 label: item.xmmc || `未知名称_${index}`, // 确保label存在
@ -64,7 +65,7 @@ const loadDictData = async () => {
}; };
}); });
// 为每个字典项添加简拼字段 // 为每个字典项添加简拼字段
dictData.value = (rawData || []).map(item => ({ dictData.value = (rawData || []).map((item: any) => ({
...item, ...item,
pinyin: getFirstLetter(item.label) // 新增pinyin字段存储简拼 pinyin: getFirstLetter(item.label) // 新增pinyin字段存储简拼
})); }));
@ -87,7 +88,7 @@ const filterDictData = () => {
return; return;
} }
filteredDictData.value = dictData.value.filter(item => { filteredDictData.value = dictData.value.filter((item: any) => {
// 1. 模糊搜索:匹配label(名称)或value(编码) // 1. 模糊搜索:匹配label(名称)或value(编码)
const matchLabel = item.label.toLowerCase().includes(key); const matchLabel = item.label.toLowerCase().includes(key);
const matchValue = String(item.value).toLowerCase().includes(key); const matchValue = String(item.value).toLowerCase().includes(key);
@ -123,7 +124,7 @@ const openDictSelector = async () => {
// 选择字典项 // 选择字典项
const selectItem = (item) => { const selectItem = (item: any) => {
emit('select', item); emit('select', item);
dialogVisible.value = false; dialogVisible.value = false;
}; };

View File

@ -1,20 +1,20 @@
<template> <template>
<div> <div>
<el-dialog v-model="visible" :title="title" :width="500" :close-on-click-modal="false" :draggable="true"> <el-dialog v-model="visible" :title="title" :width="500" :close-on-click-modal="false" :draggable="true">
<el-form ref="formRef" :model="formValue" label-width="100px"> <el-form ref="formRef" :model="formData" label-width="100px">
<!-- 用户代号 --> <!-- 用户代号 -->
<el-form-item label="用户代号:" prop="yhdh" :rules="[{ required: true, message: '请输入用户代号', trigger: 'change' }]"> <el-form-item label="用户代号:" prop="yhdh" :rules="[{ required: true, message: '请输入用户代号', trigger: 'change' }]">
<el-input ref="yhdhRef" v-model="formValue.yhdh" @change="handleChange" /> <el-input ref="yhdhRef" v-model="formData.yhdh" @change="handleChange" />
</el-form-item> </el-form-item>
<!-- 用户姓名 --> <!-- 用户姓名 -->
<el-form-item label="用户姓名:"> <el-form-item label="用户姓名:">
<el-input v-model="formValue.userName" disabled /> <el-input v-model="formData.userName" disabled />
</el-form-item> </el-form-item>
<!-- 密码输入 --> <!-- 密码输入 -->
<el-form-item label="密码:" prop="mm" :rules="[{ required: true, message: '请输入密码', trigger: 'change' }]"> <el-form-item label="密码:" prop="mm" :rules="[{ required: true, message: '请输入密码', trigger: 'change' }]">
<el-input v-model="formValue.mm" type="password" @keyup.enter="handleConfirm" /> <el-input v-model="formData.mm" type="password" @keyup.enter="handleConfirm" />
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -36,14 +36,6 @@ interface UserInfo {
nickName: string, nickName: string,
} }
const props = defineProps({ const props = defineProps({
formValue: {
type: Object,
default: {
yhdh: '',
userName: '',
mm: '',
}
},
labPatKey: { labPatKey: {
type: Object, type: Object,
@ -61,7 +53,11 @@ const props = defineProps({
}); });
const visible = ref(false); const visible = ref(false);
// 表单数据 // 表单数据
const formData = ref({
yhdh: '',
userName: '',
mm: '',
})
const formRef = ref(); const formRef = ref();
const yhdhRef = ref(); const yhdhRef = ref();
@ -74,7 +70,7 @@ const open = () => {
}); });
} }
const emit = defineEmits(["confirm", "cancel",]); const emit = defineEmits(["confirm"]);
// 处理确定按钮点击 // 处理确定按钮点击
const handleConfirm = async () => { const handleConfirm = async () => {
if (!formRef.value) return; if (!formRef.value) return;
@ -82,9 +78,9 @@ const handleConfirm = async () => {
// 表单验证 // 表单验证
const valid = await formRef.value.validate(); const valid = await formRef.value.validate();
if (valid) { if (valid) {
checkYsUser({ ...props.formValue, ...props.labPatKey }).then((res: any) => { checkYsUser({ ...formData.value, ...props.labPatKey }).then((res: any) => {
if (res.code == 0) { if (res.code == 0) {
emit('confirm', props.formValue) emit('confirm', formData.value)
} }
}) })
@ -93,14 +89,18 @@ const handleConfirm = async () => {
// 处理取消按钮点击 // 处理取消按钮点击
const cancel = () => { const cancel = () => {
formData.value = {
yhdh: '',
userName: '',
mm: '',
}
formRef.value?.resetFields(); formRef.value?.resetFields();
visible.value = false visible.value = false
emit('cancel',)
}; };
const handleChange = (value: string) => { const handleChange = (value: string) => {
props.formValue.userName = props.userList.find((item: any) => item.userName == value)?.nickName formData.value.userName = props.userList.find((item: any) => item.userName == value)?.nickName || value
}; };

View File

@ -217,9 +217,9 @@ const handleRowClick = (row: any) => {
const myEcharts = ref() const myEcharts = ref()
const getEcharts = (data: any) => { const getEcharts = (data: any) => {
const periods = ['nine', 'eight', 'seven', 'six', 'five', 'four', 'three', 'two', 'one', 'first'] const periods = ['nine', 'eight', 'seven', 'six', 'five', 'four', 'three', 'two', 'one', 'first']
if (!data) return
const xData = periods.map(period => { return data[`${period}Date`] }).filter(Boolean) //过滤掉空值 const xData = periods.map(period => { return data[`${period}Date`] })?.filter(Boolean) //过滤掉空值
const yData = periods.map(period => { return data[`${period}Csjg`] }).filter(Boolean) const yData = periods.map(period => { return data[`${period}Csjg`] })?.filter(Boolean)
const Intance = echarts.init(myEcharts.value); const Intance = echarts.init(myEcharts.value);

View File

@ -27,8 +27,8 @@
<el-col :span="6"> <el-col :span="6">
<el-form-item label="日期:" prop="jyrq"> <el-form-item label="日期:" prop="jyrq">
<el-date-picker v-model="ybJyrq" type="date" label-width="1.25rem" placeholder="检验日期" <el-date-picker v-model="ybJyrq" type="date" label-width="1.25rem" placeholder="检验日期"
value-format="YYYY-MM-DD" :clearable="false" @change="jyrqChange" value-format="YYYY-MM-DD" :clearable="false" @change="jyrqChange" ref="datePickerRef"
style="width:100%"></el-date-picker> style="width:100%" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
@ -65,12 +65,13 @@
<el-col :span="16"> <el-col :span="16">
<el-tabs v-model="activeName" type="card" class="demo-tabs"> <el-tabs v-model="activeName" type="card" class="demo-tabs">
<el-tab-pane label="鉴定(终报)结果" name="first"> <el-tab-pane label="鉴定(终报)结果" name="first">
<ZbReport ref="labResultRef" v-model:labPat="labInfo" :labPatKey="queryParams" <ZbReport ref="labResultRef" v-model:labPat="labPat" :labPatKey="queryParams"
@update:labPatKey="queryParams = $event" :dictData="dictData" :labResutsData="zbLabResuts" @update:labPatKey="queryParams = $event" :dictData="dictData" :labResutsData="zbLabResuts"
@fetchLabResults="resultsHandle" @changeStatus="changeStatus" @previewHandle="previewHandle" /> :userList="userList" @fetchLabResults="resultsHandle" @changeStatus="changeStatus"
@previewHandle="previewHandle" />
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="初级和二级报告" name="second"> <el-tab-pane label="初级和二级报告" name="second">
<CbReport v-model:labPat="labInfo" :labPatKey="queryParams" @update:labPatKey="queryParams = $event" <CbReport v-model:labPat="labPat" :labPatKey="queryParams" @update:labPatKey="queryParams = $event"
:instrdComOpt="instrdComOpt" :dictData="dictData" @changeStatus="changeStatus" :userList="userList" :instrdComOpt="instrdComOpt" :dictData="dictData" @changeStatus="changeStatus" :userList="userList"
@previewHandle="previewHandle" /> @previewHandle="previewHandle" />
</el-tab-pane> </el-tab-pane>
@ -78,7 +79,7 @@
<Pyj :labPat="labPat" :labPatKey="queryParams" :userList="userList" /> <Pyj :labPat="labPat" :labPatKey="queryParams" :userList="userList" />
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="操作记录" name="fourth"> <el-tab-pane label="操作记录" name="fourth">
<Record :labPat="labInfo" :labPatKey="queryParams" /> <Record :labPat="labPat" :labPatKey="queryParams" />
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</el-col> </el-col>
@ -120,10 +121,10 @@
</el-radio> </el-radio>
</el-radio-group> </el-radio-group>
<el-date-picker v-model="queryParams.jyrq" type="date" :size="aotuSize" @change="fetchlabPatList" <el-date-picker v-model="queryParams.jyrq" type="date" :size="aotuSize" @change="fetchlabPatList"
style="width: 9.375rem;" /> value-format="YYYY-MM-DD" style="width: 9.375rem;" />
</div> </div>
<LabPatList ref="labPatListRef" :labPatList="labPatList" :loading="loading" @select="selectJob" <LabPatList ref="labPatListRef" :labPatList="labPatList" :loading="loading" @select="selectJob"
:tableKey="queryParams" :dictData="dictData" @search="searchJobs" /> :tableKey="{ ...queryParams, jyrq: ybJyrq }" :dictData="dictData" @search="searchJobs" />
<div class="button-group"> <div class="button-group">
<el-pagination v-model:current-page="queryParams.pageNum" v-model:page-size="queryParams.pageSize" <el-pagination v-model:current-page="queryParams.pageNum" v-model:page-size="queryParams.pageSize"
@ -134,8 +135,8 @@
</template> </template>
<component :is="activeTabName" :queryParams="queryParams" :dictData="dictData" :instrOptions="instrOptions" <component :is="activeTabName" :queryParams="{ ...queryParams, jyrq: ybJyrq }" :dictData="dictData"
@fetchResults="fetchLabResults" :tablekey="queryParams" /> :instrOptions="instrOptions" @fetchResults="fetchLabResults" :tablekey="labPat" />
</div> </div>
</div> </div>
@ -179,7 +180,7 @@ import Record from './labresult/record.vue';
// @ts-ignore // @ts-ignore
import { comDict } from '@/utils/dict' import { comDict } from '@/utils/dict'
import { queryLabResults, loadDefault, queryLabPat, instrdconfig, delSample, getGroupInstrdList, checkuser, updateLabPat } from "@/api/liswork/work/LisWork"; import { queryLabResults, loadDefault, queryLabPat, instrdconfig, delSample, getGroupInstrdList, checkuser, updateLabPat } from "@/api/liswork/work/LisWork";
import { wswsamplelistpage, sampleMedInfo } from "@/api/liswork/micro/index"; import { wswsamplelistpage, sampleMedInfo, changepatjyrq } from "@/api/liswork/micro/index";
import { getComDicts, queryComDictListService } from "@/api/liswork/dict/ComDict"; import { getComDicts, queryComDictListService } from "@/api/liswork/dict/ComDict";
import { ElMessage, ElMessageBox } from "element-plus"; import { ElMessage, ElMessageBox } from "element-plus";
import BatchCode from '../work/components/batchCode.vue'; import BatchCode from '../work/components/batchCode.vue';
@ -271,7 +272,9 @@ watch(() => labPat.value, (newValue) => {
}, { deep: true }); }, { deep: true });
const checkUserRef = ref() const checkUserRef = ref()
const datePickerRef = ref()
const jyrqChange = (val: string) => { const jyrqChange = (val: string) => {
datePickerRef.value?.blur();
ElMessageBox.confirm( ElMessageBox.confirm(
`确定修改当前样本检验日期?`, `确定修改当前样本检验日期?`,
'提示', '提示',
@ -288,6 +291,7 @@ const jyrqChange = (val: string) => {
} }
}).catch(() => { }).catch(() => {
fetchLabPat(); fetchLabPat();
datePickerRef.value?.blur();
}) })
}; };
@ -299,6 +303,7 @@ const handleCheckUserConfirm = (info: { yhdh: string, mm: string }) => {
updateJyrq() updateJyrq()
} else { } else {
fetchLabPat(); fetchLabPat();
datePickerRef.value?.blur();
} }
}) })
}; };
@ -309,7 +314,19 @@ const checkUserCancel = () => {
// 更新检验日期 // 更新检验日期
const updateJyrq = () => { const updateJyrq = () => {
// updateLabPat({ ...queryParams.value, ...labPat.value }) changepatjyrq({ ...queryParams.value, jyrq: ybJyrq.value }).then((response: any) => {
if (response.code == 0) {
ElMessage.success('检验日期修改成功');
changeStatus(
{
jyrq: ybJyrq.value,
ybh: labPat.value.ybh,
yq: labPat.value.yq
}, false
)
datePickerRef.value?.blur();
}
});
}; };
// 模糊查询 // 模糊查询
@ -475,22 +492,22 @@ const lastRow: any = ref({})
// 批量扫码ybh同步样本编号 // 批量扫码ybh同步样本编号
const ybhChangeTb = (val: string) => { const ybhChangeTb = (val: string) => {
// console.log('val==>', val); // console.log('val==>', val);
labInfo.value.ybh = val labPat.value.ybh = val
queryParams.value.ybh = val queryParams.value.ybh = val
handleQuery(); handleQuery();
} }
const handleQuery = () => { const handleQuery = () => {
if (!labPatList.value.length) return if (!labPatList.value.length) return
if (!labInfo.value.ybh) { if (!labPat.value.ybh) {
highlightRowIndex.value = -1; highlightRowIndex.value = -1;
ElMessage.warning('请输入样本编号') ElMessage.warning('请输入样本编号')
labInfo.value.ybh = lastRow.value.ybh labPat.value.ybh = lastRow.value.ybh
queryParams.value.ybh = lastRow.value.ybh queryParams.value.ybh = lastRow.value.ybh
return; return;
} }
// queryParams.value = { ...queryParams.value }; // queryParams.value = { ...queryParams.value };
// 查找匹配的行 // 查找匹配的行
const matchedIndex = labPatList.value.findIndex((item: any) => item.ybh == labInfo.value.ybh); const matchedIndex = labPatList.value.findIndex((item: any) => item.ybh == labPat.value.ybh);
const row = labPatList.value[matchedIndex] const row = labPatList.value[matchedIndex]
if (matchedIndex !== -1) { if (matchedIndex !== -1) {
@ -524,15 +541,15 @@ const handleCreate = () => {
// 删除样本 // 删除样本
const delSampleHd = () => { const delSampleHd = () => {
if (labInfo.value.jgbz == '2') return ElMessage.warning('标本已审核,不能删除!') if (labPat.value.jgbz == '2') return ElMessage.warning('标本已审核,不能删除!')
const data = { const data = {
jyrq: labInfo.value.jyrq, jyrq: labPat.value.jyrq,
yq: labInfo.value.yq.trim(), yq: labPat.value.yq.trim(),
ybh: labInfo.value.ybh, ybh: labPat.value.ybh,
} }
ElMessageBox.confirm( ElMessageBox.confirm(
`确定删除当前${labInfo.value.ybh}号标本?`, `确定删除当前${labPat.value.ybh}号标本?`,
'提示', '提示',
{ {
confirmButtonText: '确定', confirmButtonText: '确定',
@ -544,7 +561,7 @@ const delSampleHd = () => {
delSample(data).then((res: any) => { delSample(data).then((res: any) => {
if (res.code == 0) { if (res.code == 0) {
ElMessage.success('删除成功') ElMessage.success('删除成功')
labPatList.value = labPatList.value.filter((item: any) => item.ybh != labInfo.value.ybh) labPatList.value = labPatList.value.filter((item: any) => item.ybh != labPat.value.ybh)
// 删除跳当前页面下一个样本 // 删除跳当前页面下一个样本
// handleNext() // handleNext()
if (highlightRowIndex.value > labPatList.value.length - 1) { if (highlightRowIndex.value > labPatList.value.length - 1) {
@ -564,8 +581,7 @@ const delSampleHd = () => {
// 上一个样本 // 上一个样本
const handlePrev = () => { const handlePrev = () => {
if (!lbFlag.value) { if (!lbFlag.value) {
const ybh = getPreviousNumber(labInfo.value.ybh) as string; const ybh = getPreviousNumber(labPat.value.ybh) as string;
labInfo.value.ybh = ybh;
queryParams.value.ybh = ybh; queryParams.value.ybh = ybh;
const index = labPatList.value.findIndex((item: any) => item.ybh == ybh) const index = labPatList.value.findIndex((item: any) => item.ybh == ybh)
if (index !== -1) { if (index !== -1) {
@ -594,8 +610,7 @@ const handlePrev = () => {
// 下一个样本 // 下一个样本
const handleNext = () => { const handleNext = () => {
if (!lbFlag.value) { if (!lbFlag.value) {
const ybh = getNextNumber(labInfo.value.ybh) as string; const ybh = getNextNumber(labPat.value.ybh) as string;
labInfo.value.ybh = ybh;
queryParams.value.ybh = ybh; queryParams.value.ybh = ybh;
const index = labPatList.value.findIndex((item: any) => item.ybh == ybh) const index = labPatList.value.findIndex((item: any) => item.ybh == ybh)
if (index !== -1) { if (index !== -1) {
@ -617,15 +632,13 @@ const handleNext = () => {
} }
selectJob(row); selectJob(row);
} else { } else {
labInfo.value.ybh = getNextNumber(labInfo.value.ybh) as string; queryParams.value.ybh = labPat.value.ybh;
queryParams.value.ybh = labInfo.value.ybh;
handleCreate(); handleCreate();
} }
} }
} }
// 最后一个样本 // 最后一个样本
const handleLast = () => { const handleLast = () => {
labInfo.value.ybh = labPatList.value[labPatList.value.length - 1].ybh;
queryParams.value.ybh = labPatList.value[labPatList.value.length - 1].ybh; queryParams.value.ybh = labPatList.value[labPatList.value.length - 1].ybh;
handleNext(); handleNext();
} }
@ -693,10 +706,6 @@ const handleCurrentChange = (page: number) => {
//载入样本列表(右边labpatlist.vue组件) //载入样本列表(右边labpatlist.vue组件)
const fetchlabPatList = () => { const fetchlabPatList = () => {
// if (!queryParams.value.jyrq) {
// queryParams.value.jyrq = lastRow.value.jyrq
// return ElMessage.warning('请选择检验日期')
// }
loading.value = true; loading.value = true;
wswsamplelistpage(queryParams.value).then((res: any) => { wswsamplelistpage(queryParams.value).then((res: any) => {
if (res.code == 200) { if (res.code == 200) {

View File

@ -102,7 +102,6 @@ const handleCsjgEnter = (row: any) => {
const handleInputFocus = (row: any) => { const handleInputFocus = (row: any) => {
updateItem.value = row; updateItem.value = row;
pyjRef.value.openDictSelector(); pyjRef.value.openDictSelector();
console.log('row', row);
} }
const selectItem = (item: any) => { const selectItem = (item: any) => {
if (updateItem.value) { if (updateItem.value) {
@ -117,7 +116,6 @@ const selectItem = (item: any) => {
} }
}); });
} else { } else {
console.log('labPat==>', labPat.value);
const data = { const data = {
mediumno: item.value, mediumno: item.value,
mediumname: item.label, mediumname: item.label,

View File

@ -10,46 +10,48 @@
plain @click="handleBatchDelete">删除</el-button> plain @click="handleBatchDelete">删除</el-button>
<el-button class="btn_green btns_box" :size="autoSize" @click="zhHandel">组合项目</el-button> <el-button class="btn_green btns_box" :size="autoSize" @click="zhHandel">组合项目</el-button>
</div> </div>
<CustomTable ref="tableRef" :data="tableData" :columns="columns" :config="tableConfig" :enable-column-drag="true" <ContextMenu :items="contextMenuItems" @select="handleMenuSelect">
@column-drag-end="handleColumnDragEnd" @row-click="rowHandle"> <CustomTable ref="tableRef" :data="tableData" :columns="columns" :config="tableConfig" :enable-column-drag="true"
<template #xmdh="{ column }"> @column-drag-end="handleColumnDragEnd" @row-click="rowHandle">
细菌/结果({{ tableData.length }})项 <template #xmdh="{ column }">
</template> 细菌/结果({{ tableData.length }})项
<template #od="{ row }"> </template>
<el-input v-model="row.od" v-if="labPat.jgbz == 0 || labPat.jgbz == null" size="small" <template #od="{ row }">
class="full-width-input foucs-input" @change="handleCsjgEnter(row)" /> <el-input v-model="row.od" v-if="labPat.jgbz == 0 || labPat.jgbz == null" size="small"
<span v-else>{{ row.od }}</span> class="full-width-input foucs-input" @change="handleCsjgEnter(row)" />
</template> <span v-else>{{ row.od }}</span>
<template #csjg="{ row }"> </template>
<el-input v-model="row.csjg" v-if="labPat.jgbz == 0 || labPat.jgbz == null" size="small" <template #csjg="{ row }">
class="full-width-input" @change="handleCsjgEnter(row)" @dblclick="handleInputFocus(row)" /> <el-input v-model="row.csjg" v-if="labPat.jgbz == 0 || labPat.jgbz == null" size="small"
<span v-else>{{ row.csjg }}</span> class="full-width-input" @change="handleCsjgEnter(row)" @dblclick="handleInputFocus(row)" />
</template> <span v-else>{{ row.csjg }}</span>
<template #jgbz="{ row }"> </template>
<el-select v-model="row.jgbz" class="full-width-input" v-if="labPat.jgbz == 0 || labPat.jgbz == null" <template #jgbz="{ row }">
placeholder="" @change="handleCsjgEnter(row)"> <el-select v-model="row.jgbz" class="full-width-input" v-if="labPat.jgbz == 0 || labPat.jgbz == null"
<el-option label="阳性" value="P" /> placeholder="" @change="handleCsjgEnter(row)">
<el-option label="阴性" value="N" /> <el-option label="阳性" value="P" />
</el-select> <el-option label="阴性" value="N" />
<span v-else> {{ formatJgbz(row.jgbz) }}</span> </el-select>
</template> <span v-else> {{ formatJgbz(row.jgbz) }}</span>
<template #cutoff="{ row }"> </template>
<el-input v-model="row.cutoff" v-if="labPat.jgbz == 0 || labPat.jgbz == null" size="small" <template #cutoff="{ row }">
class="full-width-input" @change="handleCsjgEnter(row)" /> <el-input v-model="row.cutoff" v-if="labPat.jgbz == 0 || labPat.jgbz == null" size="small"
<span v-else>{{ row.cutoff }}</span> class="full-width-input" @change="handleCsjgEnter(row)" />
</template> <span v-else>{{ row.cutoff }}</span>
<template #alarm_flag="{ row }"> </template>
<el-select v-model="row.alarm_flag" class="full-width-input" v-if="labPat.jgbz == 0 || labPat.jgbz == null" <template #alarm_flag="{ row }">
placeholder="" @change="handleCsjgEnter(row)"> <el-select v-model="row.alarm_flag" class="full-width-input" v-if="labPat.jgbz == 0 || labPat.jgbz == null"
<el-option label="危急值" value="H" /> placeholder="" @change="handleCsjgEnter(row)">
<el-option label="无" value="" /> <el-option label="危急值" value="H" />
</el-select> <el-option label="无" value="" />
<span v-else> {{ row.alarm_flag == 'H' ? '危急值' : '' }}</span> </el-select>
</template> <span v-else> {{ row.alarm_flag == 'H' ? '危急值' : '' }}</span>
<template #germclass="{ row }"> </template>
{{ formatDict(row.germclass, 'germclass') }} <template #germclass="{ row }">
</template> {{ formatDict(row.germclass, 'germclass') }}
</CustomTable> </template>
</CustomTable>
</ContextMenu>
<div class="tabs_btns"> <div class="tabs_btns">
<el-tabs v-model="activeName2" type="card" class="demo-tabs" :size="autoSize"> <el-tabs v-model="activeName2" type="card" class="demo-tabs" :size="autoSize">
<el-tab-pane label="药敏结果" name="first"> <el-tab-pane label="药敏结果" name="first">
@ -152,6 +154,22 @@
<!-- 危急值结果上报 --> <!-- 危急值结果上报 -->
<UploadWarning ref="uploadwarningRef" :warningMsgdata="warningMsgdata" :tableKey="labPatKey" <UploadWarning ref="uploadwarningRef" :warningMsgdata="warningMsgdata" :tableKey="labPatKey"
@onupload="shHandleCheck" /> @onupload="shHandleCheck" />
<!-- 用户校验 -->
<userVerification ref="formRef" :title="verTitle" :userList="userList" @confirm="handleConfirm" />
<!-- 合并当前病人其他结果 -->
<MergeResults ref="mergeRef" :tableKey="{ ...labPatKey, jyrq: labPat.jyrq }" :dictData="dictData" />
<!-- 查看备份数据 -->
<ViewBackup ref="backRef" :tableKey="{ ...labPatKey, jyrq: labPat.jyrq }" :userList="userList"
:dictData="dictData" />
<!-- 双工流水线 -->
<DlDialog ref="dlRef" :tableKey="{ ...labPatKey, jyrq: labPat.jyrq }" :dictData="dictData" />
<!-- 未建项目结果 -->
<BuiltDialog ref="builtRef" :tableKey="{ ...labPatKey, jyrq: labPat.jyrq }" @clearPro="clearProHandle" />
</div> </div>
</template> </template>
@ -162,7 +180,11 @@ import {
getresultmedList, savetestResult, changeresult, saveresult, newresult, getmeddictList, savemedresult, getresultmedList, savetestResult, changeresult, saveresult, newresult, getmeddictList, savemedresult,
savemedresultall, deletemedresult, getmedgroupMbList savemedresultall, deletemedresult, getmedgroupMbList
} from '@/api/liswork/micro/index'; } from '@/api/liswork/micro/index';
import { check2, uncheck2, unconfirmlog, checkuser, deleteresult, queryXmVal, setinputmdl, } from "@/api/liswork/work/LisWork"; import {
check2, uncheck2, unconfirmlog, checkuser, deleteresult, queryXmVal, setinputmdl, clearPrintflag,
clearnotComplete, emrquery, allPatquery, lockSample, unLockSample,
printListwork,
} from "@/api/liswork/work/LisWork";
import { useCommonStore } from "@/store/modules/commonStore"; import { useCommonStore } from "@/store/modules/commonStore";
import CheckUser from "../../work/components/CheckUser.vue"; import CheckUser from "../../work/components/CheckUser.vue";
import Unconfirmlog from "../../work/components/unconfirmlog.vue"; import Unconfirmlog from "../../work/components/unconfirmlog.vue";
@ -179,7 +201,13 @@ import { ElMessage, ElMessageBox } from "element-plus";
import emitter from "@/utils/mitt"; import emitter from "@/utils/mitt";
const autoSize = classCom.useAutoSize(); const autoSize = classCom.useAutoSize();
import { LabResultItem, ymTableDataItem } from '@/types/index'; import { LabResultItem, ymTableDataItem } from '@/types/index';
import ContextMenu from "@/components/contextMenu/index.vue";
import { ContextMenuItem } from '@/types/index'
import BuiltDialog from "../../work/components/builtDialog.vue"
import ViewBackup from "../../work/components/viewBackup.vue"
import userVerification from "@/components/userVerification/index.vue";
import DlDialog from "../../work/components/dlDialog.vue";
import MergeResults from "../../work/components/mergeResults.vue";
const props = defineProps({ const props = defineProps({
labPat: { labPat: {
@ -198,6 +226,10 @@ const props = defineProps({
dictData: { dictData: {
type: Object, type: Object,
default: () => { } default: () => { }
},
userList: {
type: Array as PropType<any[]>,
default: () => []
} }
}); });
const { labPat, labPatKey, labResutsData, dictData } = toRefs(props); const { labPat, labPatKey, labResutsData, dictData } = toRefs(props);
@ -249,8 +281,6 @@ const CellStyleHd = ({ row, column, rowIndex, columnIndex }: {
if (column.label == "检验结果" && row.jgbz == "Q") { if (column.label == "检验结果" && row.jgbz == "Q") {
return { background: '#ffff80 !important', color: '#606266' }; return { background: '#ffff80 !important', color: '#606266' };
} }
if (column.label == "阴阳性" && row.jgbz == "H") { if (column.label == "阴阳性" && row.jgbz == "H") {
return { background: '#ffc0c0 !important', color: '#606266' }; return { background: '#ffc0c0 !important', color: '#606266' };
} }
@ -276,11 +306,206 @@ const handleColumnDragEnd = (data: any) => {
columns.value = data.columns; columns.value = data.columns;
} }
// 右键菜单配置
const contextMenuItems = computed<ContextMenuItem[]>(() => [
{ label: '打印预览', action: 'view', shortcut: 'V', },
{ label: 'PDF报告预览', action: 'bgyl', shortcut: 'P', },
{ label: '合并病人当前其他结果', action: 'merge', shortcut: 'B', },
{ type: 'divider' },
{ label: '锁定报告', action: 'Lock', shortcut: 'L', },
{ label: '解除报告锁定', action: 'lift', shortcut: 'W', },
{ type: 'divider' },
// { label: '删除记录', action: 'delete', danger: true, shortcut: 'd', },
{ label: '查看电子病历', action: 'emrquery', shortcut: 'E', },
{ label: '查看360全景视图', action: 'patquery', shortcut: 'Y', },
{ label: '查看备份数据', action: 'viewbackup', shortcut: 'P', },
{ label: '双工流水线', action: 'datalink', shortcut: 'F', },
{ type: 'divider' },
{ label: '解除审核', action: 'unblock', shortcut: 'C', },
{ label: '清除打印标志', action: 'clearPrint', shortcut: 'U', },
{ label: '清除所有未做项目', action: 'clearPro', shortcut: 'T', },
{ type: 'divider' },
{ label: '未建项目结果', action: 'unbuilt', shortcut: 'N', },
]);
// 处理菜单选择
const handleMenuSelect = (item: any) => {
switch (item.action) {
case 'view':
previewHandle(1) //打印预览
break;
case 'bgyl':
previewHandle(2) //PDF报告预览
break;
case 'merge':
mergeHandle()
// alert(`合并病人当前其他结果`);
break;
case 'Lock':
lockHandle(); //锁定
break;
case 'lift':
unlockHandle() //解锁
break;
case 'emrquery':
emrqueryHandle() //电子病历查询
break;
case 'patquery':
patqueryHandle() //360视图
break;
case 'viewbackup':
viewbackupHandle() //查看备份数据
break;
case 'datalink':
datalinkHandle() //流水线
break;
case 'unblock':
handleCheck(3) //解除审核
break;
case 'clearPrint':
clearPrintHandle() //清除打印标志
break;
case 'clearPro':
clearProHandle() //清除所有未做项目
break;
case 'unbuilt':
unbuiltHandle() //未建项目结果
break;
case 'delete':
if (confirm(`确定要删除患者的记录吗?`)) {
}
break;
}
};
const previewHandle = (type: number) => { //1 打印预览 2 PDF报告预览
const data = {
jyrq: labPat.value.jyrq,
yq: labPat.value.yq,
ybh: labPat.value.ybh,
sqh: labPat.value.sqh
}
printListwork(data).then((res: any) => {
if (res.code == 0) {
if (type == 1) {
classCom.printBase64PDF(res.data)
} else {
emits('previewHandle', res.data);
}
}
})
};
const mergeRef = ref()
const mergeHandle = () => {
mergeRef.value.open()
};
const formRef = ref();
const verTitle = ref('请输入锁定人员账号密码')
const lockType = ref(1)
// 锁定报告
const lockHandle = () => {
if (props.labPat.jgbz != 0) return ElMessage.warning('样本已审核,不能锁定!')
lockType.value = 1
formRef.value.open()
verTitle.value = '请输入锁定人员账号密码'
}
// 解除锁定报告
const unlockHandle = () => {
if (props.labPat.jgbz != 5) return ElMessage.warning('目标标本未锁定,不可解除锁定!')
lockType.value = 2
verTitle.value = '请输入解除锁定人员账号密码'
formRef.value.open()
}
// 锁定样本
const handleConfirm = (data: { yhdh: string, userName: string, mm: string }) => {
const obj = {
...labPatKey.value,
jyrq: labPat.value.jyrq,
yhdh: data.yhdh,
}
emits('update:labPatKey', {
...labPatKey.value,
yhdh: data.yhdh,
});
if (lockType.value == 1) {
lockSample(obj).then((res: any) => {
if (res.code == 0) {
formRef.value?.cancel()
ElMessage.success(res.msg)
emits('changeStatus', labPat.value)
}
});
} else {
unLockSample(obj).then((res: any) => {
if (res.code == 0) {
formRef.value?.cancel()
ElMessage.success(res.msg)
emits('changeStatus', labPat.value)
}
});
}
}
const emrqueryHandle = () => {
emrquery({ ...labPatKey.value, jyrq: labPat.value.jyrq }).then((res: any) => {
if (res.data) {
window.open(res.data)
}
})
};
const patqueryHandle = () => {
allPatquery({ ...labPatKey.value, jyrq: labPat.value.jyrq }).then((res: any) => {
if (res.data) {
window.open(res.data)
}
})
};
const dlRef = ref()
const datalinkHandle = () => {
dlRef.value.open()
};
const backRef = ref()
const viewbackupHandle = () => {
backRef.value.openDialog()
};
const builtRef = ref()
const unbuiltHandle = () => {
builtRef.value.open()
};
const clearPrintHandle = () => {
clearPrintflag({ ...labPatKey.value, jyrq: labPat.value.jyrq }).then((res: any) => {
if (res.code == 0) {
emits('changeStatus', labPat.value)
}
})
};
const clearProHandle = () => {
clearnotComplete({ ...labPatKey.value, jyrq: labPat.value.jyrq }).then((res: any) => {
if (res.code == 0) {
emits('fetchLabResults')
}
})
};
const reasonText = ref(''); const reasonText = ref('');
const warningMsgdata = ref(''); const warningMsgdata = ref('');
const checktitle = ref(''); const checktitle = ref('');
const checkUserRef = ref(); const checkUserRef = ref();
const runnextstepname = ref(-1); const runnextstepname = ref(-1); // 审核类型
const handleCheck = (checkType: number) => { const handleCheck = (checkType: number) => {
runnextstepname.value = checkType runnextstepname.value = checkType
labPatKey.value.problemId = 0; labPatKey.value.problemId = 0;
@ -299,7 +524,10 @@ const handleCheckUserConfirm = (info: { yhdh: string, mm: string }) => {
...labPatKey.value, ...labPatKey.value,
yhdh: info.yhdh yhdh: info.yhdh
}); });
proceedCheck(runnextstepname.value) // 异步处理 等待yhdh数据更新
setTimeout(() => {
proceedCheck(runnextstepname.value)
}, 100);
} }
}) })
} }
@ -320,7 +548,7 @@ const proceedCheck = (type: number) => {
} }
const uploadwarningRef = ref(); const uploadwarningRef = ref();
const shHandleCheck = () => { const shHandleCheck = () => {
check2({ ...labPatKey.value, jyrq: labPat.value.jyrq, yhdh: props.labPat.yhdh }).then((res: any) => { check2({ ...labPatKey.value, jyrq: labPat.value.jyrq }).then((res: any) => {
emits("changeStatus", props.labPat); emits("changeStatus", props.labPat);
if (res.code == "4" && res.problemId === 4) { if (res.code == "4" && res.problemId === 4) {
labPatKey.value.problemId = res.problemId; labPatKey.value.problemId = res.problemId;
@ -332,7 +560,7 @@ const shHandleCheck = () => {
const unconfirmlogRef = ref(); const unconfirmlogRef = ref();
const unShHandle = () => { const unShHandle = () => {
uncheck2({ ...labPatKey.value, jyrq: labPat.value.jyrq, yhdh: props.labPat.yhdh }).then((res: any) => { uncheck2({ ...labPatKey.value, jyrq: labPat.value.jyrq }).then((res: any) => {
if (res.code == "4") { if (res.code == "4") {
labPatKey.value.problemId = res.problemId; labPatKey.value.problemId = res.problemId;
reasonText.value = res.msg; reasonText.value = res.msg;
@ -342,10 +570,6 @@ const unShHandle = () => {
}) })
}; };
const itemDictRef = ref(); const itemDictRef = ref();
const openItemDictDialog = () => { const openItemDictDialog = () => {
itemDictRef.value.openDictSelector(); itemDictRef.value.openDictSelector();
@ -706,7 +930,6 @@ const delMed = () => {
ymselectedRows.value = []; ymselectedRows.value = [];
} }
const medSelect = (row: any) => { const medSelect = (row: any) => {
console.log('row==>', row);
const ymFlag = tableData.value.some((item: any) => item.ywdh === row.value); const ymFlag = tableData.value.some((item: any) => item.ywdh === row.value);
if (ymFlag) return ElMessage.warning(`抗生素【${row.label}】已存在`); if (ymFlag) return ElMessage.warning(`抗生素【${row.label}】已存在`);
// 1. 构造新增行数据 // 1. 构造新增行数据

View File

@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<el-dialog v-model="checkShow" :title="title" width="500" :close-on-click-modal="false" :draggable="true" <el-dialog v-model="checkShow" :title="title" width="500" :close-on-click-modal="false" :draggable="true"
@close="handleCancel"> @close="close">
<el-form ref="ruleFormRef" style="max-width: 600px" :model="ruleForm" :rules="rules" label-width="auto"> <el-form ref="ruleFormRef" style="max-width: 600px" :model="ruleForm" :rules="rules" label-width="auto">
<el-form-item label="用户工号:" prop="yhdh"> <el-form-item label="用户工号:" prop="yhdh">
<el-input ref="yhdhRef" v-model.trim="ruleForm.yhdh" placeholder="请输入用户工号" maxlength="20" <el-input ref="yhdhRef" v-model.trim="ruleForm.yhdh" placeholder="请输入用户工号" maxlength="20"
@ -70,6 +70,7 @@ const rules = ref(
const yhdhRef = ref(); const yhdhRef = ref();
const open = () => { const open = () => {
checkShow.value = true; checkShow.value = true;
flag.value = true;
nextTick(() => { nextTick(() => {
setTimeout(() => { setTimeout(() => {
yhdhRef.value.focus(); yhdhRef.value.focus();
@ -78,11 +79,13 @@ const open = () => {
}; };
const checkShow = ref(false); const checkShow = ref(false);
const ruleFormRef = ref(); const ruleFormRef = ref();
const flag = ref(true);
// 处理确认验证 // 处理确认验证
const handleConfirm = () => { const handleConfirm = () => {
ruleFormRef.value.validate((valid: boolean) => { ruleFormRef.value.validate((valid: boolean) => {
if (valid) { if (valid) {
emit('onConfirm', { yhdh: ruleForm.value.yhdh, mm: ruleForm.value.mm }); emit('onConfirm', { yhdh: ruleForm.value.yhdh, mm: ruleForm.value.mm });
flag.value = false;
checkShow.value = false; checkShow.value = false;
} else { } else {
return false; return false;
@ -99,6 +102,15 @@ const handleCancel = () => {
emit('onCancel'); emit('onCancel');
}; };
const close = () => {
ruleForm.value.yhdh = '';
ruleForm.value.mm = '';
ruleFormRef.value.resetFields();
if (flag.value) {
emit('onCancel');
}
};
defineExpose({ defineExpose({
open, open,
}); });

View File

@ -0,0 +1,177 @@
<template>
<div>
<el-dialog v-model="builtShow" title="检验结果对照" width="40vw" :close-on-click-modal="false" :draggable="true">
<div class="tips mb10">字典中不存在项目</div>
<el-row :gutter="10">
<el-col :span="16">
<el-table :data="builtTableData" height="50vh" border show-overflow-tooltip>
<el-table-column label="接口/通道号" prop="xmdh" />
<el-table-column label="结果" prop="csjg" />
<el-table-column label="对应检验项目" width="180">
<template #default="{ row }">
<el-select v-model="row.xmdh0" placeholder="" filterable @change="" size="small"
class="full-width-input">
<el-option v-for="item in builtOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</template>
</el-table-column>
</el-table>
</el-col>
<el-col :span="8">
<div class="tips">
提示:<br />
如果结果就是某个检验项目的结果,请在“对应检验项目”列表中直接选择进行对照。<br />
如果不是,<br />
请选择菜单“字典”一>“检验项目”进入检验维护作业后点击按钮<br />
自动加载”加入项目。<br />
</div>
<div class="btns_box">
<div class="btn" @click="cpHandle">存盘</div>
<div class="btn" @click="builtShow = false">退出</div>
<div class="btn" @lcick="clearProHandle">清除未做</div>
</div>
</el-col>
</el-row>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { noiteMresult, queryXmInfo, setitemInter } from '@/api/liswork/work/LisWork';
import { ElMessageBox } from 'element-plus';
const props = defineProps({
tableKey: {
type: Object as PropType<any>,
required: true
}
});
const { tableKey } = toRefs(props);
const builtShow = ref(false);
const builtTableData = ref<Array<any>>([]);
const builtOptions = ref<Array<any>>([]);
const emits = defineEmits(['clearPro']);
const open = () => {
queryXmInfo({ yq: tableKey.value.yq }).then((res: any) => {
if (res.code == 0) {
builtOptions.value = res.data.map((item: any) => {
return {
value: item.xmdh,
label: item.xmdh + ' - ' + item.xmmc
}
})
}
})
noiteMresult(tableKey.value).then((res: any) => {
builtTableData.value = res.data.map((item: any) => {
return {
...item,
xmdh0: ''
}
})
})
builtShow.value = true;
}
const cpHandle = () => {
const validItems = builtTableData.value.filter(item => item.xmdh0);
if (validItems.length === 0) {
console.log("没有需要处理的项");
return;
}
let successCount = 0;
let failCount = 0;
const requests = validItems.map((item, index) => {
return setitemInter({ ...tableKey.value, xmdh0: item.xmdh0, xmdh: item.xmdh })
.then((response: any) => ({
index,
success: true,
data: response
}))
.catch((error: any) => ({
index,
success: false,
error: error
}));
});
Promise.all(requests).then(results => {
results.forEach((result: any) => {
if (result.success) {
successCount++;
// console.log(`第 ${result.index + 1} 项成功:`, result.data);
} else {
failCount++;
// console.error(`第 ${result.index + 1} 项失败:`, result.error);
}
});
// 输出统计结果
ElMessageBox.alert(
`项目与通道号对照已经完成,成功${successCount}个;失败${failCount}个。<br />你可以重新从仪器端传送一遍数据,就可以看到正确的结果了。`,
'信息',
{
dangerouslyUseHTMLString: true,
}
)
})
};
const clearProHandle = () => {
emits('clearPro')
}
defineExpose({
open
})
</script>
<style scoped lang="scss">
.tips {
font-family: SourceHanSansCN, SourceHanSansCN;
}
.btns_box {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
margin-top: 1.875rem;
.btn {
width: 80%;
height: 2.5rem;
line-height: 2.5rem;
margin-bottom: 0.5rem;
font-size: 0.9rem;
font-weight: 500;
border-radius: 0.5rem;
background-color: var(--el-color-primary);
color: var(--el-color-white);
cursor: pointer;
&:hover {
background-color: var(--el-color-primary-light-2);
}
&:last-child {
margin-bottom: 0;
}
&.disabled {
background-color: var(--el-color-primary-light-5);
cursor: not-allowed;
}
}
}
</style>

View File

@ -0,0 +1,130 @@
<template>
<div>
<el-dialog v-model="dlShow" title="双工流水线申请单列表" width="40vw" :close-on-click-modal="false" :draggable="true">
<div class="mb10">
<el-button type="primary" @click="getDlList">刷新</el-button>
<el-button type="primary" @click="cfHandle">重发申请单</el-button>
<el-button @click="closeHandle">取消申请单</el-button>
</div>
<CustomTable :data="dlTableData" :columns="dlColumns" :config="dlTableConfig" :enable-column-drag="true"
@column-drag-end="dlDragEnd" @selection-change="dlSelectionChange">
<template #instrid="{ row }">
{{ row.instrid ? dlObj[row.instrid] : '未发送指令' }}
</template>
<template #brxb="{ row }">
{{ formatDict(row.brxb, 'SX') }}
</template>
<template #nldw="{ row }">
{{ formatDict(row.nldw, 'AU') }}
</template>
</CustomTable>
<div class="mt5" style="text-align: center;color:blue;">样本总数:{{ dlTableData.length }}</div>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { changeLinkList, datalink } from '@/api/liswork/work/LisWork'
import { ElMessage } from 'element-plus'
import CustomTable from '@/components/elTable/index.vue'
const props = defineProps({
tableKey: {
type: Object,
required: true
},
dictData: {
type: Object,
default: () => ({})
},
})
const { tableKey } = toRefs(props)
const dlObj: any = {
0: '申请发送',
1: '已发送指令',
2: '申请撤销中'
}
const dlShow = ref(false)
const dlTableData = ref([])
const dlColumns = ref([
{ label: "选择", type: 'selection', align: 'center', width: 40, visible: true, },
{ label: "动作状态", prop: "instrid", align: 'center', visible: true, slot: 'instrid' },
{ label: "申请号", prop: "sqh", align: 'center', visible: true, },
{ label: "样本号", prop: "ybh", align: 'center', visible: true, },
{ label: "姓名", prop: "brxm", align: 'center', visible: true, },
{ label: "性别", prop: "brxb", width: 30, align: 'center', visible: true, slot: 'brxb' },
{ label: "年", prop: "nl", width: 30, align: 'center', visible: true, },
{ label: "龄", prop: "nldw", width: 30, align: 'center', visible: true, slot: "nldw" },
{ label: "检验目的", prop: "jymd", width: 180, visible: true, },
])
const dlTableConfig = ref({
border: true,
height: '500px',
cellStyle: ({ row, column }: any) => {
if (row.instrid == 1) {
return { background: '#c0c0c0 !important' }
}
},
})
const dlDragEnd = (data: any) => {
dlColumns.value = data.columns
}
const dlList = ref([])
const dlSelectionChange = (selection: any) => {
dlList.value = selection
}
const getDlList = () => {
datalink(tableKey.value).then((res: any) => {
dlTableData.value = res.data;
})
}
const cfHandle = () => {
if (dlList.value.length < 0) return ElMessage.warning('请选择数据')
const arr = dlList.value.filter((item: any) => item.instrid == 1)
arr.forEach((v: any) => {
v.instrid = null
})
changeLinkList(arr).then((res: any) => {
if (res.code == 0) {
getDlList()
}
})
}
const closeHandle = () => {
dlList.value.forEach((v: any) => {
v.instrid = 2
})
changeLinkList(dlList.value).then((res: any) => {
if (res.code == 0) {
getDlList()
}
})
}
const open = () => {
getDlList()
dlShow.value = true
}
defineExpose({
open
})
const formatDict = (v: string, dictType: string) => {
return props.dictData[dictType]?.find((item: any) => item.value == v)?.label || v;
}
</script>
<style scoped></style>

View File

@ -0,0 +1,113 @@
<template>
<div>
<el-dialog v-model="jgShow" title="绑定其他结果" width="40vw" :close-on-click-modal="false" :draggable="true">
<el-row>
<el-col :span="8">
<el-radio-group v-model="radio1">
<el-radio value="1">5天内</el-radio>
<el-radio value="2">10天内</el-radio>
<el-radio value="3">20天内</el-radio>
<el-radio value="4">30天内</el-radio>
</el-radio-group>
</el-col>
<el-col :span="4">
<el-radio-group v-model="radio2">
<el-radio value="1">复制</el-radio>
<el-radio value="2">移动</el-radio>
</el-radio-group>
</el-col>
<el-col :span="4">
<el-radio-group v-model="radio3">
<el-radio value="1">覆盖</el-radio>
<el-radio value="2">不覆盖</el-radio>
</el-radio-group>
</el-col>
<el-col :span="8">
<div> <el-checkbox>只显示同一申请单号</el-checkbox> </div>
<div>
<el-button type="primary">合并</el-button>
<el-button>取消</el-button>
</div>
</el-col>
</el-row>
<CustomTable :data="mTableData" :columns="mColumns" :config="mTableConfig" :enable-column-drag="true"
@column-drag-end="mDragEnd" @selection-change="mSelectionChange">
<template #brxb="{ row }">
{{ formatDict(row.brxb, 'SX') }}
</template>
<template #nldw="{ row }">
{{ formatDict(row.nldw, 'AU') }}
</template>
</CustomTable>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import CustomTable from '@/components/elTable/index.vue'
const props = defineProps({
tableKey: {
type: Object,
required: true
},
dictData: {
type: Object,
default: () => ({})
},
})
const { tableKey } = toRefs(props)
const jgShow = ref(false)
const radio1 = ref('1')
const radio2 = ref('1')
const radio3 = ref('1')
const mTableData = ref([])
const mColumns = ref([
{ label: "选择", type: 'selection', align: 'center', width: 40, visible: true, },
{ label: "仪器", prop: "yq", visible: true, },
{ label: "检验日期", prop: "jyrq", visible: true, },
{ label: "样本号", prop: "ybh", visible: true, },
{ label: "病历号", prop: "brdh", visible: true, },
{ label: "病人姓名", prop: "brxm", visible: true, },
{ label: "年", prop: "nl", width: 40, visible: true, },
{ label: "龄", prop: "nldw", width: 30, visible: true, slot: "nldw" },
{ label: "检验项目", prop: "xmdh", visible: true, },
{ label: "检验结果", prop: "csjg", width: 60, visible: true, },
{ label: "申请号", prop: "sqh", visible: true, },
])
const mTableConfig = {
border: true,
height: '500px'
}
const mDragEnd = (data: any) => {
mColumns.value = data.columns
}
const mSelectionChange = (data: any) => {
}
const open = () => {
jgShow.value = true
}
defineExpose({
open
})
const formatDict = (v: string, dictType: string) => {
return props.dictData[dictType]?.find((item: any) => item.value == v)?.label || v;
}
</script>
<style scoped></style>

View File

@ -105,17 +105,15 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { viewBackup } from '@/api/liswork/work/LisWork';
import SelectTable from '@/components/SelectTable/index.vue'; import SelectTable from '@/components/SelectTable/index.vue';
const props = defineProps({ const props = defineProps({
backTableData: { tableKey: {
type: Array,
default: () => [],
},
backLabInfo: {
type: Object, type: Object,
default: () => { }, required: true,
}, },
userList: { userList: {
type: Array as PropType<object[]>, type: Array as PropType<object[]>,
default: () => [], default: () => [],
@ -143,6 +141,12 @@ const backTableData = ref([])
const backLabInfo: any = ref({}) const backLabInfo: any = ref({})
const openDialog = () => { const openDialog = () => {
viewBackup(props.tableKey).then((res: any) => {
if (res.data) {
backTableData.value = res.data.labresultbk
backLabInfo.value = res.data.labpatbk || {}
}
})
backShow.value = true backShow.value = true
} }

View File

@ -133,8 +133,8 @@ import {
import { querylabInstrList, querylabInstrListByLisgroup } from "../../../api/liswork/dict/LabInstr"; import { querylabInstrList, querylabInstrListByLisgroup } from "../../../api/liswork/dict/LabInstr";
import { getComDicts, queryComDictListService } from "../../../api/liswork/dict/ComDict"; import { getComDicts, queryComDictListService } from "../../../api/liswork/dict/ComDict";
import LabPatForm from './components/labpat.vue' import LabPatForm from './components/labpat.vue'
import LabResultForm from './components/labresult.vue' import LabResultForm from './labresult.vue'
import LabPatListForm from './components/labpatlist.vue' import LabPatListForm from './labpatlist.vue'
import Unconfirmlog from './components/unconfirmlog.vue' import Unconfirmlog from './components/unconfirmlog.vue'
import Ddlb from './components/ddlb.vue' import Ddlb from './components/ddlb.vue'
import CheckUser from './components/CheckUser.vue' import CheckUser from './components/CheckUser.vue'

View File

@ -123,14 +123,14 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, nextTick, onMounted, toRaw } from 'vue'; import { ref, nextTick, onMounted, toRaw } from 'vue';
import LabPat from './components/labpat.vue'; import LabPat from './labpat.vue';
import SelectTable from '@/components/SelectTable/index.vue'; import SelectTable from '@/components/SelectTable/index.vue';
import tabView from '@/components/tabViews/index.vue'; import tabView from '@/components/tabViews/index.vue';
// @ts-ignore // @ts-ignore
import iFrame from "@/components/iFrame/index.vue"; import iFrame from "@/components/iFrame/index.vue";
// @ts-ignore // @ts-ignore
import LabResult from './components/labresult.vue'; import LabResult from './labresult.vue';
import LabPatList from './components/labpatlist.vue'; import LabPatList from './labpatlist.vue';
// @ts-ignore // @ts-ignore
import { comDict } from '@/utils/dict' import { comDict } from '@/utils/dict'
import { queryLabPatList, queryLabResults, loadDefault, queryLabPat, instrdconfig, delSample, getGroupInstrdList } from "@/api/liswork/work/LisWork"; import { queryLabPatList, queryLabResults, loadDefault, queryLabPat, instrdconfig, delSample, getGroupInstrdList } from "@/api/liswork/work/LisWork";

View File

@ -71,7 +71,7 @@
import { ref, reactive, watch, toRaw, computed, onMounted, nextTick } from 'vue'; import { ref, reactive, watch, toRaw, computed, onMounted, nextTick } from 'vue';
import { changepatcolumn, updateLabPat, checkYsUser } from "@/api/liswork/work/LisWork"; import { changepatcolumn, updateLabPat, checkYsUser } from "@/api/liswork/work/LisWork";
import SelectTable from '@/components/SelectTable/index.vue'; import SelectTable from '@/components/SelectTable/index.vue';
import YhVerification from './yhVerification.vue'; import YhVerification from './components/yhVerification.vue';
import emitter from '@/utils/mitt'; import emitter from '@/utils/mitt';
import { classCom } from '@/utils/classCom'; import { classCom } from '@/utils/classCom';

View File

@ -11,8 +11,8 @@
@click="handleBatchDelete">删除</el-button> @click="handleBatchDelete">删除</el-button>
</div> </div>
<div> <div>
<el-button type="primary" plain icon="Files" :size="aotuSize" @click="printHandle">打印</el-button> <el-button type="primary" plain icon="Files" :size="aotuSize" @click="previewHandle(1)">打印</el-button>
<el-button type="primary" plain icon="View" :size="aotuSize" @click="previewHandle">预览</el-button> <el-button type="primary" plain icon="View" :size="aotuSize" @click="previewHandle(2)">预览</el-button>
</div> </div>
</div> </div>
<ContextMenu :items="contextMenuItems" @select="handleMenuSelect"> <ContextMenu :items="contextMenuItems" @select="handleMenuSelect">
@ -77,121 +77,28 @@
<!-- 校验用户 --> <!-- 校验用户 -->
<CheckUser ref="checkUserRef" :title="checktitle" @onConfirm="handleCheckUserConfirm" /> <CheckUser ref="checkUserRef" :title="checktitle" @onConfirm="handleCheckUserConfirm" />
<!-- 危急值结果上报 --> <!-- 危急值结果上报 -->
<UploadWarning ref="uploadwarningRef" :warningMsgdata="warningMsgdata" :tableKey="tableKey" <UploadWarning ref="uploadwarningRef" :warningMsgdata="warningMsgdata" :tableKey="tableKey"
@onupload="shHandleCheck" /> @onupload="shHandleCheck" />
<!-- 操作原因 --> <!-- 操作原因 -->
<Unconfirmlog ref="unconfirmlogRef" :reasonText="reasonText" :tableKey="tableKey" @onConfirm="unShHandle" /> <Unconfirmlog ref="unconfirmlogRef" :reasonText="reasonText" :tableKey="tableKey" @onConfirm="unShHandle" />
<!-- 合并当前病人其他结果 --> <!-- 合并当前病人其他结果 -->
<el-dialog v-model="jgShow" title="绑定其他结果" width="40vw" :close-on-click-modal="false" :draggable="true"> <MergeResults ref="mergeRef" :tableKey="tableKey" :dictData="dictData" />
<el-row>
<el-col :span="8">
<el-radio-group v-model="radio2">
<el-radio value="1">5天内</el-radio>
<el-radio value="2">10天内</el-radio>
<el-radio value="2">20天内</el-radio>
<el-radio value="2">30天内</el-radio>
</el-radio-group>
</el-col>
<el-col :span="4">
<el-radio-group v-model="radio2">
<el-radio value="1">复制</el-radio>
<el-radio value="2">移动</el-radio>
</el-radio-group>
</el-col>
<el-col :span="4">
<el-radio-group v-model="radio2">
<el-radio value="1">覆盖</el-radio>
<el-radio value="2">不覆盖</el-radio>
</el-radio-group>
</el-col>
<el-col :span="8">
<div> <el-checkbox>只显示同一申请单号</el-checkbox> </div>
<div>
<el-button type="primary">合并</el-button>
<el-button>取消</el-button>
</div>
</el-col>
</el-row>
<CustomTable :data="mTableData" :columns="mColumns" :config="mTableConfig" :enable-column-drag="true"
@column-drag-end="mDragEnd" @selection-change="mSelectionChange">
<template #brxb="{ row }">
{{ formatDict(row.brxb, 'SX') }}
</template>
<template #nldw="{ row }">
{{ formatDict(row.nldw, 'AU') }}
</template>
</CustomTable>
</el-dialog>
<!-- 用户校验 --> <!-- 用户校验 -->
<userVerification ref="formRef" :title="verTitle" :form-value="formData" :userList="userList" <userVerification ref="formRef" :title="verTitle" :userList="userList" @confirm="handleConfirm" />
@confirm="handleConfirm" @cancel="handleCancel" />
<!-- 双工流水线 --> <!-- 双工流水线 -->
<el-dialog v-model="dlShow" title="双工流水线申请单列表" width="40vw" :close-on-click-modal="false" :draggable="true"> <DlDialog ref="dlRef" :tableKey="tableKey" :dictData="dictData" />
<div class="mb10">
<el-button type="primary" @click="getDlList">刷新</el-button>
<el-button type="primary" @click="cfHandle">重发申请单</el-button>
<el-button @click="closeHandle">取消申请单</el-button>
</div>
<CustomTable :data="dlTableData" :columns="dlColumns" :config="dlTableConfig" :enable-column-drag="true"
@column-drag-end="dlDragEnd" @selection-change="dlSelectionChange">
<template #instrid="{ row }">
{{ row.instrid ? dlObj[row.instrid] : '未发送指令' }}
</template>
<template #brxb="{ row }">
{{ formatDict(row.brxb, 'SX') }}
</template>
<template #nldw="{ row }">
{{ formatDict(row.nldw, 'AU') }}
</template>
</CustomTable>
<div class="mt5" style="text-align: center;color:blue;">样本总数:{{ dlTableData.length }}</div>
</el-dialog>
<!-- 查看备份数据 --> <!-- 查看备份数据 -->
<ViewBackup ref="backRef" :backLabInfo="backLabInfo" :backTableData="backTableData" :userList="userList" <ViewBackup ref="backRef" :tableKey="tableKey" :userList="userList" :dictData="dictData" />
:dictData="dictData" />
<!-- 未建项目结果 --> <!-- 未建项目结果 -->
<el-dialog v-model="builtShow" title="检验结果对照" width="40vw" :close-on-click-modal="false" :draggable="true"> <BuiltDialog ref="builtRef" :tableKey="tableKey" @clearPro="clearProHandle" />
<div class="tips mb10">字典中不存在项目</div>
<el-row :gutter="10">
<el-col :span="16">
<el-table :data="builtTableData" height="50vh" border show-overflow-tooltip>
<el-table-column label="接口/通道号" prop="xmdh" />
<el-table-column label="结果" prop="csjg" />
<el-table-column label="对应检验项目" width="180">
<template #default="{ row }">
<el-select v-model="row.xmdh0" placeholder="" filterable @change="" size="small"
class="full-width-input">
<el-option v-for="item in builtOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</template>
</el-table-column>
</el-table>
</el-col>
<el-col :span="8">
<div class="tips">
提示:<br />
如果结果就是某个检验项目的结果,请在“对应检验项目”列表中直接选择进行对照。<br />
如果不是,<br />
请选择菜单“字典”一>“检验项目”进入检验维护作业后点击按钮<br />
自动加载”加入项目。<br />
</div>
<div class="btns_box">
<div class="btn" @click="cpHandle">存盘</div>
<div class="btn" @click="builtShow = false">退出</div>
<div class="btn" @lcick="clearProHandle">清除未做</div>
</div>
</el-col>
</el-row>
</el-dialog>
</div> </div>
</template> </template>
@ -199,23 +106,26 @@
import { ref, toRefs, watch, nextTick, onMounted, computed } from "vue"; import { ref, toRefs, watch, nextTick, onMounted, computed } from "vue";
import userVerification from "@/components/userVerification/index.vue"; import userVerification from "@/components/userVerification/index.vue";
import { import {
check1, check2, uncheck2, unconfirmlog, checkuser, reglimit, deleteresult, changeresult, allPatquery, emrquery, datalink, changeLinkList, check1, check2, uncheck2, checkuser, deleteresult, changeresult, allPatquery, emrquery,
viewBackup, newresult, queryXmVal, printListwork, getresultchangelog, setinputmdl, saveResult, lockSample, unLockSample, clearnotComplete, clearPrintflag, newresult, queryXmVal, printListwork, getresultchangelog, setinputmdl, saveResult, lockSample, unLockSample, clearnotComplete, clearPrintflag
noiteMresult, queryXmInfo, setitemInter
} from "@/api/liswork/work/LisWork"; } from "@/api/liswork/work/LisWork";
import { ElMessageBox, ElMessage } from "element-plus"; import { ElMessageBox, ElMessage } from "element-plus";
import ProjectDetails from "@/components/projectDetails/index.vue"; import ProjectDetails from "@/components/projectDetails/index.vue";
import projectsJg from "@/components/projectsjg/index.vue" import projectsJg from "@/components/projectsjg/index.vue"
import BuiltDialog from "./components/builtDialog.vue";
import { classCom } from '@/utils/classCom' import { classCom } from '@/utils/classCom'
import CustomTable from '@/components/elTable/index.vue' import CustomTable from '@/components/elTable/index.vue'
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import emitter from "@/utils/mitt"; import emitter from "@/utils/mitt";
import CheckUser from "./CheckUser.vue"; import CheckUser from "./components/CheckUser.vue";
import Unconfirmlog from './unconfirmlog.vue'; import Unconfirmlog from './components/unconfirmlog.vue';
import UploadWarning from "./uploadwarning.vue"; import UploadWarning from "./components/uploadwarning.vue";
import { useCommonStore } from "@/store/modules/commonStore"; import { useCommonStore } from "@/store/modules/commonStore";
import ContextMenu from "@/components/contextMenu/index.vue"; import ContextMenu from "@/components/contextMenu/index.vue";
import ViewBackup from "./viewBackup.vue"; import ViewBackup from "./components/viewBackup.vue";
import DlDialog from "./components/dlDialog.vue";
import MergeResults from "./components/mergeResults.vue";
import { dictData } from "@/hooks";
// 组件属性定义 // 组件属性定义
const props = defineProps({ const props = defineProps({
resultSysList: { type: Array, required: true }, resultSysList: { type: Array, required: true },
@ -320,10 +230,10 @@ const contextMenuItems = computed(() => [
const handleMenuSelect = (item) => { const handleMenuSelect = (item) => {
switch (item.action) { switch (item.action) {
case 'view': case 'view':
printHandle() //打印预览 previewHandle(1) //打印预览
break; break;
case 'bgyl': case 'bgyl':
previewHandle() //PDF报告预览 previewHandle(2) //PDF报告预览
break; break;
case 'merge': case 'merge':
mergeHandle() mergeHandle()
@ -366,82 +276,12 @@ const handleMenuSelect = (item) => {
break; break;
} }
}; };
const builtShow = ref(false) const builtRef = ref()
const builtTableData = ref([])
const builtOptions = ref([])
const unbuiltHandle = () => { const unbuiltHandle = () => {
queryXmInfo({ yq: tableKey.value.yq }).then(res => { builtRef.value.open()
if (res.code == 0) {
builtOptions.value = res.data.map(item => {
return {
value: item.xmdh,
label: item.xmdh + ' - ' + item.xmmc
}
})
}
})
noiteMresult(tableKey.value).then(res => {
builtTableData.value = res.data.map(item => {
return {
...item,
xmdh0: ''
}
})
})
builtShow.value = true
}; };
const cpHandle = () => {
const validItems = builtTableData.value.filter(item => item.xmdh0);
if (validItems.length === 0) {
console.log("没有需要处理的项");
return;
}
let successCount = 0;
let failCount = 0;
const requests = validItems.map((item, index) => {
return setitemInter({ ...tableKey.value, xmdh0: item.xmdh0, xmdh: item.xmdh })
.then(response => ({
index,
success: true,
data: response
}))
.catch(error => ({
index,
success: false,
error: error
}));
});
Promise.all(requests).then(results => {
results.forEach(result => {
if (result.success) {
successCount++;
// console.log(`第 ${result.index + 1} 项成功:`, result.data);
} else {
failCount++;
// console.error(`第 ${result.index + 1} 项失败:`, result.error);
}
});
// 输出统计结果
ElMessageBox.alert(
`项目与通道号对照已经完成,成功${successCount}个;失败${failCount}个。<br />你可以重新从仪器端传送一遍数据,就可以看到正确的结果了。`,
'信息',
{
dangerouslyUseHTMLString: true,
}
)
})
};
const clearPrintHandle = () => { const clearPrintHandle = () => {
clearPrintflag(tableKey.value).then(res => { clearPrintflag(tableKey.value).then(res => {
if (res.code == 0) { if (res.code == 0) {
@ -458,36 +298,9 @@ const clearProHandle = () => {
} }
}) })
}; };
const mTableData = ref([]) const mergeRef = ref()
const mColumns = ref([
{ label: "选择", type: 'selection', align: 'center', width: 40, visible: true, },
{ label: "仪器", prop: "yq", visible: true, },
{ label: "检验日期", prop: "jyrq", visible: true, },
{ label: "样本号", prop: "ybh", visible: true, },
{ label: "病历号", prop: "brdh", visible: true, },
{ label: "病人姓名", prop: "brxm", visible: true, },
{ label: "年", prop: "nl", width: 40, visible: true, },
{ label: "龄", prop: "nldw", width: 30, visible: true, slot: "nldw" },
{ label: "检验项目", prop: "xmdh", visible: true, },
{ label: "检验结果", prop: "csjg", width: 60, visible: true, },
{ label: "申请号", prop: "sqh", visible: true, },
])
const mTableConfig = {
border: true
}
const mDragEnd = (data) => {
mColumns.value = data.columns
}
const mSelectionChange = (data) => {
}
const mergeHandle = () => { const mergeHandle = () => {
jgShow.value = true; mergeRef.value.open()
}; };
const emrqueryHandle = () => { const emrqueryHandle = () => {
@ -505,94 +318,17 @@ const patqueryHandle = () => {
}) })
}; };
const backRef = ref() const backRef = ref()
const backLabInfo = ref({})
const backTableData = ref([])
const viewbackupHandle = () => { const viewbackupHandle = () => {
viewBackup(tableKey.value).then(res => {
if (res.data) {
backTableData.value = res.data.labresultbk
backLabInfo.value = res.data.labpatbk
}
})
backRef.value.openDialog() backRef.value.openDialog()
}; };
const dlObj = {
0: '申请发送',
1: '已发送指令',
2: '申请撤销中'
}
const dlShow = ref(false)
const dlTableData = ref([])
const dlColumns = ref([
{ label: "选择", type: 'selection', align: 'center', width: 40, visible: true, },
{ label: "动作状态", prop: "instrid", align: 'center', visible: true, slot: 'instrid' },
{ label: "申请号", prop: "sqh", align: 'center', visible: true, },
{ label: "样本号", prop: "ybh", align: 'center', visible: true, },
{ label: "姓名", prop: "brxm", align: 'center', visible: true, },
{ label: "性别", prop: "brxb", width: 30, align: 'center', visible: true, slot: 'brxb' },
{ label: "年", prop: "nl", width: 30, align: 'center', visible: true, },
{ label: "龄", prop: "nldw", width: 30, align: 'center', visible: true, slot: "nldw" },
{ label: "检验目的", prop: "jymd", width: 180, visible: true, },
])
const dlTableConfig = ref({
border: true, const dlRef = ref()
maxHeight: 500,
cellStyle: ({ row, column }) => {
if (row.instrid == 1) {
return { background: '#c0c0c0 !important' }
}
},
})
const dlDragEnd = (data) => {
dlColumns.value = data.columns
}
const dlList = ref([])
const dlSelectionChange = (selection) => {
dlList.value = selection
}
const datalinkHandle = () => { const datalinkHandle = () => {
getDlList() dlRef.value.open()
dlShow.value = true;
}; };
const getDlList = () => {
datalink(tableKey.value).then(res => {
dlTableData.value = res.data;
})
}
const cfHandle = () => {
if (dlList.value.length < 0) return ElMessage.warning('请选择数据')
const arr = dlList.value.filter(item => item.instrid == 1)
arr.forEach(v => {
v.instrid = null
})
changeLinkList(arr).then(res => {
if (res.code == 0) {
getDlList()
}
})
}
const closeHandle = () => {
dlList.value.forEach(v => {
v.instrid = 2
})
changeLinkList(dlList.value).then(res => {
if (res.code == 0) {
getDlList()
}
})
}
const formRef = ref();
const formData = ref({
yhdh: '',
userName: '',
mm: '',
})
const verTitle = ref('请输入锁定人员账号密码') const verTitle = ref('请输入锁定人员账号密码')
const lockType = ref(1) const lockType = ref(1)
// 锁定报告 // 锁定报告
@ -614,9 +350,13 @@ const unlockHandle = () => {
// 锁定样本 // 锁定样本
const handleConfirm = (data) => { const handleConfirm = (data) => {
const obj = { const obj = {
...tableKey.value,
yhdh: data.yhdh, yhdh: data.yhdh,
...tableKey.value
} }
emits('update:tableKey', {
...tableKey.value,
yhdh: info.yhdh
});
if (lockType.value == 1) { if (lockType.value == 1) {
lockSample(obj).then((res) => { lockSample(obj).then((res) => {
if (res.code == 0) { if (res.code == 0) {
@ -635,13 +375,7 @@ const handleConfirm = (data) => {
}); });
} }
} }
const handleCancel = () => {
formData.value = {
yhdh: '',
userName: '',
mm: '',
}
}
const columns = ref([ const columns = ref([
{ label: 'No', prop: 'index', width: 30, align: 'center', visible: true, slot: "index" }, { label: 'No', prop: 'index', width: 30, align: 'center', visible: true, slot: "index" },
{ label: "复", prop: "redo_flag", width: 30, align: 'center', visible: true, }, { label: "复", prop: "redo_flag", width: 30, align: 'center', visible: true, },
@ -751,7 +485,11 @@ const handleCheckUserConfirm = (info) => {
...tableKey.value, ...tableKey.value,
yhdh: info.yhdh yhdh: info.yhdh
}); });
proceedCheck(runnextstepname.value)
// 异步处理 等待yhdh数据更新
setTimeout(() => {
proceedCheck(runnextstepname.value)
}, 100);
} }
}) })
} }
@ -759,7 +497,7 @@ const handleCheckUserConfirm = (info) => {
const proceedCheck = (checkType) => { const proceedCheck = (checkType) => {
switch (checkType) { switch (checkType) {
case 1: // 初审 case 1: // 初审
check1({ ...tableKey.value, yhdh: props.labPat.yhdh }).then(res => { check1({ ...tableKey.value }).then(res => {
emits("changeStatus", props.labPat); emits("changeStatus", props.labPat);
}) })
break; break;
@ -777,7 +515,7 @@ const proceedCheck = (checkType) => {
} }
const uploadwarningRef = ref(); const uploadwarningRef = ref();
const shHandleCheck = () => { const shHandleCheck = () => {
check2({ ...props.tableKey, yhdh: props.labPat.yhdh }).then(res => { check2({ ...props.tableKey }).then(res => {
emits("changeStatus", props.labPat); emits("changeStatus", props.labPat);
if (res.code == "4" && res.problemId === 4) { if (res.code == "4" && res.problemId === 4) {
tableKey.value.problemId = res.problemId; tableKey.value.problemId = res.problemId;
@ -790,8 +528,7 @@ const shHandleCheck = () => {
const unconfirmlogRef = ref(); const unconfirmlogRef = ref();
const unShHandle = () => { const unShHandle = () => {
uncheck2({ ...tableKey.value, yhdh: props.labPat.yhdh }).then(res => { uncheck2({ ...tableKey.value }).then(res => {
console.log('res',res);
if (res.code == "4") { if (res.code == "4") {
tableKey.value.problemId = res.problemId; tableKey.value.problemId = res.problemId;
reasonText.value = res.msg; reasonText.value = res.msg;
@ -1013,7 +750,8 @@ const handleBatchDelete = () => {
}); });
}; };
const printHandle = () => {
const previewHandle = (type) => {
const data = { const data = {
jyrq: tableKey.value.jyrq, jyrq: tableKey.value.jyrq,
yq: tableKey.value.yq, yq: tableKey.value.yq,
@ -1022,20 +760,11 @@ const printHandle = () => {
} }
printListwork(data).then(res => { printListwork(data).then(res => {
if (res.code == 0) { if (res.code == 0) {
classCom.printBase64PDF(res.data) if (type == 1) {
} classCom.printBase64PDF(res.data)
}) } else {
}; emits('previewHandle', res.data);
const previewHandle = () => { }
const data = {
jyrq: tableKey.value.jyrq,
yq: tableKey.value.yq,
ybh: tableKey.value.ybh,
sqh: tableKey.value.sqh
}
printListwork(data).then(res => {
if (res.code == 0) {
emits('previewHandle', res.data);
} }
}) })
}; };
@ -1103,43 +832,4 @@ const formatDict = (v, dictType) => {
.custom-table-container { .custom-table-container {
height: 100%; height: 100%;
} }
.tips {
font-family: SourceHanSansCN, SourceHanSansCN;
}
.btns_box {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
margin-top: 1.875rem;
.btn {
width: 80%;
height: 2.5rem;
line-height: 2.5rem;
margin-bottom: 0.5rem;
font-size: 0.9rem;
font-weight: 500;
border-radius: 0.5rem;
background-color: var(--el-color-primary);
color: var(--el-color-white);
cursor: pointer;
&:hover {
background-color: var(--el-color-primary-light-2);
}
&:last-child {
margin-bottom: 0;
}
&.disabled {
background-color: var(--el-color-primary-light-5);
cursor: not-allowed;
}
}
}
</style> </style>

View File

@ -1,13 +1,15 @@
<template> <template>
<div class="login"> <div class="login">
<el-form ref="loginRef" class="login-form"> <!-- <FloatingLines :enabled-waves="['top', 'middle', 'bottom']" :line-count="[10, 15, 20]" :line-distance="[8, 6, 4]"
:bend-radius="5.0" :bend-strength="-0.5" :interactive="true" :parallax="true" /> -->
<el-form ref="loginRef" class="login-form">
<div class="login-header"> <div class="login-header">
<div class="login-logo"> <div class="login-logo">
<img src="@/assets/images/logo_new.png" alt="系统Logo" /> <img src="@/assets/images/logo_new.png" alt="系统Logo" />
</div> </div>
<div class="login-split"></div> <div class="login-split"></div>
<div class="login-title"> <div class="login-title">
<h1>{{ oem.appname}}</h1> <h1>{{ oem.appname }}</h1>
</div> </div>
</div> </div>
@ -15,21 +17,12 @@
<el-tabs v-model="activeName" type="card" @tab-click="handleClick" class="login-tabs"> <el-tabs v-model="activeName" type="card" @tab-click="handleClick" class="login-tabs">
<!-- 工号登录 Tab --> <!-- 工号登录 Tab -->
<el-tab-pane label="账号密码登录" name="first"> <el-tab-pane label="账号密码登录" name="first">
<el-form-item label="医疗机构:" prop="loginYLJG"class="custom-select"> <el-form-item label="医疗机构:" prop="loginYLJG" class="custom-select">
<el-select <el-select v-model="loginForm.loginParam.loginYLJG" placeholder="请选择医疗机构" style="width: 100%">
v-model="loginForm.loginParam.loginYLJG"
placeholder="请选择医疗机构"
style="width: 100%"
>
<template #prefix> <template #prefix>
<svg-icon icon-class="international" class="el-input__icon input-icon" /> <svg-icon icon-class="international" class="el-input__icon input-icon" />
</template> </template>
<el-option <el-option v-for="item in selectOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
v-for="item in selectOptions"
:key="item.id"
:label="item.name"
:value="item.id"
></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
@ -43,7 +36,7 @@
<el-form-item label="登录密码:" prop="password"> <el-form-item label="登录密码:" prop="password">
<el-input v-model="loginForm.password" type="password" size="large" auto-complete="off" placeholder="密码" <el-input v-model="loginForm.password" type="password" size="large" auto-complete="off" placeholder="密码"
@keyup.enter="handleLogin"> @keyup.enter="handleLogin">
<template #prefix> <template #prefix>
<svg-icon icon-class="password" class="el-input__icon input-icon" /> <svg-icon icon-class="password" class="el-input__icon input-icon" />
</template> </template>
@ -56,15 +49,8 @@
</el-form-item> </el-form-item>
<el-form-item prop="code" label="验 证 码 :" v-if="captchaEnabled"> <el-form-item prop="code" label="验 证 码 :" v-if="captchaEnabled">
<el-input <el-input v-model="loginForm.code" size="large" auto-complete="off" placeholder="验证码" style="width: 53%"
@keyup.enter="handleLogin">
v-model="loginForm.code"
size="large"
auto-complete="off"
placeholder="验证码"
style="width: 53%"
@keyup.enter="handleLogin"
>
<template #prefix> <template #prefix>
<svg-icon icon-class="validCode" class="el-input__icon input-icon" /> <svg-icon icon-class="validCode" class="el-input__icon input-icon" />
</template> </template>
@ -75,7 +61,8 @@
</el-form-item> </el-form-item>
<el-form-item style="width: 100%;"> <el-form-item style="width: 100%;">
<el-button :loading="loading" size="large" type="primary" class="login-btn" style="width: 100%;" @click.prevent="handleLogin"> <el-button :loading="loading" size="large" type="primary" class="login-btn" style="width: 100%;"
@click.prevent="handleLogin">
<span v-if="!loading">登 录</span> <span v-if="!loading">登 录</span>
<span v-else>登 录 中...</span> <span v-else>登 录 中...</span>
</el-button> </el-button>
@ -87,7 +74,9 @@
<el-tab-pane label="扫码登录" name="second"> <el-tab-pane label="扫码登录" name="second">
<div class="tab-placeholder"> <div class="tab-placeholder">
<el-icon class="placeholder-icon"><Sms /></el-icon> <el-icon class="placeholder-icon">
<Sms />
</el-icon>
<p>正在加载二维码...</p> <p>正在加载二维码...</p>
<el-button type="success" icon="wechat" class="wechat-login-btn">刷新二维码</el-button> <el-button type="success" icon="wechat" class="wechat-login-btn">刷新二维码</el-button>
</div> </div>
@ -95,7 +84,9 @@
<el-tab-pane label="UKEY登录" name="third"> <el-tab-pane label="UKEY登录" name="third">
<div class="tab-placeholder"> <div class="tab-placeholder">
<el-icon class="placeholder-icon"><Wechat /></el-icon> <el-icon class="placeholder-icon">
<Wechat />
</el-icon>
<p>UKEY登录功能开发中...</p> <p>UKEY登录功能开发中...</p>
</div> </div>
</el-tab-pane> </el-tab-pane>
@ -103,7 +94,7 @@
</el-form> </el-form>
<div class="el-login-footer"> <div class="el-login-footer">
<span>版权所有(R)2022-2026 {{ oem.compay}} 电话:{{oem.phone}} E-mail:{{oem.Email}} version:{{oem.version}}</span> <span>版权所有(R)2022-2026 {{ oem.compay }} 电话:{{ oem.phone }} E-mail:{{ oem.Email }} version:{{ oem.version }}</span>
</div> </div>
</div> </div>
</template> </template>
@ -116,6 +107,7 @@ import { getCodeImg, getInfo, getLocalconfig } from "@/api/login";
import Cookies from "js-cookie"; import Cookies from "js-cookie";
import { encrypt, decrypt } from "@/utils/jsencrypt"; import { encrypt, decrypt } from "@/utils/jsencrypt";
import useUserStore from '@/store/modules/user'; import useUserStore from '@/store/modules/user';
import FloatingLines from '@/components/Ballpit/index.vue';
// 初始化响应式变量 // 初始化响应式变量
const activeName = ref('first'); const activeName = ref('first');
@ -136,12 +128,12 @@ const loginForm = ref({
rememberMe: false, rememberMe: false,
code: "", code: "",
uuid: "", uuid: "",
loginParam:{loginYLJG:"",localid:""} loginParam: { loginYLJG: "", localid: "" }
}); });
const selectOptions = ref([{ id: '1', name: '总院' }]); const selectOptions = ref([{ id: '1', name: '总院' }]);
const loginRules = ref({ // 修复:改为ref响应式,方便动态修改 const loginRules = ref({ // 修复:改为ref响应式,方便动态修改
username: [{ required: true, trigger: "blur", message: "请输入您的账号" }], username: [{ required: true, trigger: "blur", message: "请输入您的账号" }],
// password: [{ required: true, trigger: "blur", message: "请输入您的密码" }], // password: [{ required: true, trigger: "blur", message: "请输入您的密码" }],
hospid: [{ required: true, message: '请选择医疗机构', trigger: 'change' }], hospid: [{ required: true, message: '请选择医疗机构', trigger: 'change' }],
code: [{ required: true, trigger: "change", message: "请输入验证码" }] code: [{ required: true, trigger: "change", message: "请输入验证码" }]
}); });
@ -153,41 +145,41 @@ const redirect = ref(undefined);
// 路由监听(优化版) // 路由监听(优化版)
watch( watch(
() => route.query.redirect, () => route.query.redirect,
(newRedirect) => { (newRedirect) => {
if (redirect.value !== newRedirect) { if (redirect.value !== newRedirect) {
redirect.value = newRedirect || ''; redirect.value = newRedirect || '';
} }
}, },
{ immediate: true, deep: false } { immediate: true, deep: false }
); );
// 登录方法(修复proxy.$refs问题) // 登录方法(修复proxy.$refs问题)
const handleLogin = async () => { const handleLogin = async () => {
loginForm.value.loginParam.loginYLJG loginForm.value.loginParam.loginYLJG
loading.value = true; loading.value = true;
Cookies.set("czlis_username", loginForm.value.username, { expires: 30 }); Cookies.set("czlis_username", loginForm.value.username, { expires: 30 });
Cookies.set("czlis_loginYLJG", loginForm.value.loginParam.loginYLJG, {expires: 30}); Cookies.set("czlis_loginYLJG", loginForm.value.loginParam.loginYLJG, { expires: 30 });
// 调用action的登录方法 // 调用action的登录方法
userStore.login(loginForm.value).then(() => { userStore.login(loginForm.value).then(() => {
const query = route.query; const query = route.query;
const otherQueryParams = Object.keys(query).reduce((acc, cur) => { const otherQueryParams = Object.keys(query).reduce((acc, cur) => {
if (cur !== "redirect") { if (cur !== "redirect") {
acc[cur] = query[cur]; acc[cur] = query[cur];
} }
return acc; return acc;
}, {}); }, {});
const targetPath = redirect.value || "/"; const targetPath = redirect.value || "/";
if (route.path !== targetPath) { if (route.path !== targetPath) {
router.push({ path: targetPath, query: otherQueryParams }); router.push({ path: targetPath, query: otherQueryParams });
} }
}).catch(() => { }).catch(() => {
loading.value = false; loading.value = false;
// 重新获取验证码 // 重新获取验证码
if (captchaEnabled.value) { if (captchaEnabled.value) {
getCode(); getCode();
} }
}); });
}; };
// 获取验证码 // 获取验证码
@ -202,7 +194,7 @@ const getCode = () => {
if (!captchaEnabled.value) { if (!captchaEnabled.value) {
loginRules.value.code = []; loginRules.value.code = [];
} else { } else {
loginRules.value.code = [{required: true, trigger: "change", message: "请输入验证码"}]; loginRules.value.code = [{ required: true, trigger: "change", message: "请输入验证码" }];
} }
}); });
}; };
@ -212,10 +204,10 @@ const getCookie = () => {
const cookieUsername = Cookies.get("czlis_username"); const cookieUsername = Cookies.get("czlis_username");
const cookieloginYLJG = Cookies.get("czlis_loginYLJG"); const cookieloginYLJG = Cookies.get("czlis_loginYLJG");
//console.log('cookieloginYLJG', cookieloginYLJG); //console.log('cookieloginYLJG', cookieloginYLJG);
if (cookieUsername !== undefined && cookieUsername !== null&& cookieUsername !=="") { if (cookieUsername !== undefined && cookieUsername !== null && cookieUsername !== "") {
loginForm.value.username = cookieUsername; loginForm.value.username = cookieUsername;
} }
if (cookieloginYLJG !== undefined && cookieloginYLJG !== null&& cookieloginYLJG !=="") { if (cookieloginYLJG !== undefined && cookieloginYLJG !== null && cookieloginYLJG !== "") {
loginForm.value.loginParam.loginYLJG = cookieloginYLJG; loginForm.value.loginParam.loginYLJG = cookieloginYLJG;
} }
//console.log('loginForm', loginForm); //console.log('loginForm', loginForm);
@ -223,16 +215,16 @@ const getCookie = () => {
// 获取本地配置 // 获取本地配置
const Localconfig = (localid) => { const Localconfig = (localid) => {
getLocalconfig({localid}).then(res => { getLocalconfig({ localid }).then(res => {
if (res) { if (res) {
const {localconfig, hosplist, oem: oemData} = res; const { localconfig, hosplist, oem: oemData } = res;
// 修复:赋值oem数据,显示动态标题 // 修复:赋值oem数据,显示动态标题
if (oemData) oem.value = oemData; if (oemData) oem.value = oemData;
// console.log('oemData', oemData); // console.log('oemData', oemData);
// console.log('oem', oem.value); // console.log('oem', oem.value);
// 修复:判重后更新下拉选项,避免递归 // 修复:判重后更新下拉选项,避免递归
if (JSON.stringify(selectOptions.value) !== JSON.stringify(hosplist)) { if (JSON.stringify(selectOptions.value) !== JSON.stringify(hosplist)) {
selectOptions.value = hosplist || [{id: '1', name: '总院'}]; selectOptions.value = hosplist || [{ id: '1', name: '总院' }];
// 判重后赋值,避免重复修改触发更新 // 判重后赋值,避免重复修改触发更新
if (!selectOptions.value.some(item => item.id === loginForm.value.hospid)) { if (!selectOptions.value.some(item => item.id === loginForm.value.hospid)) {
loginForm.value.loginParam.loginYLJG = selectOptions.value[0]?.id || '1'; loginForm.value.loginParam.loginYLJG = selectOptions.value[0]?.id || '1';
@ -246,11 +238,11 @@ const Localconfig = (localid) => {
}; };
// 获取指纹并加载配置 // 获取指纹并加载配置
const {getFingerprint} = useFingerprint(); const { getFingerprint } = useFingerprint();
const refreshFingerprint = async () => { const refreshFingerprint = async () => {
try { try {
const res = await getFingerprint(); const res = await getFingerprint();
loginForm.value.loginParam.localid=res.visitorId loginForm.value.loginParam.localid = res.visitorId
Localconfig(res.visitorId); Localconfig(res.visitorId);
} catch (err) { } catch (err) {
console.error("获取指纹失败:", err); console.error("获取指纹失败:", err);
@ -276,15 +268,18 @@ onMounted(() => {
<style lang='scss' scoped> <style lang='scss' scoped>
.login { .login {
display: flex; position: relative;
justify-content: center;
align-items: center;
height: 100vh; height: 100vh;
background-image: url("../assets/images/login-background.jpg"); background-image: url("../assets/images/login-background.jpg");
background-size: cover; background-size: cover;
overflow: hidden;
} }
.login-form { .login-form {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(255, 255, 255, 0.4); background: rgba(255, 255, 255, 0.4);
backdrop-filter: blur(10px); backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
@ -390,7 +385,8 @@ onMounted(() => {
} }
.custom-select { .custom-select {
margin-top: 20px; /* 可根据需求调整数值 */ margin-top: 20px;
/* 可根据需求调整数值 */
} }
/* Tab占位样式 */ /* Tab占位样式 */