|
|
<template> <div id="configuration-container" v-loading="loading"> <!-- 渲染试管架列表 --> <div class="tube-rack-list"> <div v-for="(tubeRack, index) in tubeRacks" :key="`${tubeRack.uuid || index}-${componentRefreshKey}`" class="tube-rack-container"> <TestTubeRack ref="tubeRackComponentInstance" :tubeRack="tubeRack" :plates="plates" :key="refreshKey" @updateActivate="handleActivateChange" @updateSelectedSamples="handleUpdateSelectedSamples" @deleteTubeRack="deleteHandle" @changeUser="handleChangeUser" @clearProjectSelection="clearProjectSelection" /> </div> </div> <!-- 添加试管架按钮 --> <div class="add-tube" @click="addTubeRack"> <div class="icon"> <img src="@/assets/add.svg" alt="Add Icon" /> </div> <div class="text">添加试管架</div> </div> <!-- 试管信息编辑 --> <ProjectSelector :uuid="UUID" v-model:visible="showProjectSelector" :selectedSampleIds="selectedSampleIdsInParent" @updateSample="handleSampleUpdate" @confirm="handleConfirmProjectSelector" @cancel="closeProjectSelector" @clearSelection="clearProjectSelection" /> </div> </template>
<script setup lang="ts"> import { ref, onMounted, nextTick } from 'vue' import { useRouter } from 'vue-router' import TestTubeRack from '../components/TestTube/TestTubeRack.vue' import { addTestTube, getTestTube, getProjectInfo, deleteTube, updateTubeConfig, } from '../../../services/Index/Test-tube/test-tube' import type { DataItem, TubeSetting, } from '../../../types/Index/index' import { ConsumableGroupBase } from '../../../websocket/socket' import ProjectSelector from '../components/Consumables/ProjectSelector.vue' import { useConsumablesStore, useTestTubeStore, useSettingTestTubeStore } from '../../../store' import { ElMessage } from 'element-plus' const router = useRouter() const testTubeStore = useTestTubeStore() const settingTestTubeStore = useSettingTestTubeStore() const consumables = useConsumablesStore() const tubeRacks = ref<DataItem[]>([]) const loading = ref(false) // 控制加载状态
const plates = ref<ConsumableGroupBase[]>(consumables.plates) const refreshKey = ref(0) const selectedUUID = ref<string>('')
// 初始化获取试管架数据
onMounted(() => { getTubeData() getProjectInfoData() }) //获取设备支持的项目信息
const getProjectInfoData = async () => { const res = await getProjectInfo() if (res.success) { console.log(res.data) } } //获取已经配置的试管信息
const getTubeData = async () => { loading.value = true const res = await getTestTube() if (res.success) { // 初始化每个试管架的选中状态
tubeRacks.value = res.data.map((rack: DataItem) => ({ ...rack, selectedSampleIds: [], // 初始化选中状态数组
})) } loading.value = false } const selectedProject = ref<string | null>(null) // 添加事件监听,用于清空项目选择状态
const clearProjectSelection = () => { selectedProject.value = null // 清空选中的项目状态
} //编辑患者信息
const handleChangeUser = async (uuid: string) => { selectedUUID.value = uuid
const selectedTube = tubeRacks.value.find((t) => t.uuid === selectedUUID.value) if (!selectedTube) return testTubeStore.setTubeInfo(selectedTube) await updateTubeSettingsHandler() router.push({ path: '/index/change-user', }) }
//删除试管架
const deleteHandle = async (uuid: string) => { const res = await deleteTube(uuid) if (res.success) { ElMessage({ message: '删除成功', type: 'success', }) getTubeData() } else { ElMessage({ message: '删除失败', type: 'error', }) } } // 添加新试管架
const addTubeRack = async () => { loading.value = true // 开始加载
const newTubeRack: DataItem = { uuid: `uuid-${Date.now()}`, active: false, lock: false, tubeSettings: Array.from({ length: 10 }, (_, index) => ({ tubeIndex: index, userid: '', sampleBarcode: '', projId: [], bloodType: 'WHOLE_BLOOD', })), selectedSampleIds: [], }
// 直接将新试管架添加到 tubeRacks 中
tubeRacks.value.push(newTubeRack) // 向服务端发送添加请求
const response = await addTestTube() if (response && response.success) { // 更新 tubeRacks 列表为最新数据,避免闪烁
tubeRacks.value = [...tubeRacks.value] } else { console.error('试管架添加失败') } loading.value = false // 加载结束
}
// 处理试管架激活状态变化
const handleActivateChange = (update: { uuid: string; active: boolean }) => { const rack = tubeRacks.value.find((t) => t.uuid === update.uuid) if (rack) { rack.active = update.active } } const handleSampleUpdate = async ({ projectIds, bloodType, }: { projectIds: number[] bloodType: string }): Promise<void> => { if (selectedSampleIdsInParent.value.length > 0) { // 创建 tubeRacks 的深拷贝
const updatedTubeRacks = JSON.parse(JSON.stringify(tubeRacks.value)) // 找到对应的 tubeRack
const targetTubeRack = updatedTubeRacks.find( (t: DataItem) => t.uuid === UUID.value, ) if (targetTubeRack) { targetTubeRack.tubeSettings = targetTubeRack.tubeSettings.map( (tube: TubeSetting) => { if (selectedSampleIdsInParent.value.includes(tube.tubeIndex)) { return { ...tube, projId: [...projectIds], bloodType: bloodType, } } return tube }, )
// 清空数组再重新赋值,确保响应式更新
tubeRacks.value = [] await nextTick() tubeRacks.value = updatedTubeRacks// 新赋值触发响应式
console.log("🚀 ~ handleSampleUpdate ~ updatedTubeRacks:", updatedTubeRacks) const selectedTube = updatedTubeRacks.find((t: any) => t.uuid === UUID.value) console.log("🚀 ~ handleSampleUpdate ~ selectedTube:", selectedTube) testTubeStore.setTubeInfo(selectedTube) console.log("🚀 ~ handleSampleUpdate ~ testTubeStore.$state.tubeInfo:", testTubeStore.$state.tubeInfo) selectedProject.value = null // 选择后清空选中状态
await nextTick()
ElMessage({ message: '样本信息已更新', type: 'success', duration: 2000, }) } } else { ElMessage({ message: '请先选择样本后再选择项目', type: 'warning', duration: 2000, }) } } //声明组件实例
const UUID = ref<string>('') // 当前选中的样本ID列表
const selectedSampleIdsInParent = ref<number[]>([]) // 添加一个刷新key
const componentRefreshKey = ref(0)
// 修改 handleConfirmProjectSelector 函数
const handleConfirmProjectSelector = async () => { await updateTubeSettingsHandler()
// 清空父组件选中样本列表
selectedSampleIdsInParent.value = []
// 找到当前操作的试管架并清空其选中状态
const currentTubeRack = tubeRacks.value.find(rack => rack.uuid === UUID.value) if (currentTubeRack) { currentTubeRack.selectedSampleIds = [] }
// 重置其他相关状态
showProjectSelector.value = false UUID.value = ''
ElMessage({ message: '样本已确认,选中状态已清空', type: 'success', duration: 2000, }) } const tubeRackComponentInstance = ref() const showProjectSelector = ref(false)
// 修改关闭项目选择器的方法
const closeProjectSelector = () => { // 找到当前操作的试管架并清空其选中状态
const currentTubeRack = tubeRacks.value.find(rack => rack.uuid === UUID.value) if (currentTubeRack) { currentTubeRack.selectedSampleIds = [] }
// 重置所有相关状态
selectedSampleIdsInParent.value = [] showProjectSelector.value = false UUID.value = '' } // 父组件代码
const handleUpdateSelectedSamples = ({ sampleIds, uuid }: { sampleIds: number[]; uuid: string }) => { // 更新特定试管架的选中状态
const tubeRack = tubeRacks.value.find(tube => tube.uuid === uuid) if (tubeRack) { // 如果是取消选中(sampleIds为空),则关闭弹窗并清空状态
if (sampleIds.length === 0) { showProjectSelector.value = false selectedSampleIdsInParent.value = [] tubeRack.selectedSampleIds = [] UUID.value = '' } else { // 如果是新选中,则更新状态并打开弹窗
tubeRack.selectedSampleIds = sampleIds selectedSampleIdsInParent.value = sampleIds UUID.value = uuid showProjectSelector.value = true } } }
// 添加更新试管设置的方法
const updateTubeSettingsHandler = async () => { const { uuid, setting } = settingTestTubeStore.currentConfig
if (uuid && setting.tubeIndex >= 0) { try { const response = await updateTubeConfig({ uuid, setting })
if (response.success) { ElMessage.success('设置更新成功') console.log(tubeRacks.value) settingTestTubeStore.clearConfig() } else { ElMessage.error('设置更新失败') } } catch (error) { console.error('更新试管设置失败:', error) ElMessage.error('设置更新失败') } } } </script>
<style scoped lang="less"> #configuration-container { position: relative;
.el-message { width: 200px; height: 200px; }
/* 主容器定高和滚动条样式 */ .tube-rack-list { max-height: 1200px; /* 根据需要设置主容器的最大高度 */ overflow-y: auto; overflow-x: hidden; width: 100%; box-sizing: border-box;
/* 自定义滚动条样式 */ &::-webkit-scrollbar { width: 8px; }
&::-webkit-scrollbar-track { background: #f1f1f1; }
&::-webkit-scrollbar-thumb { background: #888; border-radius: 4px; }
&::-webkit-scrollbar-thumb:hover { background: #555; } }
.add-tube { width: 100%; height: 100px; background-color: #f6f6f6; display: flex; align-items: center; justify-content: center;
.icon { width: 60px; height: 100px; margin-right: 40px; }
.text { font-size: 32px; color: #73bc54; font-weight: bold; } }
/* 加载状态样式 */ .loading-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100vh; display: flex; align-items: center; justify-content: center; background-color: rgba(255, 255, 255, 0.8); font-size: 24px; color: #333; z-index: 1000; } } </style>
|