|
|
<template> <div id="add-emergency-container"> <!-- 添加急诊 --> <div class="page-header" @click="goBack"> <img class="page-header-icon" src="@/assets/Index/left.svg" /> <div class="page-header-title">添加急诊</div> </div>
<div class="emergency-userid"> <el-row> <el-col :span="5"> <label>样本条形码</label> </el-col> <el-col :span="12" style="padding-left: 20px"> <input type="text" placeholder="请输入样本条形码信息" @focus="showKeyboard('sampleBarcode')" style="width: 400px" :value="emergencyPosition.sampleBarcode" /> </el-col> </el-row> <el-row> <el-col :span="5"> <label>用户ID</label> </el-col> <el-col :span="12" style="padding-left: 20px"> <input type="text" placeholder="请输入用户ID信息" @focus="showKeyboard('userid')" :value="emergencyPosition.userid" style="width: 400px" readonly /> </el-col> </el-row> </div> <hr style="height: 1px; border: none" /> <!-- 急诊项目 --> <div class="emergency-project"> <!-- 项目选择内容,根据需要添加 --> <div class="project-title"> <span>项目选择</span> </div> <div class="project-list"> <div v-for="item in consumableStore.projectsAvailable" :key="item.projId" class="project-item" :style="projectStyle(item)" @click="selectProject(item)" > <span class="proj-name">{{ item.projName }}</span> <span> {{ item.num }}</span> </div> </div>
<div class="project-title"> <span>血液类型</span> </div> <div class="type-list"> <div v-for="item in settingTubeStore.bloodTypes" :key="item.key" @click="selectBloodType(item)" class="blood-button" :class="{ active: emergencyPosition.bloodType === item.key }" > {{ item.name }} </div> </div> </div> <hr style="height: 1px; border: none" /> <!-- 急诊控制 --> <div class="emergency-btns" style="padding: 50px 0"> <el-button class="cancel-button" @click="goBack">取消</el-button> <el-button class="ok-button" @click="confirmHandle">确定</el-button> </div>
<!-- 键盘 --> <transition name="slide-up"> <div class="keyboard" v-if="keyboardVisible"> <SimpleKeyboard :input="currentInputValue" @onChange="handleKeyboardInput" @onKeyPress="handleKeyPress" /> </div> </transition> </div> </template>
<script setup lang="ts"> import { ref, onMounted, onUnmounted } from 'vue' import { useRouter } from 'vue-router' import { insertEmergency } from '@/services/Index/index' import { useEmergencyStore, useConsumablesStore, useDeviceStore, useSettingTestTubeStore, } from '@/store' import type { AddEmergencyInfo } from '@/types/Index' import type { BloodType, ReactionPlateGroup } from '@/websocket/socket' import { ElMessage } from 'element-plus'
defineOptions({ name: 'EmergencyForm', })
const consumableStore = useConsumablesStore() const emergencyStore = useEmergencyStore() const deviceStore = useDeviceStore() const settingTubeStore = useSettingTestTubeStore()
const isProjectActivated = (item: ReactionPlateGroup) => { return emergencyPosition.value.projIds.includes(item.projId!) } //项目选中样式及背景色
const projectStyle = (item: ReactionPlateGroup) => { const activated = isProjectActivated(item) if (activated) { return { border: 'solid 1px transparent', backgroundColor: consumableStore.projIdColorMap[item.projId!], color: '#FFF', } } else { return { border: `solid 1px ${consumableStore.projIdColorMap[item.projId!]}`, backgroundColor: '#FFF', color: consumableStore.projIdColorMap[item.projId!], } } } // 急诊位数据
const emergencyPosition = ref<AddEmergencyInfo>({ sampleBarcode: '', // 样本条形码
userid: '', // 用户ID
projIds: [], // 项目选择
bloodType: '', // 血液类型
})
// 返回事件处理
const router = useRouter() const goBack = () => { router.go(-1) }
// 确认请求
const confirmHandle = async () => { //设备运行状态不能添加急诊
if (deviceStore.deviceState.workState === 'WORKING') { ElMessage.error('设备正在运行,无法添加急诊') return } const emergencyInfo = emergencyPosition.value if (emergencyInfo.projIds.length === 0) { ElMessage.error('请选择项目') return } if (!emergencyInfo.bloodType) { ElMessage.error('请选择血液类型') return } const res = await insertEmergency(emergencyPosition.value) if (res && res.success) { goBack() } else { res && res.data && res.data.info && ElMessage.error(res.data.info) } }
const selectProject = (item: ReactionPlateGroup) => { const projectIndex = emergencyPosition.value.projIds.findIndex( (proj) => proj === item.projId, ) if (projectIndex > -1) { emergencyPosition.value.projIds.splice(projectIndex, 1) } else { emergencyPosition.value.projIds.push(item.projId!) } }
const selectBloodType = (item: { key: BloodType }) => { emergencyPosition.value.bloodType = item.key }
// 处理回显数据
onMounted(() => { if (!emergencyStore.emergencyInfo) { return } if ( deviceStore.deviceState.workState === 'IDLE' || (deviceStore.deviceState.workState === 'PAUSE' && emergencyStore.emergencyInfo!.state === 'TO_BE_PROCESSED') ) { emergencyPosition.value = { sampleBarcode: emergencyStore.emergencyInfo.sampleBarcode, userid: emergencyStore.emergencyInfo.userid, projIds: emergencyStore.emergencyInfo.projIds, bloodType: emergencyStore.emergencyInfo.bloodType, } } }) // 键盘相关状态
const keyboardVisible = ref(false) const currentInputValue = ref('') const currentInputField = ref<'sampleBarcode' | 'userid' | ''>('')
// 显示键盘
const showKeyboard = (field: 'sampleBarcode' | 'userid') => { // 清空当前输入值,避免累加
if (field == 'sampleBarcode') { currentInputValue.value = emergencyPosition.value.sampleBarcode } if (field == 'userid') { currentInputValue.value = emergencyPosition.value.userid } currentInputField.value = field keyboardVisible.value = true }
// 处理键盘输入
const handleKeyboardInput = (value: string) => { if (!currentInputField.value) return // 更新当前输入值
currentInputValue.value = value // 更新对应字段的值
if (currentInputField.value === 'sampleBarcode') { emergencyPosition.value.sampleBarcode = value } else { emergencyPosition.value.userid = value } }
// 处理键盘按键
const handleKeyPress = (button: string) => { if (button === '{enter}') { hideKeyboard() } else if (button === '{bksp}') { // 处理退格键
const value = currentInputValue.value if (value.length > 0) { const newValue = value.slice(0, -1) handleKeyboardInput(newValue) } } }
// 隐藏键盘
const hideKeyboard = () => { keyboardVisible.value = false currentInputField.value = '' currentInputValue.value = '' }
// 在组件卸载时清理状态
onUnmounted(() => { hideKeyboard() }) </script>
<style lang="less" scoped> input { margin-bottom: 20px; padding: 8px 5px; border: 1px solid #ccc; border-radius: 4px; font-size: 32px; transition: box-shadow 0.2s ease; border-radius: 10px; &::placeholder { font-size: 32px; font-weight: 100; color: #d8d8d8; } }
label { margin-bottom: 8px; font-size: 32px; font-weight: 700; }
#add-emergency-container { > * { box-sizing: border-box; } margin: 0; padding: 0; position: relative; height: 100%; width: 100%; background-color: #f4f6f9; box-sizing: border-box;
hr { background-color: #e0e0e0; }
.page-header { width: 100%; height: 100px; display: flex; align-items: center; background-color: #ffffff; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); border-radius: 8px;
.page-header-icon { width: 16.14px; height: 26.76px; margin: 0 20px; cursor: pointer; transition: transform 0.2s ease;
&:hover { transform: scale(1.1); /* 放大效果 */ } }
.page-header-title { font-size: 36px; font-weight: 900; line-height: 1.2; color: #333; } } .emergency-userid { margin-top: 40px; margin-left: 60px; } .emergency-project { width: 100%; padding: 20px 40px; border-radius: 10px; margin-top: 20px;
.project-title { width: 100%; text-align: left; margin-bottom: 10px; font-size: 32px; font-weight: 600; }
.project-list { display: flex; align-items: center; gap: 12px; .project-item { display: flex; flex-direction: column; align-items: center; gap: 5px; padding: 8px 16px; font-size: 24px; border-radius: 8px; min-width: 64px; .proj-name { font-weight: 600; } }
margin-bottom: 24px; } .type-list { display: flex; align-items: center; gap: 12px; padding: 10px 0 10px;
.blood-button { border: 1px solid #5c94fe; border-radius: 8px; padding: 8px 16px; color: #4a90e2; font-size: 32px; &.active { border: 1px solid transparent; background-color: #4a90e2; color: #fff; } } } }
.emergency-btns { width: 100%; height: 120px; display: flex; margin-top: 30px;
display: flex; justify-content: center; align-items: center;
.cancel-button, .ok-button { width: 360px; height: 100px; border-radius: 30px; font-size: 36px; font-weight: 400; margin: 0 10px; border: none; }
.ok-button { background-color: #528dfe; color: white; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); }
.cancel-button { background-color: #f2f2f2; color: black; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); } }
.keyboard { position: fixed; bottom: 0; left: 0; width: 100%; height: 300px; background-color: #f5f7fa; border-top-left-radius: 16px; border-top-right-radius: 16px; box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.1); z-index: 1000; } // 键盘动画
.slide-up-enter-active, .slide-up-leave-active { transition: transform 0.3s ease; } .slide-up-enter-from, .slide-up-leave-to { transform: translateY(100%); } } </style>
|