|
|
@ -1,50 +1,56 @@ |
|
|
|
<template> |
|
|
|
<div id="project-selector"> |
|
|
|
<hr /> |
|
|
|
<div class="emergency-project"> |
|
|
|
<div class="project-title"> |
|
|
|
<span>项目选择</span> |
|
|
|
</div> |
|
|
|
<div class="project-list"> |
|
|
|
<button @click="toggleAutoProject" :class="['project-auto', { 'active-item': isSelected(0) }]"> |
|
|
|
自动 |
|
|
|
</button> |
|
|
|
<div v-for="(item, index) in projects" :key="index" @click="toggleProject(item)" :class="[ |
|
|
|
'project-item', |
|
|
|
{ 'active-project-item': isSelected(item.projId) }, |
|
|
|
]" :style="getStyle(item)"> |
|
|
|
<span>{{ item.projName }}</span> |
|
|
|
<span> {{ item.num }}/25</span> |
|
|
|
<teleport to="body"> |
|
|
|
<div class="project-selector-overlay" v-if="visible"> |
|
|
|
<div id="project-selector" class="project-selector-modal"> |
|
|
|
<div class="modal-header"> |
|
|
|
<span class="title">项目选择</span> |
|
|
|
<img src="@/assets/del-icon copy.svg" alt="关闭" class="close-icon" @click="handleCancel" /> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<hr style=" |
|
|
|
width: 98%; |
|
|
|
margin: 0 auto; |
|
|
|
background-color: gray; |
|
|
|
margin: 10px 0; |
|
|
|
" /> |
|
|
|
<div class="project-controller"> |
|
|
|
<div class="blood-type"> |
|
|
|
<div class="project-title"> |
|
|
|
<span>血液类型</span> |
|
|
|
</div> |
|
|
|
<div class="type-list"> |
|
|
|
<button @click="toggleAutoBloodType" :class="['project-auto', { 'active-item': bloodType === '自动' }]"> |
|
|
|
|
|
|
|
<div class="emergency-project"> |
|
|
|
<div class="project-list"> |
|
|
|
<button @click="toggleAutoProject" :class="['project-auto', { 'active-item': isSelected(0) }]"> |
|
|
|
自动 |
|
|
|
</button> |
|
|
|
<button v-for="(item, index) in bloodTypes" :key="index" @click="selectBloodType(item)" |
|
|
|
:class="getTypeClass(item)"> |
|
|
|
{{ item.projectName }} |
|
|
|
</button> |
|
|
|
<div v-for="(item, index) in projects" :key="index" @click="toggleProject(item)" :class="[ |
|
|
|
'project-item', |
|
|
|
{ 'active-project-item': isSelected(item.projId) }, |
|
|
|
]" :style="getStyle(item)"> |
|
|
|
<span>{{ item.projName }}</span> |
|
|
|
<span> {{ item.num }}/25</span> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<hr style=" |
|
|
|
width: 98%; |
|
|
|
margin: 0 auto; |
|
|
|
background-color: gray; |
|
|
|
margin: 10px 0; |
|
|
|
" /> |
|
|
|
<div class="project-controller"> |
|
|
|
<div class="blood-type"> |
|
|
|
<div class="project-title"> |
|
|
|
<span>血液类型</span> |
|
|
|
</div> |
|
|
|
<div class="type-list"> |
|
|
|
<button @click="toggleAutoBloodType" :class="['project-auto', { 'active-item': bloodType === '自动' }]"> |
|
|
|
自动 |
|
|
|
</button> |
|
|
|
<button v-for="(item, index) in bloodTypes" :key="index" @click="selectBloodType(item)" |
|
|
|
:class="getTypeClass(item)"> |
|
|
|
{{ item.projectName }} |
|
|
|
</button> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div class="actions"> |
|
|
|
<button class="confirm-button" @click="handleConfirm">确认</button> |
|
|
|
<button class="cancel-button" @click="handleCancel">取消</button> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div class="actions"> |
|
|
|
<button class="confirm-button" @click="handleConfirm">确认</button> |
|
|
|
<button class="cancel-button" @click="handleCancel">取消</button> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</teleport> |
|
|
|
</template> |
|
|
|
|
|
|
|
<script setup lang="ts"> |
|
|
@ -52,13 +58,13 @@ import { ref } from 'vue' |
|
|
|
import type { ReactionPlate } from '../../../../types/Index' |
|
|
|
import { nanoid } from 'nanoid' |
|
|
|
import { useConsumablesStore, useSettingTestTubeStore } from '../../../../store' |
|
|
|
import { updateTubeConfig } from '../../../../services/Index/Test-tube/test-tube' |
|
|
|
|
|
|
|
const consumables = useConsumablesStore() |
|
|
|
const settingTestTubeStore = useSettingTestTubeStore() |
|
|
|
const emit = defineEmits<{ |
|
|
|
(e: 'confirm'): void |
|
|
|
(e: 'cancel'): void |
|
|
|
(e: 'update:visible', value: boolean): void |
|
|
|
(e: 'updateSample', data: { projectIds: number[]; bloodType: string }): void |
|
|
|
}>() |
|
|
|
// 清空选中状态 |
|
|
@ -79,7 +85,7 @@ const bloodTypes = ref([ |
|
|
|
{ |
|
|
|
id: nanoid(), |
|
|
|
projectName: '血清/血浆', |
|
|
|
projectType: 'SEUM_OR_PLASMA', |
|
|
|
projectType: 'SERUM_OR_PLASMA', |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: nanoid(), |
|
|
@ -114,7 +120,7 @@ const toggleProject = (project: ReactionPlate) => { |
|
|
|
emitUpdate() // 发送更新 |
|
|
|
} |
|
|
|
|
|
|
|
// 切换“自动”项目的激活状态 |
|
|
|
// 切换"自动"项目的激活状态 |
|
|
|
const toggleAutoProject = () => { |
|
|
|
if (!isSelected(0)) { |
|
|
|
selectedProjects.value = [0] |
|
|
@ -126,7 +132,7 @@ const toggleAutoProject = () => { |
|
|
|
// 按钮逻辑 |
|
|
|
const handleConfirm = () => { |
|
|
|
// 对每个选中的试管单独更新 |
|
|
|
props.selectedSampleIds.forEach(async (tubeIndex) => { |
|
|
|
props.selectedSampleIds.forEach((tubeIndex) => { |
|
|
|
settingTestTubeStore.updateTubeSetting(props.uuid, { |
|
|
|
tubeIndex, |
|
|
|
projId: selectedProjects.value, |
|
|
@ -134,11 +140,27 @@ const handleConfirm = () => { |
|
|
|
}) |
|
|
|
}) |
|
|
|
|
|
|
|
// 更新本地数据 |
|
|
|
emit('updateSample', { |
|
|
|
projectIds: selectedProjects.value, |
|
|
|
bloodType: bloodType.value, |
|
|
|
}) |
|
|
|
|
|
|
|
// 重置选中状态 |
|
|
|
selectedProjects.value = [] |
|
|
|
bloodType.value = '' |
|
|
|
|
|
|
|
emit('confirm') |
|
|
|
emit('update:visible', false) |
|
|
|
} |
|
|
|
|
|
|
|
const handleCancel = () => { |
|
|
|
emit('cancel') // 通知父组件取消事件 |
|
|
|
// 重置选中状态 |
|
|
|
selectedProjects.value = [] |
|
|
|
bloodType.value = '' |
|
|
|
|
|
|
|
emit('cancel') |
|
|
|
emit('update:visible', false) |
|
|
|
} |
|
|
|
// 切换自动血液类型的激活状态 |
|
|
|
const toggleAutoBloodType = () => { |
|
|
@ -172,10 +194,53 @@ const emitUpdate = () => { |
|
|
|
const props = defineProps<{ |
|
|
|
uuid: string |
|
|
|
selectedSampleIds: number[] |
|
|
|
visible: boolean |
|
|
|
}>() |
|
|
|
</script> |
|
|
|
|
|
|
|
<style lang="less" scoped> |
|
|
|
.project-selector-overlay { |
|
|
|
position: fixed; |
|
|
|
top: 0; |
|
|
|
left: 0; |
|
|
|
width: 100vw; |
|
|
|
height: 100vh; |
|
|
|
background-color: rgba(0, 0, 0, 0.5); |
|
|
|
display: flex; |
|
|
|
justify-content: center; |
|
|
|
align-items: center; |
|
|
|
z-index: 1000; |
|
|
|
} |
|
|
|
|
|
|
|
.project-selector-modal { |
|
|
|
background: white; |
|
|
|
border-radius: 16px; |
|
|
|
padding: 20px; |
|
|
|
width: 90%; |
|
|
|
max-width: 800px; |
|
|
|
max-height: 90vh; |
|
|
|
overflow-y: auto; |
|
|
|
position: relative; |
|
|
|
|
|
|
|
.modal-header { |
|
|
|
display: flex; |
|
|
|
justify-content: space-between; |
|
|
|
align-items: center; |
|
|
|
margin-bottom: 20px; |
|
|
|
|
|
|
|
.title { |
|
|
|
font-size: 32px; |
|
|
|
font-weight: bold; |
|
|
|
} |
|
|
|
|
|
|
|
.close-icon { |
|
|
|
width: 32px; |
|
|
|
height: 32px; |
|
|
|
cursor: pointer; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
#project-selector { |
|
|
|
.active-item { |
|
|
|
background-color: #528dfe; |
|
|
@ -207,8 +272,6 @@ const props = defineProps<{ |
|
|
|
} |
|
|
|
|
|
|
|
.project-auto { |
|
|
|
height: 70px; |
|
|
|
width: 150px; |
|
|
|
border: 1px solid #4a90e2; |
|
|
|
color: #4a90e2; |
|
|
|
border-radius: 8px; |
|
|
@ -216,6 +279,7 @@ const props = defineProps<{ |
|
|
|
cursor: pointer; |
|
|
|
font-size: 32px; |
|
|
|
transition: all 0.3s ease; |
|
|
|
width: 150px; |
|
|
|
} |
|
|
|
|
|
|
|
//禁用状态下的样式 |
|
|
|