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.

254 lines
5.6 KiB

3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
  1. <script setup lang="ts">
  2. import { onMounted, onUnmounted, ref } from 'vue'
  3. import { dropTipBlock, getConfig, getConfig1, startTest, submitConfig, submitConfig1, testOnce } from '@/services/debug'
  4. import { eMessage } from '@/pages/Index/utils'
  5. const tubeData = ref<any[]>([])
  6. const takeTipEachTime = ref(false)
  7. onMounted(async () => {
  8. const res = await getConfig();
  9. const res1 = await getConfig1();
  10. tubeData.value = res.data.tubeExConfigs
  11. takeTipEachTime.value = res1.data.takeTipEachTime || false
  12. })
  13. onUnmounted(() => {
  14. hideKeyboard()
  15. })
  16. const keyboardVisible = ref(false)
  17. const currentInputValue = ref('')
  18. const handleKeyboardInput = (inputValue: string) => {
  19. currentInputValue.value = inputValue;
  20. tubeData.value[inputNum.value].repeatTimes = currentInputValue.value;
  21. }
  22. // 处理键盘按键
  23. const handleKeyPress = (button: string) => {
  24. if (button === '{enter}') {
  25. hideKeyboard()
  26. } else if (button === '{bksp}') {
  27. // 处理退格键
  28. const value = currentInputValue.value
  29. if (value.length > 0) {
  30. const newValue = value.slice(0, -1)
  31. handleKeyboardInput(newValue)
  32. }
  33. }
  34. }
  35. // 隐藏键盘
  36. const hideKeyboard = () => {
  37. keyboardVisible.value = false
  38. currentInputValue.value = ''
  39. }
  40. const inputNum = ref(0);
  41. const showKeyboard = (index: number) => {
  42. layout.value = numericLayout;
  43. inputNum.value = index;
  44. keyboardVisible.value = false
  45. setTimeout(() => {
  46. keyboardVisible.value = true
  47. }, 200)
  48. // 清空当前输入值,避免累加
  49. currentInputValue.value = tubeData.value[index].repeatTimes;
  50. }
  51. const layout = ref()
  52. const numericLayout = {
  53. default: [
  54. '1 2 3',
  55. '4 5 6',
  56. '7 8 9',
  57. '{bksp} 0 {enter}' // 包含删除和确认键
  58. ],
  59. }
  60. const start = async () => {
  61. // 保存配置
  62. const data = tubeData.value.filter((item) => item.repeatTimes > 10);
  63. if (data.length) {
  64. eMessage.error('请输入正确的试管次数');
  65. return;
  66. }
  67. const res = await submitConfig({tubeExConfigs: tubeData.value.map(item => {
  68. return {
  69. repeatTimes: Number(item.repeatTimes) || 0
  70. }
  71. })});
  72. if (res && res.success) {
  73. const res1 = await startTest();
  74. if (res1 && res1.success) {
  75. eMessage.success('已开始测试')
  76. }
  77. }
  78. }
  79. const moveLiquid = [
  80. {
  81. label: '取一次10ul',
  82. value: 10
  83. },
  84. {
  85. label: '取一次75ul',
  86. value: 75
  87. }
  88. ]
  89. const move = ref(10)
  90. const lostTip = async () => {
  91. const res = await dropTipBlock();
  92. if (res.success) {
  93. eMessage.success('操作成功')
  94. }
  95. }
  96. const checkboxHandle = async () => {
  97. const res = await submitConfig1({takeTipEachTime: takeTipEachTime.value})
  98. if (res.success) {
  99. eMessage.success('保存成功')
  100. }
  101. }
  102. const start1 = async () => {
  103. const res = await testOnce(move.value);
  104. if (res.success) {
  105. eMessage.success('已开始移液')
  106. }
  107. }
  108. </script>
  109. <template>
  110. <div id="debug-view">
  111. <div class="content-box">
  112. <div class="title">
  113. <span>一致性测试</span>
  114. <div>
  115. <el-button type="primary" @click="start">开始测试</el-button>
  116. </div>
  117. </div>
  118. <div class="content">
  119. <div v-for="(item, index) in tubeData" :key="index" class="tube-item">
  120. <span>试管{{index + 1}}</span>
  121. <el-input
  122. style="width: 80px"
  123. v-model="item.repeatTimes"
  124. type="number"
  125. @focus="showKeyboard(index)"
  126. readonly
  127. />
  128. </div>
  129. </div>
  130. </div>
  131. <div class="content-box">
  132. <div class="title">
  133. <span>加样准确度与重复性</span>
  134. <div>
  135. <el-button @click="lostTip">丢弃tip</el-button>
  136. <el-button type="primary" @click="start1">移液操作</el-button>
  137. </div></div>
  138. <div class="content1">
  139. <div>移液操作: </div>
  140. <el-select v-model="move" style="width: 150px">
  141. <el-option
  142. v-for="(item, index) in moveLiquid"
  143. :key="index"
  144. :label="item.label"
  145. :value="item.value"
  146. />
  147. </el-select>
  148. <el-checkbox v-model="takeTipEachTime" @change="checkboxHandle"> 每次丢弃tip</el-checkbox>
  149. </div>
  150. </div>
  151. <!-- 键盘 -->
  152. <transition name="slide-up">
  153. <div class="keyboard" v-if="keyboardVisible">
  154. <SimpleKeyboard
  155. :input="currentInputValue"
  156. :layout
  157. @onChange="handleKeyboardInput"
  158. @onKeyPress="handleKeyPress"
  159. />
  160. </div>
  161. </transition>
  162. </div>
  163. </template>
  164. <style scoped lang="less">
  165. #debug-view {
  166. width: 100%;
  167. height: 100%;
  168. display: flex;
  169. flex-direction: column;
  170. background-color: #DDE4E9;
  171. padding: 20px;
  172. box-sizing: border-box;
  173. .content-box {
  174. margin-bottom: 20px;
  175. box-sizing: border-box;
  176. width: 100%;
  177. background: #fff;
  178. padding: 20px;
  179. border-radius: 10px;
  180. .content1 {
  181. display: flex;
  182. padding: 10px;
  183. align-items: center;
  184. .el-select {
  185. margin: 0 20px;
  186. }
  187. }
  188. .content {
  189. .tube-item {
  190. float: left;
  191. height: 50px;
  192. display: flex;
  193. align-items: center;
  194. padding: 10px 0;
  195. box-sizing: border-box;
  196. span {
  197. width: 80px;
  198. font-size: 16px;
  199. }
  200. }
  201. }
  202. .title {
  203. font-weight: 800;
  204. font-size: 20px;
  205. display: flex;
  206. align-items: center;
  207. justify-content: space-between;
  208. padding-bottom: 10px;
  209. box-sizing: border-box;
  210. border-bottom: 1px solid #ccc;
  211. }
  212. }
  213. }
  214. .keyboard {
  215. position: fixed;
  216. bottom: 0;
  217. left: 0;
  218. width: 100%;
  219. height: 300px;
  220. background-color: #f5f7fa;
  221. border-top-left-radius: 16px;
  222. border-top-right-radius: 16px;
  223. box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.1);
  224. z-index: 1000;
  225. }
  226. </style>