forked from gzt/A8000
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1024 lines
25 KiB
1024 lines
25 KiB
<template>
|
|
<div id="add-emergency-container">
|
|
<!-- 添加急诊 -->
|
|
<div class="page-header">
|
|
<img class="page-header-icon" src="@/assets/Index/left.svg" @click="goBack"></img>
|
|
<div class="page-header-title">添加急诊</div>
|
|
</div>
|
|
|
|
<!-- 急诊信息 -->
|
|
<!-- <div class="emergency-info" :class="{ 'disable-section': !isEmergencyEnabled }">
|
|
<div class="tab-content">
|
|
<div class="tab-form" :class="{ isOpacity: !isEmergencyEnabled }">
|
|
<div class="line-code">
|
|
<label>样本条形码</label>
|
|
<input type="text" placeholder="请输入样本条形码信息" @focus="showKeyboard('sampleBarcode')"
|
|
:value="emergencyPosition.sampleBarcode"/>
|
|
</div>
|
|
<div class="id-info">
|
|
<label>用户ID</label>
|
|
<input type="text" placeholder="请输入用户ID信息" @focus="showKeyboard('userid')" :value="emergencyPosition.userid"
|
|
:disabled="!isEmergencyEnabled" readonly />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div> -->
|
|
<div class="emergency-main">
|
|
<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"
|
|
:disabled="!isEmergencyEnabled" readonly />
|
|
</el-col>
|
|
</el-row>
|
|
</div>
|
|
<hr style="height: 1px; border: none;" />
|
|
<!-- 急诊项目 -->
|
|
<div class="emergency-project" :class="{ isOpacity: !isEmergencyEnabled }">
|
|
<!-- 项目选择内容,根据需要添加 -->
|
|
<div class="project-title">
|
|
<span>项目选择</span>
|
|
</div>
|
|
<div class="project-list">
|
|
|
|
<div v-for="(item, index) in projects" :key="index" @click="selectProject(item)" :class="[
|
|
isEmergencyEnabled ? 'project-item' : 'disabled-project-item',
|
|
{ 'active-project-item': emergencyPosition.projIds.includes(item.projId) && isEmergencyEnabled },
|
|
]">
|
|
<span :disabled="!isEmergencyEnabled">{{ item.projName }}</span>
|
|
<span :disabled="!isEmergencyEnabled"> {{ item.num }}/25</span>
|
|
</div>
|
|
</div>
|
|
<hr style="width: 98%; margin: 0 auto; background-color: gray; margin: 10px 0;" />
|
|
<div class="project-controller">
|
|
<!-- 血液类型 -->
|
|
<div class="blood-type">
|
|
<div class="project-title">
|
|
<span>血液类型</span>
|
|
</div>
|
|
<div class="type-list">
|
|
<button v-for="(item, index) in bloodTypes" :key="index" @click="selectBloodType(item)"
|
|
:disabled="!isEmergencyEnabled" :class="getTypeClass(item)">
|
|
{{ item.projectName }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<hr style="height: 1px; border: none;" />
|
|
<!-- 急诊控制 -->
|
|
<div class="emergency-controller" :class="{ isOpacity: !isEmergencyEnabled }" style="padding:50px 0">
|
|
<el-button class="cancel-button" @click="cancelHandle">取消</el-button>
|
|
<el-button v-if="showSaveBtn" class="ok-button" :disabled="!isEmergencyEnabled" @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 v-if="showTubeSelector" class="tube-selector-overlay">
|
|
<div class="tube-selector-container">
|
|
<div class="tube-selector-header">
|
|
<span class="title">选择试管位置</span>
|
|
</div>
|
|
<div class="tube-selector-content">
|
|
<div class="tube-grid">
|
|
<button v-for="i in 10" :key="i - 1" :class="['tube-button', { 'occupied': isTubeOccupied(i - 1) }]"
|
|
:disabled="isTubeOccupied(i - 1)" @click="selectTube(i - 1)">
|
|
{{ i }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
import { ref, onMounted, onUnmounted, onActivated, onDeactivated, watch } from 'vue';
|
|
import { useRouter } from 'vue-router';
|
|
import { nanoid } from 'nanoid';
|
|
import { insertEmergency } from '@/services/Index/index';
|
|
import { useEmergencyStore, useConsumablesStore, useDeviceStore } from '@/store';
|
|
import type { ReactionPlate, AddEmergencyInfo } from '@/types/Index';
|
|
import type { EmergencyPosStateMessage, TubeHolderStateMessage } from '@/websocket/socket';
|
|
import { ElMessage } from 'element-plus';
|
|
import { createWebSocket } from '@/websocket/socket';
|
|
import { getServerInfo } from '@/utils/getServerInfo';
|
|
const ws = createWebSocket(getServerInfo().wsUrl);
|
|
const consumableStore = useConsumablesStore();
|
|
const emergencyStore = useEmergencyStore();
|
|
const deviceStore = useDeviceStore();
|
|
// 急诊位开启/关闭状态
|
|
const isEmergencyEnabled = ref(true);//设置表单是否可输入
|
|
|
|
// 模拟项目列表数据
|
|
const projects = ref<ReactionPlate[]>([]);
|
|
onMounted(() => {
|
|
// 延迟加载 projects,确保数据从持久化存储中加载完成
|
|
if (consumableStore.plates.length > 0) {
|
|
projects.value = consumableStore.plates as ReactionPlate[];
|
|
}
|
|
//过滤projId为null的数据
|
|
projects.value = projects.value.filter(item => item.projId)
|
|
})
|
|
|
|
const bloodTypes = ref([
|
|
{
|
|
id: nanoid(),
|
|
projectName: '血清/血浆',
|
|
projectType: "SERUM_OR_PLASMA"
|
|
},
|
|
{
|
|
id: nanoid(),
|
|
projectName: '全血',
|
|
projectType: "WHOLE_BLOOD"
|
|
},
|
|
]);
|
|
|
|
// 获取类型class
|
|
const getTypeClass = (project: { projectType: string }) => {
|
|
return [
|
|
isEmergencyEnabled.value ? 'blood-button' : 'disabled-blood',
|
|
{ 'active-item': bloodType.value === project.projectType && isEmergencyEnabled.value },
|
|
];
|
|
};
|
|
|
|
// 公共状态管理
|
|
const projectName = ref('');
|
|
const bloodType = ref('');
|
|
|
|
// 急诊位数据
|
|
const emergencyPosition = ref<AddEmergencyInfo>({
|
|
sampleBarcode: '', // 样本条形码
|
|
userid: '', // 用户ID
|
|
projIds: [], // 项目选择
|
|
bloodType: '', // 血液类型
|
|
});
|
|
|
|
//获取试管架状态
|
|
const tubeRackState = ref<TubeHolderStateMessage['data']>({
|
|
tubeHolderType: '',
|
|
tubes: [],
|
|
state: 'IDLE'
|
|
});
|
|
|
|
//处理试管架状态
|
|
const handleTubeHolderStateMessage = (data: TubeHolderStateMessage['data']) => {
|
|
tubeRackState.value = data
|
|
}
|
|
|
|
//急诊位可操作状态
|
|
const emergencyStateList = ["EMPTY", "TO_BE_PROCESSED", "PROCESS_COMPLETE", "ERROR"]
|
|
let showSaveBtn = ref<Boolean>(false)
|
|
onMounted(() => {
|
|
ws.connect()
|
|
ws.subscribe<TubeHolderStateMessage>('TubeHolderState', handleTubeHolderStateMessage)
|
|
})
|
|
onActivated(() => {
|
|
ws.connect()
|
|
ws.subscribe<TubeHolderStateMessage>('TubeHolderState', handleTubeHolderStateMessage)
|
|
const { emergencyInfo } = emergencyStore.$state
|
|
console.log('emergencyInfo---', emergencyInfo)
|
|
if(emergencyInfo && emergencyInfo.state){
|
|
const {state, sampleBarcode} = emergencyInfo
|
|
currentInputValue.value = sampleBarcode
|
|
if(emergencyStateList.includes(state)){
|
|
showSaveBtn.value = true
|
|
}
|
|
}
|
|
})
|
|
onDeactivated(() => {
|
|
ws.disconnect()
|
|
ws.unsubscribe<TubeHolderStateMessage>('TubeHolderState', handleTubeHolderStateMessage);
|
|
})
|
|
onUnmounted(() => {
|
|
ws.disconnect()
|
|
ws.unsubscribe<TubeHolderStateMessage>('TubeHolderState', handleTubeHolderStateMessage);
|
|
})
|
|
// 返回事件处理
|
|
const router = useRouter();
|
|
const goBack = () => {
|
|
router.go(-1);
|
|
};
|
|
|
|
// 取消和确认事件
|
|
const cancelHandle = () => {
|
|
router.push('/index/regular/consumables');
|
|
};
|
|
const getProjectInfo = (projIds: number[]) => {
|
|
const projectInfo = projects.value.filter(item => projIds.includes(item.projId));
|
|
return projectInfo;
|
|
}
|
|
// 确认请求
|
|
const confirmHandle = async () => {
|
|
//只有设备暂停状态才能添加急诊
|
|
// if (deviceStore.status !== 'PAUSE') {
|
|
// ElMessage.error('设备未暂停,无法添加急诊');
|
|
// return
|
|
// }
|
|
const emergencyInfo = emergencyPosition.value;
|
|
if(!emergencyInfo.sampleBarcode){
|
|
ElMessage.error('请输入样本条形码');
|
|
return
|
|
}
|
|
if(!emergencyInfo.userid){
|
|
ElMessage.error('请输入用户ID');
|
|
return
|
|
}
|
|
if (emergencyInfo.projIds.length === 0) {
|
|
ElMessage.error('请选择项目');
|
|
return
|
|
}
|
|
if(!emergencyInfo.bloodType){
|
|
ElMessage.error('请选择血液类型');
|
|
return;
|
|
}
|
|
const res = await insertEmergency(emergencyPosition.value);
|
|
if (res.success) {
|
|
|
|
// 构造急诊位数据
|
|
const emergencyData: EmergencyPosStateMessage['data']['tube'] = {
|
|
pos: 1,
|
|
state: "OCCUPIED",
|
|
bloodType: emergencyInfo.bloodType as "SERUM_OR_PLASMA" | "WHOLE_BLOOD",
|
|
sampleBarcode: emergencyInfo.sampleBarcode || "",
|
|
userid: emergencyInfo.userid || "",
|
|
projInfo: getProjectInfo(emergencyInfo.projIds),
|
|
sampleId: `EMERGENCY-${Date.now()}`,
|
|
projIds: emergencyInfo.projIds,
|
|
errors: [],
|
|
isHighTube: false,
|
|
isEmergency: true
|
|
};
|
|
emergencyStore.setInfo(emergencyData);
|
|
|
|
// 跳转到运行中页面并传递数据
|
|
router.push({
|
|
path: "/index/regular/running",
|
|
});
|
|
} else {
|
|
console.log("🚀 ~ confirmHandle ~ res:", res)
|
|
}
|
|
|
|
};
|
|
|
|
// 项目选择事件
|
|
const selectProject = (item: any) => {
|
|
if (!isEmergencyEnabled.value) return;
|
|
if (item === '自动') {
|
|
// 自动选择清空项目
|
|
projectName.value = '自动';
|
|
emergencyPosition.value.projIds = [];
|
|
} else {
|
|
projectName.value = ""
|
|
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: any) => {
|
|
if (!isEmergencyEnabled.value) return;
|
|
if (item === "自动") {
|
|
// 自动选择清空血液类型
|
|
console.log("血液类型为自动");
|
|
bloodType.value = '自动';
|
|
emergencyPosition.value.bloodType = '';
|
|
return
|
|
}
|
|
emergencyPosition.value.bloodType = item.projectType;
|
|
bloodType.value = item.projectType;
|
|
};
|
|
|
|
// 切换急诊位开启/关闭状态
|
|
const toggleEmergency = () => {
|
|
isEmergencyEnabled.value = !isEmergencyEnabled.value;
|
|
if (!isEmergencyEnabled.value) {
|
|
// 清空数据
|
|
emergencyPosition.value = {
|
|
sampleBarcode: '',
|
|
userid: '',
|
|
projIds: [],
|
|
bloodType: '',
|
|
};
|
|
projectName.value = '';
|
|
bloodType.value = '';
|
|
}
|
|
};
|
|
watch(isEmergencyEnabled, (newVal) => {
|
|
if (newVal) {
|
|
showTubeSelector.value = true
|
|
} else {
|
|
selectedTubePos.value = null
|
|
}
|
|
})
|
|
|
|
// 处理回显数据
|
|
onMounted(() => {
|
|
const { emergencyInfo } = emergencyStore.$state
|
|
if (Object.keys(emergencyInfo).length > 0) {
|
|
console.log("🚀 ~ onMounted ~ emergencyInfo:", emergencyInfo)
|
|
isEmergencyEnabled.value = true
|
|
emergencyPosition.value.bloodType = emergencyInfo.bloodType;
|
|
emergencyInfo.projInfo.forEach(item => {
|
|
emergencyPosition.value.projIds.push(item.projId);
|
|
})
|
|
emergencyPosition.value.sampleBarcode = emergencyInfo.sampleBarcode;
|
|
emergencyPosition.value.userid = emergencyInfo.userid;
|
|
bloodType.value = emergencyInfo.bloodType;
|
|
projectName.value = '';
|
|
}
|
|
|
|
});
|
|
// 键盘相关状态
|
|
const keyboardVisible = ref(false)
|
|
const currentInputValue = ref('')
|
|
const currentInputField = ref<'sampleBarcode' | 'userid' | ''>('')
|
|
|
|
// 显示键盘
|
|
const showKeyboard = (field: 'sampleBarcode' | 'userid') => {
|
|
// 清空当前输入值,避免累加
|
|
// currentInputValue.value = ''
|
|
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
|
|
console.log('value----', value)
|
|
// 更新当前输入值
|
|
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()
|
|
})
|
|
|
|
const showTubeSelector = ref(false)
|
|
const selectedTubePos = ref<number | null>(1)
|
|
|
|
// 检查试管是否被占用
|
|
const isTubeOccupied = (pos: number) => {
|
|
return tubeRackState.value.tubes.some(tube =>
|
|
tube.pos === pos && tube.state === 'OCCUPIED'
|
|
)
|
|
}
|
|
|
|
// 选择试管
|
|
const selectTube = (pos: number) => {
|
|
selectedTubePos.value = pos
|
|
showTubeSelector.value = false
|
|
isEmergencyEnabled.value = true
|
|
}
|
|
|
|
</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;
|
|
text-align: left;
|
|
}
|
|
|
|
#add-emergency-container {
|
|
margin: 0;
|
|
padding: 0;
|
|
position: relative;
|
|
height: 100%;
|
|
width: 100%;
|
|
background-color: #f4f6f9;
|
|
box-sizing: border-box;
|
|
|
|
/* 设置背景色 */
|
|
.active-item {
|
|
background-color: #528dfe;
|
|
color: white !important;
|
|
}
|
|
|
|
.isOpacity {
|
|
opacity: 0.4;
|
|
|
|
}
|
|
|
|
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-tabs {
|
|
width: 1200px;
|
|
height: 118px;
|
|
display: flex;
|
|
background-color: #ffffff;
|
|
display: flex;
|
|
transition: all 0.3s ease;
|
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
|
|
border-radius: 8px;
|
|
overflow: hidden;
|
|
margin-top: 20px;
|
|
|
|
.tab-button {
|
|
flex: 1;
|
|
padding: 10px;
|
|
background-color: #f6f6f6;
|
|
border: none;
|
|
cursor: pointer;
|
|
font-size: 40px;
|
|
font-weight: 700;
|
|
line-height: 24px;
|
|
transition: background-color 0.3s ease, color 0.3s ease;
|
|
|
|
&:hover {
|
|
background-color: #eef4ff;
|
|
/* 悬停时背景色 */
|
|
}
|
|
}
|
|
|
|
.tab-button.active {
|
|
background-color: #528dfe;
|
|
color: white;
|
|
}
|
|
}
|
|
|
|
.emergency-info {
|
|
width: 100%;
|
|
height: auto;
|
|
margin-top: 20px;
|
|
border-radius: 8px;
|
|
padding: 20px 0;
|
|
|
|
.tab-content {
|
|
display: flex;
|
|
font-size: 32px;
|
|
font-weight: 700;
|
|
padding: 0 40px;
|
|
|
|
.tab-form {
|
|
flex: 0.7;
|
|
padding: 20px;
|
|
|
|
|
|
.line-code,
|
|
.id-info {
|
|
display: flex;
|
|
flex-direction: column;
|
|
margin-bottom: 20px;
|
|
|
|
label {
|
|
margin-bottom: 8px;
|
|
font-size: 32px;
|
|
font-weight: 700;
|
|
text-align: left;
|
|
}
|
|
|
|
input {
|
|
margin-bottom: 20px;
|
|
padding: 8px 5px;
|
|
border: 1px solid #ccc;
|
|
border-radius: 4px;
|
|
width: 80%;
|
|
font-size: 32px;
|
|
transition: box-shadow 0.2s ease;
|
|
border-radius: 10px;
|
|
&::placeholder {
|
|
font-size: 32px;
|
|
font-weight: 100;
|
|
color: #d8d8d8;
|
|
}
|
|
|
|
//自定义获取焦点后的样式
|
|
&:focus {
|
|
outline: none; // 去掉默认的聚焦边框
|
|
border-color: #528dfe;
|
|
box-shadow: 0 0 5px rgba(181, 189, 181, 0.5);
|
|
/* 添加阴影效果 */
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.active-button {
|
|
flex: 0.3;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
.open-button {
|
|
width: 80%;
|
|
height: 70%;
|
|
background-color: #4caf50;
|
|
/* 开启状态颜色:绿色 */
|
|
color: white;
|
|
font-size: 40px;
|
|
font-weight: 600;
|
|
border: none;
|
|
border-radius: 6px;
|
|
cursor: pointer;
|
|
transition: background-color 0.3s ease, transform 0.2s ease;
|
|
}
|
|
|
|
.close-button {
|
|
width: 80%;
|
|
height: 70%;
|
|
background-color: #f44336;
|
|
/* 关闭状态颜色:红色 */
|
|
color: white;
|
|
font-size: 40px;
|
|
font-weight: 600;
|
|
border: none;
|
|
border-radius: 6px;
|
|
cursor: pointer;
|
|
transition: background-color 0.3s ease, transform 0.2s ease;
|
|
}
|
|
|
|
button {
|
|
width: 100%;
|
|
height: 70%;
|
|
background-color: #528dfe;
|
|
color: white;
|
|
border: none;
|
|
border-radius: 7px;
|
|
cursor: pointer;
|
|
margin-top: 50px;
|
|
font-size: 40px;
|
|
transition: background-color 0.3s ease, transform 0.2s ease;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
.emergency-project {
|
|
width: 100%;
|
|
padding: 20px 40px;
|
|
border-radius: 10px;
|
|
margin-top: 20px;
|
|
box-sizing: border-box;
|
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
|
|
.disabled-item {
|
|
color: gray;
|
|
border: 1px solid gray;
|
|
height: 70px;
|
|
width: 150px;
|
|
background-color: white;
|
|
border-radius: 8px;
|
|
margin-right: 20px;
|
|
font-size: 32px;
|
|
}
|
|
|
|
|
|
|
|
|
|
.project-auto {
|
|
height: 70px;
|
|
width: 150px;
|
|
border: 1px solid #4a90e2;
|
|
color: #4a90e2;
|
|
border-radius: 8px;
|
|
margin-right: 20px;
|
|
cursor: pointer;
|
|
font-size: 32px;
|
|
transition: all 0.3s ease
|
|
}
|
|
|
|
//禁用状态下的样式
|
|
|
|
|
|
.project-title {
|
|
width: 100%;
|
|
text-align: left;
|
|
margin-bottom: 10px;
|
|
gap: 10px;
|
|
|
|
span {
|
|
font-size: 32px;
|
|
font-weight: 700;
|
|
}
|
|
}
|
|
|
|
.project-list {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 10px 0;
|
|
border-radius: 8px;
|
|
justify-content: flex-start;
|
|
|
|
.active-project-item {
|
|
background-color: #528dfe !important;
|
|
color: white !important;
|
|
}
|
|
|
|
.disabled-item {
|
|
color: gray;
|
|
border: 1px solid gray;
|
|
height: 70px;
|
|
width: 150px;
|
|
background-color: white;
|
|
border-radius: 8px;
|
|
margin-right: 20px;
|
|
font-size: 32px;
|
|
}
|
|
|
|
.project-item {
|
|
width: 150px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
padding: 0 10px;
|
|
color: #4a90e2;
|
|
background-color: #f2f2f2;
|
|
font-size: 24px;
|
|
text-align: center;
|
|
position: relative;
|
|
border-radius: 8px;
|
|
|
|
&::before {
|
|
content: "";
|
|
position: absolute;
|
|
left: 0;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
width: 1px;
|
|
height: 60%;
|
|
background-color: #ccc;
|
|
}
|
|
}
|
|
|
|
.disabled-project-item {
|
|
width: 150px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
padding: 0 10px;
|
|
color: gray;
|
|
font-size: 24px;
|
|
text-align: center;
|
|
position: relative;
|
|
background-color: #f2f2f2;
|
|
border-radius: 8px;
|
|
pointer-events: none;
|
|
|
|
&::before {
|
|
content: "";
|
|
position: absolute;
|
|
left: 0;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
width: 1px;
|
|
height: 60%;
|
|
background-color: #ccc;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
.project-controller {
|
|
display: flex;
|
|
width: 100%;
|
|
margin: 20px 0;
|
|
justify-content: space-between;
|
|
gap: 20px;
|
|
|
|
.blood-type {
|
|
width: 60%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
|
|
.type-list {
|
|
display: flex;
|
|
gap: 15px;
|
|
justify-content: space-between;
|
|
padding: 10px 0 10px;
|
|
|
|
.blood-button,
|
|
.disabled-blood {
|
|
flex: 1;
|
|
min-width: 150px;
|
|
padding: 15px;
|
|
font-size: 32px;
|
|
border-radius: 8px;
|
|
text-align: center;
|
|
transition: all 0.3s ease
|
|
}
|
|
|
|
.blood-button {
|
|
border: 1px solid #5c94fe;
|
|
border-radius: 8px;
|
|
padding: 0;
|
|
color: #4a90e2;
|
|
border-radius: 8px;
|
|
margin-right: 20px;
|
|
cursor: pointer;
|
|
font-size: 32px;
|
|
}
|
|
|
|
.disabled-blood {
|
|
|
|
border: 1px solid gray;
|
|
border-radius: 8px;
|
|
padding: 0;
|
|
color: gray;
|
|
border-radius: 8px;
|
|
margin-right: 20px;
|
|
cursor: none;
|
|
font-size: 32px;
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
.sample-attenuation {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
position: relative;
|
|
|
|
.active-item {
|
|
background-color: #528dfe;
|
|
color: white !important;
|
|
}
|
|
|
|
.project-title {
|
|
margin-left: 20px;
|
|
}
|
|
|
|
&::before {
|
|
content: "";
|
|
position: absolute;
|
|
left: 0;
|
|
top: 70%;
|
|
transform: translateY(-50%);
|
|
width: 2px;
|
|
height: 40%;
|
|
background-color: #ccc;
|
|
}
|
|
|
|
.sample-button {
|
|
width: 80%;
|
|
margin: 0 20px;
|
|
height: 74px;
|
|
border-radius: 8px;
|
|
border: 1px solid #5c94fe;
|
|
color: #4a90e2;
|
|
border-radius: 8px;
|
|
margin-right: 20px;
|
|
cursor: pointer;
|
|
font-size: 32px;
|
|
}
|
|
|
|
.disabled-sample-button {
|
|
width: 80%;
|
|
margin: 0 20px;
|
|
height: 74px;
|
|
border-radius: 8px;
|
|
border: 1px solid gray;
|
|
color: gray;
|
|
border-radius: 8px;
|
|
margin-right: 20px;
|
|
cursor: pointer;
|
|
font-size: 32px;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.emergency-controller {
|
|
width: 100%;
|
|
height: 120px;
|
|
display: flex;
|
|
margin-top: 20px;
|
|
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
|
|
.cancel-button,
|
|
.ok-button {
|
|
width: 365px;
|
|
height: 100px;
|
|
border-radius: 30px;
|
|
font-size: 40px;
|
|
font-weight: 400;
|
|
margin: 0 10px;
|
|
border: none;
|
|
cursor: pointer;
|
|
transition: background-color 0.3s ease, transform 0.2s ease;
|
|
}
|
|
|
|
.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%);
|
|
}
|
|
|
|
.tube-selector-overlay {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100vw;
|
|
height: 100vh;
|
|
background: rgba(0, 0, 0, 0.7);
|
|
backdrop-filter: blur(4px);
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
z-index: 10000;
|
|
}
|
|
|
|
.tube-selector-container {
|
|
background: white;
|
|
border-radius: 8px;
|
|
padding: 20px;
|
|
width: 600px;
|
|
|
|
.tube-selector-header {
|
|
text-align: center;
|
|
margin-bottom: 20px;
|
|
|
|
.title {
|
|
font-size: 32px;
|
|
font-weight: bold;
|
|
}
|
|
}
|
|
|
|
.tube-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(5, 1fr);
|
|
gap: 15px;
|
|
padding: 20px;
|
|
|
|
.tube-button {
|
|
padding: 20px;
|
|
font-size: 24px;
|
|
border: 2px solid #409eff;
|
|
border-radius: 8px;
|
|
background: white;
|
|
cursor: pointer;
|
|
transition: all 0.3s;
|
|
|
|
&:hover:not(:disabled) {
|
|
background: #409eff;
|
|
color: white;
|
|
}
|
|
|
|
&.occupied {
|
|
border-color: #909399;
|
|
background: #f4f4f5;
|
|
cursor: not-allowed;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.emergency-main{
|
|
margin-top:40px;
|
|
margin-left:80px
|
|
}
|
|
</style>
|