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.
|
|
<script setup lang="ts"> import { onMounted, onUnmounted, ref } from 'vue' import { dropTipBlock, getConfig, getConfig1, startTest, submitConfig, submitConfig1, testOnce } from '@/services/debug' import { eMessage } from '@/pages/Index/utils'
const tubeData = ref<any[]>([])
const takeTipEachTime = ref(false) onMounted(async () => { const res = await getConfig(); const res1 = await getConfig1(); tubeData.value = res.data.tubeExConfigs takeTipEachTime.value = res1.data.takeTipEachTime || false }) onUnmounted(() => { hideKeyboard() })
const keyboardVisible = ref(false) const currentInputValue = ref('')
const handleKeyboardInput = (inputValue: string) => { currentInputValue.value = inputValue; tubeData.value[inputNum.value].repeatTimes = currentInputValue.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 currentInputValue.value = '' }
const inputNum = ref(0); const showKeyboard = (index: number) => { layout.value = numericLayout; inputNum.value = index; keyboardVisible.value = false setTimeout(() => { keyboardVisible.value = true }, 200) // 清空当前输入值,避免累加
currentInputValue.value = tubeData.value[index].repeatTimes;
}
const layout = ref()
const numericLayout = { default: [ '1 2 3', '4 5 6', '7 8 9', '{bksp} 0 {enter}' // 包含删除和确认键
], }
const start = async () => { // 保存配置
const data = tubeData.value.filter((item) => item.repeatTimes > 10); if (data.length) { eMessage.error('请输入正确的试管次数'); return; } const res = await submitConfig({tubeExConfigs: tubeData.value.map(item => { return { repeatTimes: Number(item.repeatTimes) || 0 } })}); if (res && res.success) { const res1 = await startTest(); if (res1 && res1.success) { eMessage.success('已开始测试') } }
} const moveLiquid = [ { label: '取一次10ul', value: 10 }, { label: '取一次75ul', value: 75 } ]
const move = ref(10)
const lostTip = async () => { const res = await dropTipBlock(); if (res.success) { eMessage.success('操作成功') } }
const checkboxHandle = async () => { const res = await submitConfig1({takeTipEachTime: takeTipEachTime.value}) if (res.success) { eMessage.success('保存成功') } }
const start1 = async () => { const res = await testOnce(move.value); if (res.success) { eMessage.success('已开始移液') } } </script>
<template> <div id="debug-view"> <div class="content-box"> <div class="title"> <span>一致性测试</span> <div> <el-button type="primary" @click="start">开始测试</el-button> </div> </div> <div class="content"> <div v-for="(item, index) in tubeData" :key="index" class="tube-item"> <span>试管{{index + 1}}</span> <el-input style="width: 80px" v-model="item.repeatTimes" type="number" @focus="showKeyboard(index)" readonly /> </div> </div>
</div>
<div class="content-box"> <div class="title"> <span>加样准确度与重复性</span> <div> <el-button @click="lostTip">丢弃tip</el-button> <el-button type="primary" @click="start1">移液操作</el-button> </div></div> <div class="content1"> <div>移液操作: </div> <el-select v-model="move" style="width: 150px"> <el-option v-for="(item, index) in moveLiquid" :key="index" :label="item.label" :value="item.value" /> </el-select> <el-checkbox v-model="takeTipEachTime" @change="checkboxHandle"> 每次丢弃tip</el-checkbox> </div>
</div> <!-- 键盘 --> <transition name="slide-up"> <div class="keyboard" v-if="keyboardVisible"> <SimpleKeyboard :input="currentInputValue" :layout @onChange="handleKeyboardInput" @onKeyPress="handleKeyPress" /> </div> </transition> </div> </template>
<style scoped lang="less"> #debug-view { width: 100%; height: 100%; display: flex; flex-direction: column; background-color: #DDE4E9; padding: 20px; box-sizing: border-box; .content-box { margin-bottom: 20px; box-sizing: border-box; width: 100%; background: #fff; padding: 20px; border-radius: 10px; .content1 { display: flex; padding: 10px; align-items: center; .el-select { margin: 0 20px; } } .content { .tube-item { float: left; height: 50px; display: flex; align-items: center; padding: 10px 0; box-sizing: border-box; span { width: 80px; font-size: 16px; } } }
.title { font-weight: 800; font-size: 20px; display: flex; align-items: center; justify-content: space-between; padding-bottom: 10px; box-sizing: border-box; border-bottom: 1px solid #ccc; }
} }
.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; } </style>
|