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