Files
zgty-mas-m/components/sample/auncel-select-popup.vue
2025-11-15 18:09:04 +08:00

305 lines
6.8 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view>
<u-popup :show="showAuncelSelector" closeable @close="close" @open="open" mode="right">
<view class="p10">天平选择</view>
<scroll-view scroll-y="true" class="content">
<u-grid :col="3" @click="doSelect" style="gap: 20px">
<u-grid-item v-for="(auncel, index) in auncelList" :index="index" :key="index">
<view class="auncel-item">
<view class="auncel-name">
{{ auncel.deviceCode }}
<view style="text-align: center">{{ auncel.controlRealName }}</view>
</view>
<view class="weight">
<view :class="getWeightClass(auncel)" :style="getWeightStyle(auncel)">
{{ getWeightText(auncel) }}
</view>
<view v-if="auncel.isConnected === 1" class="weight-unit">{{ auncel.weightUnit }}</view>
</view>
</view>
<view v-if="auncel.isConnected != 1" class="shade">天平断开</view>
</u-grid-item>
</u-grid>
</scroll-view>
</u-popup>
</view>
</template>
<script setup>
import { ref, computed, onMounted, onUnmounted } from 'vue'
import nx from '@/nx' // 假设你的全局状态/工具挂载在 nx
// Props & Emits
const props = defineProps({
showAuncelSelector: {
type: Boolean,
default: false
},
previousAuncelId: {
type: String,
default: ''
}
})
const emit = defineEmits(['update:showAuncelSelector', 'doSelect'])
// 响应式数据
const auncelList = ref([])
// 计算属性:获取用户信息
const userInfo = computed(() => nx.$store('user').userInfo)
// 方法
const open = () => {
getPageData()
listenDeviceData()
}
const close = () => {
auncelList.value = []
closeDeviceListener()
emit('update:showAuncelSelector', false)
}
const getPageData = () => {
nx.$api.laboratory
.getDeviceLaboratoryListBy({
pageNo: 1,
pageSize: 999,
collectDeviceType: 'balance',
deviceStatus: '0',
isEnable: '1'
})
.then(res => {
auncelList.value = res.list
})
}
const doSelect = index => {
const currentAuncel = auncelList.value[index]
if (currentAuncel.isConnected !== 1) {
uni.showToast({ title: '天平设备尚未连接!', icon: 'none' })
return
}
if (currentAuncel.controlRealName && currentAuncel.controlRealName !== userInfo.value.nickname) {
uni.showToast({
title: `当前天平正被“${currentAuncel.controlRealName}”使用,请选择其他天平!`,
icon: 'none'
})
return
}
let delayFlag = false
if (props.previousAuncelId && props.previousAuncelId !== '' && props.previousAuncelId !== currentAuncel.id) {
releaseDeviceControl(props.previousAuncelId)
delayFlag = true
}
const controlDevice = {
msgId: currentAuncel.id,
cmd: 'controlDevice',
clientType: 'caaClient',
data: {
deviceId: currentAuncel.id,
deviceCode: currentAuncel.deviceCode,
deviceName: currentAuncel.productName,
isControl: true,
controlRealName: userInfo.value.nickname
}
}
const sendControl = () => {
const controlData = JSON.stringify(controlDevice)
nx.$measure.send(controlData)
emit('update:showAuncelSelector', false)
emit('doSelect', controlDevice)
}
if (delayFlag) {
setTimeout(sendControl, 300)
} else {
sendControl()
}
}
const releaseDeviceControl = deviceId => {
if (!deviceId) return
const controlDevice = {
msgId: deviceId,
cmd: 'controlDevice',
clientType: 'caaClient',
data: {
deviceId,
isControl: false,
controlRealName: userInfo.value.nickname
}
}
nx.$measure.send(JSON.stringify(controlDevice))
}
const listenDeviceData = () => {
uni.$on('deviceData', handleDeviceData)
uni.$on('deviceStatus', handleDeviceStatus)
uni.$on('connClose', handleConnClose)
}
const handleDeviceData = res => {
if (res.deviceType === 'balance') {
auncelList.value.forEach(item => {
if (item.id === res.deviceId) {
item.weightData = res.weightData
item.weightUnit = res.weightUnit
item.weightStable = res.weightStable
item.isConnected = 1
item.controlRealName = res.controlRealName
}
})
}
}
const handleDeviceStatus = res => {
if (res.deviceType === 'balance') {
auncelList.value.forEach(item => {
if (item.id === res.deviceId) {
item.isConnected = res.connected
if (res.connected == 0) {
item.weightData = ''
item.weightUnit = ''
item.weightStable = 0
}
}
})
}
}
const handleConnClose = () => {
auncelList.value.forEach(item => {
item.weightData = ''
item.weightUnit = ''
item.weightStable = 0
item.controlRealName = ''
item.isConnected = 0
})
}
const closeDeviceListener = () => {
uni.$off('deviceData', handleDeviceData)
uni.$off('deviceStatus', handleDeviceStatus)
uni.$off('connClose', handleConnClose)
}
// 生命周期
onMounted(() => {
// 如果组件在 mounted 时已打开,可考虑自动加载(但通常由父组件控制 show
})
onUnmounted(() => {
closeDeviceListener()
})
function getWeightText(auncel) {
if (auncel.isConnected !== 1) {
return ''
}
return auncel.weightData || ''
}
function getWeightClass(auncel) {
if (auncel.weightStable === 0) return 'weight-data-yellow'
if (auncel.weightStable === 1) return 'weight-data'
if (auncel.weightStable === 2) return 'weight-data-warning'
return 'weight-data-yellow'
}
function getWeightStyle(auncel) {
if (auncel.isConnected !== 1) {
return {
textAlign: 'center',
fontSize: '28px'
}
}
return {
textAlign: 'right',
fontSize: '32px'
}
}
</script>
<style scoped lang="scss">
.content {
width: 60vw;
height: 90vh;
padding: 0 20px 40px 20px;
}
.auncel-item {
height: 180px;
width: 180px;
background-image: url(/static/images/auncel.png);
background-repeat: no-repeat;
background-size: 100%;
display: flex;
flex-direction: column;
}
.shade {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(31, 41, 55, 0.55);
color: #fff;
font-weight: 500;
z-index: 10;
border-radius: 8px;
}
.auncel-name {
flex: 1;
text-align: center;
padding-top: 20px;
}
.weight {
flex: 1;
font-size: 28px;
padding-top: 10px;
padding: 10px 30px 0 30px;
position: relative;
}
.weight-data,
.weight-data-yellow,
.weight-data-warning {
font-family: zzjc-lcd;
}
.weight-data {
color: #4cd964;
}
.weight-data-yellow {
color: #ffff00;
}
.weight-data-warning {
color: #ff3333;
}
.weight-unit {
position: absolute;
right: 10px;
top: 10px;
color: #ffffff;
font-size: 20px;
}
@media (max-width: 700px) {
.auncel-item {
height: 150px;
width: 150px;
}
.auncel-name {
padding-top: 10px;
}
}
</style>