forked from gzt/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.
357 lines
8.4 KiB
357 lines
8.4 KiB
<template>
|
|
<div id="changeUser-container">
|
|
<!-- 顶部导航 -->
|
|
<div class="header">
|
|
<div class="header-left" @click.stop="goBack">
|
|
<img src="@/assets/Index/left.svg" alt="返回" />
|
|
<span class="title">患者信息</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 主要内容区域 -->
|
|
<div class="content">
|
|
<div class="sample-section" v-for="(group, idx) in tubeGroups" :key="idx">
|
|
<!-- 左侧标题栏 -->
|
|
<div class="section-labels">
|
|
<div class="label-column">
|
|
<div class="label-item">
|
|
<span class="label">条形码</span>
|
|
</div>
|
|
<div class="label-item">
|
|
<span class="label">用户ID</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 右侧样本展示 -->
|
|
<div class="samples-grid">
|
|
<div class="sample-item" v-for="item in group" :key="item.tubeIndex">
|
|
<div class="sample-content">
|
|
<!-- 序号 -->
|
|
<div class="item-index">{{ item.tubeIndex + 1 }}</div>
|
|
|
|
<!-- 试管圆圈 -->
|
|
<div class="tube-circle">
|
|
<Tube
|
|
:tube="item"
|
|
:showNum="false"
|
|
:showUserId="false"
|
|
@clickTubeItem=""
|
|
/>
|
|
</div>
|
|
|
|
<!-- 输入框组 -->
|
|
<div class="inputs">
|
|
<input
|
|
class="input-field"
|
|
:class="{ onFocus: isFocused('barcode', item) }"
|
|
v-model="item.sampleBarcode"
|
|
placeholder="条形码"
|
|
@focus="showKeyboard('barcode', item)"
|
|
readonly
|
|
/>
|
|
<input
|
|
class="input-field"
|
|
:class="{ onFocus: isFocused('userid', item) }"
|
|
v-model="item.userid"
|
|
placeholder="用户ID"
|
|
@focus="showKeyboard('userid', item)"
|
|
readonly
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 底部按钮 -->
|
|
<div class="footer">
|
|
<button class="btn cancel" @click="goBack">取消</button>
|
|
<button class="btn confirm" @click="confirmChange">确定</button>
|
|
</div>
|
|
<!-- 键盘组件 -->
|
|
<transition name="slide-up">
|
|
<div class="keyboard-container">
|
|
<SimpleKeyboard
|
|
v-if="keyboardVisible"
|
|
:input="currentInputValue"
|
|
@onChange="handleKeyboardInput"
|
|
@onKeyPress="handleKeyPress"
|
|
/>
|
|
</div>
|
|
</transition>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { computed, onActivated, ref, watch } from 'vue'
|
|
import { useRouter } from 'vue-router'
|
|
import * as R from 'ramda'
|
|
import { useTestTubeStore, useConsumablesStore } from '../../../store'
|
|
import { eventBus } from '../../../eventBus'
|
|
import SimpleKeyboard from '../../../components/SimpleKeyboard.vue'
|
|
import Tube from '../components/TestTube/Tube.vue'
|
|
import { updateTubeConfig } from '../../../services'
|
|
import { ElMessage } from 'element-plus'
|
|
|
|
const router = useRouter()
|
|
|
|
const consumables = useConsumablesStore()
|
|
const tubeStore = useTestTubeStore()
|
|
|
|
defineOptions({
|
|
name: 'TubeUserId',
|
|
})
|
|
const tubeGroups = ref([
|
|
R.clone(tubeStore.tubeRack.tubeSettings.slice(0, 5)),
|
|
R.clone(tubeStore.tubeRack.tubeSettings.slice(5, 10)),
|
|
])
|
|
|
|
const keyboardVisible = ref(false)
|
|
const currentInputValue = ref('')
|
|
const currentInput = ref({
|
|
type: 'barcode',
|
|
item: null,
|
|
})
|
|
|
|
const isFocused = (type, item) => {
|
|
if (
|
|
currentInput.value.item &&
|
|
item.tubeIndex === currentInput.value.item.tubeIndex &&
|
|
type === currentInput.value.type
|
|
) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
//返回试管页面
|
|
const goBack = () => {
|
|
//router.push('/index/regular/test-tube')
|
|
router.back()
|
|
}
|
|
|
|
//确认事件
|
|
const confirmChange = async () => {
|
|
const settings = R.flatten(tubeGroups.value)
|
|
const res = await updateTubeConfig({
|
|
uuid: tubeStore.tubeRack.uuid,
|
|
setting: settings,
|
|
})
|
|
if (res.success) {
|
|
tubeStore.tubeRack.tubeSettings = settings
|
|
eventBus.emit('AppTubeSettingUpdateEvent');
|
|
goBack()
|
|
} else {
|
|
ElMessage.error('更新失败')
|
|
}
|
|
}
|
|
|
|
// 显示键盘
|
|
const showKeyboard = (type, item) => {
|
|
keyboardVisible.value = true
|
|
currentInput.value = { type, item }
|
|
currentInputValue.value =
|
|
type === 'barcode' ? item.sampleBarcode : item.userid
|
|
}
|
|
|
|
// 处理键盘输入
|
|
const handleKeyboardInput = (input) => {
|
|
if (!currentInput.value.item) return
|
|
|
|
const groupIdx = currentInput.value.item.tubeIndex < 5 ? 0 : 1
|
|
const idxOffset = groupIdx === 1 ? 5 : 0
|
|
const tubeIdx = currentInput.value.item.tubeIndex - idxOffset
|
|
if (currentInput.value.type === 'barcode') {
|
|
currentInput.value.item.sampleBarcode = input
|
|
tubeGroups.value[groupIdx][tubeIdx].sampleBarcode = input
|
|
} else {
|
|
currentInput.value.item.userid = input
|
|
tubeGroups.value[groupIdx][tubeIdx].userid = input
|
|
}
|
|
currentInputValue.value = input
|
|
// console.log(tubeGroups.value[groupIdx])
|
|
}
|
|
|
|
// 处理键盘按键
|
|
const handleKeyPress = (button) => {
|
|
if (button === '{enter}') {
|
|
keyboardVisible.value = false
|
|
currentInputValue.value = ''
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
#changeUser-container {
|
|
width: 100%;
|
|
height: 95vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
position: relative;
|
|
overflow: hidden;
|
|
|
|
.header {
|
|
height: 80px;
|
|
background-color: #fff;
|
|
padding: 0 20px;
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
.header-left {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
|
|
img {
|
|
width: 24px;
|
|
height: 24px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.title {
|
|
font-size: 28px;
|
|
color: #303133;
|
|
}
|
|
}
|
|
}
|
|
|
|
.content {
|
|
padding: 16px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 20px;
|
|
overflow: hidden;
|
|
|
|
.sample-section {
|
|
border-radius: 8px;
|
|
padding: 20px;
|
|
display: flex;
|
|
// height: 380px;
|
|
|
|
.section-labels {
|
|
width: 100px;
|
|
display: flex;
|
|
flex-direction: column-reverse;
|
|
padding-bottom: 16px;
|
|
|
|
.label-column {
|
|
> * {
|
|
box-sizing: border-box;
|
|
}
|
|
.label-item {
|
|
margin-bottom: 16px;
|
|
.label {
|
|
font-size: 24px;
|
|
font-weight: 600;
|
|
color: #606266;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.samples-grid {
|
|
flex: 1;
|
|
display: grid;
|
|
grid-template-columns: repeat(5, 1fr);
|
|
gap: 12px;
|
|
|
|
.sample-item {
|
|
// background-color: #f5f7fa;
|
|
border-radius: 12px;
|
|
padding: 12px;
|
|
|
|
.sample-content {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
|
|
.item-index {
|
|
font-size: 22px;
|
|
color: #333;
|
|
margin-bottom: 8px;
|
|
}
|
|
.tube-circle {
|
|
height: 80px;
|
|
}
|
|
|
|
.inputs {
|
|
width: 100%;
|
|
margin-top: 24px;
|
|
|
|
.input-field {
|
|
&.onFocus {
|
|
border: solid 2px #333;
|
|
}
|
|
width: 100%;
|
|
height: 36px;
|
|
border: 1px solid #aaa;
|
|
border-radius: 4px;
|
|
margin-bottom: 14px;
|
|
font-size: 20px;
|
|
font-weight: 600;
|
|
text-align: center;
|
|
background-color: #fff;
|
|
|
|
&::placeholder {
|
|
color: #c0c4cc;
|
|
font-size: 18px;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.footer {
|
|
height: 80px;
|
|
padding: 10px 20px;
|
|
background-color: #fff;
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: 16px;
|
|
|
|
.btn {
|
|
width: 320px;
|
|
height: 60px;
|
|
border-radius: 30px;
|
|
font-size: 24px;
|
|
font-weight: normal;
|
|
|
|
&.cancel {
|
|
background-color: #f5f7fa;
|
|
color: #606266;
|
|
border: 1px solid #dcdfe6;
|
|
}
|
|
|
|
&.confirm {
|
|
background-color: #409eff;
|
|
color: #fff;
|
|
}
|
|
}
|
|
}
|
|
|
|
.keyboard-container {
|
|
position: absolute;
|
|
bottom: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 20vh;
|
|
background-color: #fff;
|
|
}
|
|
|
|
// 键盘动画
|
|
.slide-up-enter-active,
|
|
.slide-up-leave-active {
|
|
transition: transform 0.3s ease;
|
|
}
|
|
|
|
.slide-up-enter-from,
|
|
.slide-up-leave-to {
|
|
transform: translateY(100%);
|
|
}
|
|
}
|
|
</style>
|