Browse Source

试管架页面改为监听上报

dev
zhangjiming 7 months ago
parent
commit
a04d50e55a
  1. 63
      src/pages/Index/Index.vue
  2. 155
      src/pages/Index/Regular/TestTube.vue
  3. 3
      src/store/modules/consumables.ts
  4. 11
      src/store/modules/testTube.ts
  5. 16
      src/types/Index/TestTube.ts
  6. 21
      src/websocket/socket.ts

63
src/pages/Index/Index.vue

@ -238,6 +238,7 @@ import {
useConsumablesStore, useConsumablesStore,
useDeviceStore, useDeviceStore,
useSettingTestTubeStore, useSettingTestTubeStore,
useTestTubeStore,
} from '../../store' } from '../../store'
import { createWebSocket } from '../../websocket/socket' import { createWebSocket } from '../../websocket/socket'
import type { import type {
@ -247,6 +248,7 @@ import type {
IncubationPlateStateMessage, IncubationPlateStateMessage,
OptScanModuleStateMessage, OptScanModuleStateMessage,
SensorStateMessage, SensorStateMessage,
TubeHolderSettingMessage,
TubeHolderStateMessage, TubeHolderStateMessage,
} from '../../websocket/socket' } from '../../websocket/socket'
import { getServerInfo } from '../../utils/getServerInfo' import { getServerInfo } from '../../utils/getServerInfo'
@ -269,6 +271,7 @@ const consumableStore = useConsumablesStore()
const deviceStore = useDeviceStore() const deviceStore = useDeviceStore()
const runningStore = useRunningStore() const runningStore = useRunningStore()
const settingTubeStore = useSettingTestTubeStore() const settingTubeStore = useSettingTestTubeStore()
const tubeRackStore = useTestTubeStore()
// //
const user = ref<User>( const user = ref<User>(
@ -367,6 +370,9 @@ const handleFooterState = (data: FooterMessageState['data']) => {
const handleTubeHolderStateMessage = (data: TubeHolderStateMessage['data']) => { const handleTubeHolderStateMessage = (data: TubeHolderStateMessage['data']) => {
runningStore.setTubeHolderState(data) runningStore.setTubeHolderState(data)
} }
const handleTubeHolderSettingMessage = (data: TubeHolderSettingMessage['data']) => {
tubeRackStore.setTubeRacks(data)
}
const handleOptScanModuleStateMessage = ( const handleOptScanModuleStateMessage = (
data: OptScanModuleStateMessage['data'], data: OptScanModuleStateMessage['data'],
@ -406,6 +412,7 @@ onMounted(() => {
'TubeHolderState', 'TubeHolderState',
handleTubeHolderStateMessage, handleTubeHolderStateMessage,
) )
wsState.subscribe<TubeHolderSettingMessage>('TubeHolderSetting', handleTubeHolderSettingMessage)
wsState.subscribe<IncubationPlateStateMessage>( wsState.subscribe<IncubationPlateStateMessage>(
'IncubationPlateState', 'IncubationPlateState',
handleIncubationPlateStateMessage, handleIncubationPlateStateMessage,
@ -454,10 +461,10 @@ const startTest = async () => {
try { try {
showDeviceWaitingModal.value = true showDeviceWaitingModal.value = true
const res = await startWork() const res = await startWork()
showDeviceWaitingModal.value = false
if (res.success) { if (res.success) {
await untilDeviceReady() await untilDeviceReady()
} else { } else {
showDeviceWaitingModal.value = false
ElMessage({ ElMessage({
message: res.data.info, message: res.data.info,
type: 'error', type: 'error',
@ -473,10 +480,10 @@ const startTest = async () => {
const pauseTest = async () => { const pauseTest = async () => {
showDeviceWaitingModal.value = true showDeviceWaitingModal.value = true
const res = await pauseWork() const res = await pauseWork()
showDeviceWaitingModal.value = false
if (res.success) { if (res.success) {
await untilDeviceReady() await untilDeviceReady()
} else { } else {
showDeviceWaitingModal.value = false
ElMessage({ ElMessage({
message: res.data.info, message: res.data.info,
type: 'error', type: 'error',
@ -489,10 +496,10 @@ const pauseTest = async () => {
const stopTest = async () => { const stopTest = async () => {
showDeviceWaitingModal.value = true showDeviceWaitingModal.value = true
const res = await stopWork() const res = await stopWork()
showDeviceWaitingModal.value = false
if (res.success) { if (res.success) {
await untilDeviceReady() await untilDeviceReady()
} else { } else {
showDeviceWaitingModal.value = false
ElMessage({ ElMessage({
message: res.data.info, message: res.data.info,
type: 'error', type: 'error',
@ -504,10 +511,10 @@ const stopTest = async () => {
const continueTest = async () => { const continueTest = async () => {
showDeviceWaitingModal.value = true showDeviceWaitingModal.value = true
const res = await continueWork() const res = await continueWork()
showDeviceWaitingModal.value = false
if (res.success) { if (res.success) {
await untilDeviceReady() await untilDeviceReady()
} else { } else {
showDeviceWaitingModal.value = false
ElMessage({ ElMessage({
message: res.data.info, message: res.data.info,
type: 'error', type: 'error',
@ -546,55 +553,11 @@ const pollingInitState = async () => {
showFailModal.value = true // showFailModal.value = true //
} }
} }
} else {
showDeviceResettingModal.value = false
} }
} }
// const checkIfResetCompleted = async () => {
// if (showFailModal.value) {
// showFailModal.value = false;
// }
// showLoadingModal.value = true; // LoadingModal
// // 2
// await new Promise(resolve => setTimeout(resolve, 2000));
// //
// const initState = await getInitState();
// if (initState.ecode === "SUC") {
// //
// if (initState.data.passed) {
// console.log("")
// sessionStorage.setItem('deviceResetFinished', "true");
// showLoadingModal.value = false;
// showAlreadyModal.value = true;
// } else {
// console.log("")
// await getCheckData(); //
// const failedItems = checkData.value.filter(item => !item.pass);
// if (failedItems.length > 0) {
// const errorMessages = generateErrorMessages(failedItems);
// console.log(':', errorMessages);
// failItems.value = failedItems; //
// failMessage.value = errorMessages.join('\n'); //
// showLoadingModal.value = false; // LoadingModal
// showFailModal.value = true; //
// } else {
// console.log("")
// showLoadingModal.value = false; // LoadingModal
// showAlreadyModal.value = true; //
// sessionStorage.setItem('deviceResetFinished', "true");
// }
// }
// }
// };
// const isTestTubeSlotReady = ref(false); //
//
// const checkTestTubeSlotStatus = (data: CheckItem[]) => {
// const slotCheck = data.find(item => item.type === 'CHECK_TEST_TUBE_SLOT_READY');
// isTestTubeSlotReady.value = slotCheck?.pass ?? false;
// console.log(':', isTestTubeSlotReady.value ? '' : '');
// };
const handleAlreadyConfirm = () => { const handleAlreadyConfirm = () => {
console.log('用户确认操作') console.log('用户确认操作')
showAlreadyModal.value = false showAlreadyModal.value = false

155
src/pages/Index/Regular/TestTube.vue

@ -3,15 +3,15 @@
<!-- 渲染试管架列表 --> <!-- 渲染试管架列表 -->
<div class="tube-rack-list"> <div class="tube-rack-list">
<div <div
v-for="(tubeRack, index) in tubeRacks"
v-for="(tubeRack, index) in testTubeStore.tubeRacks"
:key="tubeRack.uuid" :key="tubeRack.uuid"
class="tube-rack-container" class="tube-rack-container"
> >
<TestTubeRack
<TestTubeRackComponent
:tubeRack="tubeRack" :tubeRack="tubeRack"
:index="index" :index="index"
:projects="consumables.projectsAvailable" :projects="consumables.projectsAvailable"
:bloodTypes="bloodTypes"
:bloodTypes="settingTubeStore.bloodTypes"
@delete:rack="deleteTubeRack" @delete:rack="deleteTubeRack"
@active:rack="handleActivateChange" @active:rack="handleActivateChange"
@patient:edit="handleChangeUser" @patient:edit="handleChangeUser"
@ -30,7 +30,10 @@
<section class="project-area"> <section class="project-area">
<h2 class="title">项目选择</h2> <h2 class="title">项目选择</h2>
<div class="project-list"> <div class="project-list">
<div v-for="proj in consumables.projectsAvailable" :key="proj.projName">
<div
v-for="proj in consumables.projectsAvailable"
:key="proj.projName"
>
<div <div
class="project-item" class="project-item"
:class="{ active: isProjElemActive(proj) }" :class="{ active: isProjElemActive(proj) }"
@ -39,7 +42,7 @@
> >
<span class="proj-name">{{ proj.projName }}</span> <span class="proj-name">{{ proj.projName }}</span>
<span class="proj-num">{{ <span class="proj-num">{{
`${projIdCntMap[proj.projId] || 0}/${proj.num}`
`${projIdCntMap[proj.projId || 1] || 0}/${proj.num}`
}}</span> }}</span>
</div> </div>
</div> </div>
@ -48,7 +51,7 @@
<section class="blood-type-area"> <section class="blood-type-area">
<h2 class="title">血液类型</h2> <h2 class="title">血液类型</h2>
<div class="blood-list"> <div class="blood-list">
<div v-for="type in bloodTypes" :key="type.key">
<div v-for="type in settingTubeStore.bloodTypes" :key="type.key">
<div <div
class="blood-item" class="blood-item"
:class="{ active: selectedBloodTypeKey === type.key }" :class="{ active: selectedBloodTypeKey === type.key }"
@ -74,67 +77,44 @@
</div> </div>
</template> </template>
<script setup>
import {
ref,
onMounted,
onBeforeUnmount,
nextTick,
computed,
onActivated,
} from 'vue'
<script setup lang="ts">
import { ref, computed } from 'vue'
import * as R from 'ramda' import * as R from 'ramda'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import TestTubeRack from '../components/TestTube/TestTubeRack.vue'
import TestTubeRackComponent from '../components/TestTube/TestTubeRack.vue'
import { import {
addTestTube, addTestTube,
getTestTube,
deleteTube, deleteTube,
updateTubeConfig, updateTubeConfig,
getBloodTypes,
updateTubeActivationStatus, updateTubeActivationStatus,
} from '../../../services/Index/testTube' } from '../../../services/Index/testTube'
import { eventBus } from '../../../eventBus'
import { import {
useConsumablesStore, useConsumablesStore,
useTestTubeStore, useTestTubeStore,
useSettingTestTubeStore, useSettingTestTubeStore,
} from '../../../store' } from '../../../store'
import { ElMessage, ElDialog } from 'element-plus' import { ElMessage, ElDialog } from 'element-plus'
import { ReactionPlateGroup, TestTubeRack } from '@/websocket/socket'
const router = useRouter() const router = useRouter()
const settingTubeStore = useSettingTestTubeStore()
const testTubeStore = useTestTubeStore() const testTubeStore = useTestTubeStore()
const consumables = useConsumablesStore() const consumables = useConsumablesStore()
const tubeRacks = ref([]) //<DataItem[]>
const bloodTypes = ref([])
const loading = ref(false) // const loading = ref(false) //
const selectedProjIds = ref([]) // number[]
const selectedProjIds = ref<number[]>([])
const selectedBloodTypeKey = ref('WHOLE_BLOOD') const selectedBloodTypeKey = ref('WHOLE_BLOOD')
const deleteRackDialogVisible = ref(false) const deleteRackDialogVisible = ref(false)
const onTubeSettingUpdate = () => {
getTubeData()
const isProjElemActive = (proj: ReactionPlateGroup) => {
return selectedProjIds.value.includes(proj.projId!)
} }
onMounted(() => {
eventBus.on('AppTubeSettingUpdateEvent', onTubeSettingUpdate)
getTubeData()
getBloodTypeData()
})
onBeforeUnmount(() => {
eventBus.off('AppTubeSettingUpdateEvent', onTubeSettingUpdate)
})
const isProjElemActive = (proj) => {
return selectedProjIds.value.includes(proj.projId)
}
const styleOfProjElem = (proj) => {
const styleOfProjElem = (proj: ReactionPlateGroup) => {
const active = isProjElemActive(proj) const active = isProjElemActive(proj)
if (active) { if (active) {
return { return {
@ -151,13 +131,13 @@ const styleOfProjElem = (proj) => {
} }
} }
const clickProjectItem = (proj) => {
if (selectedProjIds.value.includes(proj.projId)) {
const clickProjectItem = (proj: ReactionPlateGroup) => {
if (selectedProjIds.value.includes(proj.projId!)) {
selectedProjIds.value = selectedProjIds.value.filter( selectedProjIds.value = selectedProjIds.value.filter(
(pId) => pId !== proj.projId, (pId) => pId !== proj.projId,
) )
} else { } else {
selectedProjIds.value = [...selectedProjIds.value, proj.projId].sort()
selectedProjIds.value = [...selectedProjIds.value, proj.projId!].sort()
} }
} }
@ -189,55 +169,13 @@ const projIdCntMap = computed(() => {
return acc return acc
}, },
{}, {},
tubeRacks.value,
testTubeStore.tubeRacks,
) )
}) })
const getBloodTypeData = async () => {
loading.value = true
const res = await getBloodTypes()
loading.value = false
if (res.success) {
bloodTypes.value = res.data
// console.log(res.data)
} else {
ElMessage({
message: '加载血液类型失败',
type: 'error',
duration: 2000,
})
}
}
const mockData = (data) => {
// if (data.length > 0) {
// data[0].tubeSettings.splice(0, 2)
// }
return data
}
//
const getTubeData = async () => {
loading.value = true
const res = await getTestTube()
if (res.success) {
tubeRacks.value = mockData(res.data)
// console.log(tubeRacks.value)
} else {
ElMessage({
message: '加载试管架数据失败',
type: 'error',
duration: 2000,
})
}
loading.value = false
}
// //
const handleChangeUser = async (index) => {
const rack = tubeRacks.value[index]
const handleChangeUser = async (index: number) => {
const rack = testTubeStore.tubeRacks[index]
if (rack.state !== 'INACTIVE') { if (rack.state !== 'INACTIVE') {
ElMessage({ ElMessage({
message: '试管架处理激活状态,不可修改', message: '试管架处理激活状态,不可修改',
@ -252,25 +190,21 @@ const handleChangeUser = async (index) => {
}) })
} }
const existValidProject = (tubeRack) => {
const existValidProject = (tubeRack: TestTubeRack) => {
return tubeRack.tubeSettings.some( return tubeRack.tubeSettings.some(
(s) => (s.projId || []).length > 0 && !!s.bloodType, (s) => (s.projId || []).length > 0 && !!s.bloodType,
) )
} }
let confirmDeleteRackUuid = null
let confirmDeleteRackUuid: string | undefined = undefined
const confirmDeleteTube = async () => { const confirmDeleteTube = async () => {
deleteRackDialogVisible.value = false deleteRackDialogVisible.value = false
const res = await deleteTube(confirmDeleteRackUuid)
const res = await deleteTube(confirmDeleteRackUuid!)
if (res.success) { if (res.success) {
tubeRacks.value = tubeRacks.value.filter(
(v) => v.uuid !== confirmDeleteRackUuid,
)
ElMessage({ ElMessage({
message: '删除成功', message: '删除成功',
type: 'success', type: 'success',
}) })
// getTubeData()
} else { } else {
ElMessage({ ElMessage({
message: '删除失败', message: '删除失败',
@ -280,8 +214,8 @@ const confirmDeleteTube = async () => {
} }
// //
const deleteTubeRack = async (idx) => {
const rack = tubeRacks.value[idx]
const deleteTubeRack = async (idx: number) => {
const rack = testTubeStore.tubeRacks[idx]
if (rack.state !== 'INACTIVE') { if (rack.state !== 'INACTIVE') {
ElMessage({ ElMessage({
message: '试管架处理激活状态,不可删除', message: '试管架处理激活状态,不可删除',
@ -302,7 +236,7 @@ const addTubeRack = async () => {
const response = await addTestTube() const response = await addTestTube()
if (response && response.success) { if (response && response.success) {
tubeRacks.value = [...tubeRacks.value, response.data]
// do nothing
} else { } else {
ElMessage({ ElMessage({
message: '试管架添加失败', message: '试管架添加失败',
@ -313,8 +247,8 @@ const addTubeRack = async () => {
} }
// //
const handleActivateChange = async (index) => {
const rack = tubeRacks.value[index]
const handleActivateChange = async (index: number) => {
const rack = testTubeStore.tubeRacks[index]
if (rack.state === 'LOCKED') { if (rack.state === 'LOCKED') {
ElMessage({ ElMessage({
message: '试管已锁定,不能修改', message: '试管已锁定,不能修改',
@ -332,12 +266,7 @@ const handleActivateChange = async (index) => {
active: destState === 'ACTIVE', active: destState === 'ACTIVE',
}) })
if (res.success) { if (res.success) {
tubeRacks.value = tubeRacks.value.map((rack, idx) => {
if (idx === index) {
rack.state = destState
}
return rack
})
// do nothing
} else { } else {
ElMessage({ ElMessage({
message: '更改激活状态失败', message: '更改激活状态失败',
@ -346,12 +275,12 @@ const handleActivateChange = async (index) => {
} }
} }
const updateTubeSettings = async (rackIdx, tubeIdx) => {
const updateTubeSettings = async (rackIdx:number, tubeIdx:number) => {
if (!selectedBloodTypeKey.value) { if (!selectedBloodTypeKey.value) {
ElMessage.error('请选择血液类型') ElMessage.error('请选择血液类型')
return return
} }
const rack = tubeRacks.value[rackIdx]
const rack = testTubeStore.tubeRacks[rackIdx]
if (rack.state !== 'INACTIVE') { if (rack.state !== 'INACTIVE') {
ElMessage({ ElMessage({
message: '试管架已激活,不能修改', message: '试管架已激活,不能修改',
@ -372,17 +301,7 @@ const updateTubeSettings = async (rackIdx, tubeIdx) => {
setting: [updSetting], setting: [updSetting],
}) })
if (response.success) { if (response.success) {
tubeRacks.value = tubeRacks.value.map((rack, idx) => {
if (idx === rackIdx) {
rack.tubeSettings = rack.tubeSettings.map((tube, index) => {
if (index === tubeIdx) {
return updSetting
}
return tube
})
}
return rack
})
// do nothing
} else { } else {
ElMessage.error('设置更新失败') ElMessage.error('设置更新失败')
} }

3
src/store/modules/consumables.ts

@ -10,6 +10,7 @@ import * as R from 'ramda'
// import type { PersistenceOptions } from 'pinia-plugin-persistedstate' // import type { PersistenceOptions } from 'pinia-plugin-persistedstate'
import type { import type {
ConsumablesStateMessage, ConsumablesStateMessage,
ProjectInfo,
ReactionPlateGroup, ReactionPlateGroup,
} from '../../websocket/socket' } from '../../websocket/socket'
@ -79,7 +80,7 @@ export const useConsumablesStore = defineStore(
group[n] as ReactionPlateGroup[], group[n] as ReactionPlateGroup[],
), ),
) )
return projArr
return projArr as ReactionPlateGroup[]
}) })
const tipCount = computed(() => { const tipCount = computed(() => {

11
src/store/modules/testTube.ts

@ -1,6 +1,7 @@
import { TestTubeRack, TubeHolderSettingMessage } from '@/websocket/socket'
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { ref } from 'vue' import { ref } from 'vue'
import type { TestTubeRack } from '../../types/Index'
export const useTestTubeStore = defineStore( export const useTestTubeStore = defineStore(
'testTube', 'testTube',
() => { () => {
@ -11,9 +12,17 @@ export const useTestTubeStore = defineStore(
tubeRack.value = rack tubeRack.value = rack
} }
const tubeRacks = ref<TubeHolderSettingMessage['data']>([])
const setTubeRacks = (data: TubeHolderSettingMessage['data']) => {
tubeRacks.value = data
}
return { return {
tubeRack, tubeRack,
setTubeRack, setTubeRack,
tubeRacks,
setTubeRacks
} }
}, },
{ {

16
src/types/Index/TestTube.ts

@ -1,12 +1,6 @@
import type { ConsumableGroupBase } from '../../websocket/socket'
import type { ConsumableGroupBase, TestTubeRack } from '../../websocket/socket'
export interface TubeSetting {
tubeIndex: number
userid: string
sampleBarcode: string
projId: number[]
bloodType: 'WHOLE_BLOOD' | 'SERUM_OR_PLASMA'
}
// 更新后的类型定义 // 更新后的类型定义
export interface Project { export interface Project {
id: number id: number
@ -17,12 +11,6 @@ export interface Project {
reactionTemperature: number reactionTemperature: number
color: string color: string
} }
export interface TestTubeRack {
uuid: string
state: 'INACTIVE' | 'ACTIVE' | 'LOCKED'
tubeSettings: TubeSetting[],
tubeInfo:{}
}
export interface ApiResponse { export interface ApiResponse {
dataType: string dataType: string

21
src/websocket/socket.ts

@ -170,6 +170,26 @@ interface TubeHolderStateMessage extends BaseMessage {
timestamp: number timestamp: number
} }
export interface TubeSetting {
tubeIndex: number
userid: string
sampleBarcode: string
projId: number[]
bloodType: 'WHOLE_BLOOD' | 'SERUM_OR_PLASMA'
}
export interface TestTubeRack {
uuid: string
state: 'INACTIVE' | 'ACTIVE' | 'LOCKED'
tubeSettings: TubeSetting[],
}
export interface TubeHolderSettingMessage extends BaseMessage {
type: 'TubeHolderSetting'
messageType: 'Report'
dataType: 'TubeHolderSetting'
data: TestTubeRack[]
}
// 传感器状态消息 // 传感器状态消息
interface SensorStateMessage extends BaseMessage { interface SensorStateMessage extends BaseMessage {
type: 'SensorState' type: 'SensorState'
@ -274,6 +294,7 @@ type WebSocketMessage =
| DeviceWorkStateMessage | DeviceWorkStateMessage
| EmergencyPosStateMessage | EmergencyPosStateMessage
| TubeHolderStateMessage | TubeHolderStateMessage
| TubeHolderSettingMessage
| SensorStateMessage | SensorStateMessage
| IncubationPlateStateMessage | IncubationPlateStateMessage
| AppEventMessage | AppEventMessage

Loading…
Cancel
Save