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.
 
 
 
 

255 lines
5.6 KiB

<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>