forked from gzt/A8000
5 changed files with 383 additions and 3 deletions
-
51src/pages/Index/Index.vue
-
250src/pages/Index/debug.vue
-
5src/router/router.ts
-
68src/services/debug/index.ts
-
12src/store/modules/useSystemStore.ts
@ -0,0 +1,250 @@ |
|||
<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 save = 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.success) { |
|||
eMessage.success('保存成功') |
|||
} |
|||
|
|||
} |
|||
|
|||
const start = async () => { |
|||
// 开始测试 |
|||
const res = await startTest(); |
|||
if (res.success) { |
|||
eMessage.success('已开始测试') |
|||
} |
|||
} |
|||
|
|||
const moveLiquid = [ |
|||
{ |
|||
label: '取一次5ul', |
|||
value: 5 |
|||
}, |
|||
{ |
|||
label: '取一次10ul', |
|||
value: 10 |
|||
} |
|||
] |
|||
|
|||
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">一致性测试</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> |
|||
<el-button type="primary" @click="save">保存配置</el-button> |
|||
<el-button type="primary" @click="start">开始测试</el-button> |
|||
|
|||
</div> |
|||
|
|||
<div class="content-box"> |
|||
<div class="title">加样准确度与重复性</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> |
|||
|
|||
|
|||
|
|||
<el-button @click="lostTip">丢弃tip</el-button> |
|||
<el-button type="primary" @click="start1">移液操作</el-button> |
|||
|
|||
</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: flex-start; |
|||
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> |
@ -0,0 +1,68 @@ |
|||
import apiClient from '../../utils/axios' |
|||
|
|||
const baseUrl = '/api/v1/engineer/experiment-consistency-testing/' |
|||
//添加急诊信息
|
|||
export const getConfig = async () => { |
|||
try { |
|||
const res = await apiClient.post(baseUrl + 'getConfig') |
|||
return res.data |
|||
} catch (error) { |
|||
console.log(error) |
|||
} |
|||
} |
|||
|
|||
export const submitConfig = async (params: any) => { |
|||
try { |
|||
const res = await apiClient.post(baseUrl + 'submitConfig', params) |
|||
return res.data |
|||
} catch (error) { |
|||
console.log(error) |
|||
} |
|||
} |
|||
|
|||
export const startTest = async () => { |
|||
try { |
|||
const res = await apiClient.post(baseUrl + 'startTest') |
|||
return res.data |
|||
} catch (error) { |
|||
console.log(error) |
|||
} |
|||
} |
|||
|
|||
const baseUrl1 = '/api/v1/engineer/liquid-absorption-and-distribution-test/' |
|||
export const getConfig1 = async () => { |
|||
try { |
|||
const res = await apiClient.post(baseUrl1 + 'getConfig') |
|||
return res.data |
|||
} catch (error) { |
|||
console.log(error) |
|||
} |
|||
} |
|||
|
|||
export const submitConfig1 = async (params:any) => { |
|||
try { |
|||
const res = await apiClient.post(baseUrl1 + 'submitConfig', params) |
|||
return res.data |
|||
} catch (error) { |
|||
console.log(error) |
|||
} |
|||
} |
|||
|
|||
export const dropTipBlock = async () => { |
|||
try { |
|||
const res = await apiClient.post(baseUrl1 + 'dropTipBlock') |
|||
return res.data |
|||
} catch (error) { |
|||
console.log(error) |
|||
} |
|||
} |
|||
|
|||
export const testOnce = async (params: any) => { |
|||
try { |
|||
const res = await apiClient.post(baseUrl1 + 'testOnce' , params) |
|||
return res.data |
|||
} catch (error) { |
|||
console.log(error) |
|||
} |
|||
} |
|||
|
@ -0,0 +1,12 @@ |
|||
import { defineStore } from 'pinia' |
|||
|
|||
export const useSystemStore = defineStore('system', { |
|||
state: () => ({ |
|||
isDebug: false, |
|||
}), |
|||
actions: { |
|||
updateDebug() { |
|||
this.isDebug = !this.isDebug |
|||
} |
|||
}, |
|||
}) |
Write
Preview
Loading…
Cancel
Save
Reference in new issue