Browse Source

fix: 首页和图表添加实时消毒等级和ui优化

master
guoapeng 1 week ago
parent
commit
30ac801641
  1. 7
      src/app.vue
  2. 93
      src/components/home/HomeFormula.vue
  3. 11
      src/components/home/HomeOperation.vue
  4. 1
      src/components/home/HomeSetting.vue
  5. 10
      src/components/home/LineChart.vue
  6. 18
      src/libs/constant.ts
  7. 7
      src/stores/homeStore.ts
  8. 195
      src/views/home/chart.vue
  9. 12
      src/views/home/index.vue

7
src/app.vue

@ -1,16 +1,15 @@
<script setup lang="ts"> <script setup lang="ts">
import { useDebugStore } from 'stores/debugStore'
import { useDeviceStore } from 'stores/deviceStore' import { useDeviceStore } from 'stores/deviceStore'
import { useFormulaStore } from 'stores/formulaStore'
import { useHomeStore } from 'stores/homeStore' import { useHomeStore } from 'stores/homeStore'
import { useLiquidStore } from 'stores/liquidStore' import { useLiquidStore } from 'stores/liquidStore'
import { useSealStore } from 'stores/sealStore'
import { useSystemStore } from 'stores/systemStore' import { useSystemStore } from 'stores/systemStore'
import { onBeforeMount, ref } from 'vue' import { onBeforeMount, ref } from 'vue'
import { sendCmd, subscribeEvent } from '@/apis/system' import { sendCmd, subscribeEvent } from '@/apis/system'
import { useDebugStore } from './stores/debugStore'
import { useFormulaStore } from './stores/formulaStore'
import { useSealStore } from './stores/sealStore'
/** /**
* 应用初始化组件 * 应用初始化组件
* @description 负责系统初始化流程控制包括设备信息获取数据同步及进度展示 * @description 负责系统初始化流程控制包括设备信息获取数据同步及进度展示

93
src/components/home/HomeFormula.vue

@ -9,45 +9,60 @@ const formulaStore = useFormulaStore()
const homeStore = useHomeStore() const homeStore = useHomeStore()
const formulaInfo = ref() const formulaInfo = ref()
const rate = ref() const rate = ref()
const log = ref()
watchEffect(async () => { watchEffect(async () => {
if (['idle', 'finished'].includes(homeStore.disinfectionState.state)) { if (['idle', 'finished'].includes(homeStore.disinfectionState.state)) {
formulaInfo.value = formulaStore.selectedFormulaInfo formulaInfo.value = formulaStore.selectedFormulaInfo
rate.value = formulaStore.selectedFormulaInfo?.injection_pump_speed rate.value = formulaStore.selectedFormulaInfo?.injection_pump_speed
log.value = formulaStore.selectedFormulaInfo?.loglevel
} }
else { else {
rate.value = homeStore.realRate || (await formulaStore.getRealtimeConfig()).rely?.injection_pump_speed
const realForm = (await formulaStore.getRealtimeConfig()).rely
rate.value = homeStore.realRate || realForm?.injection_pump_speed
log.value = homeStore.realLog || realForm?.loglevel
} }
}) })
</script> </script>
<template> <template>
<div class="home-right-title"> <div class="home-right-title">
<div class="title-formula">
<el-icon style="color: #31cb7a; font-size: 1.5rem">
<SuccessFilled />
</el-icon>
<el-tooltip :content="formulaInfo?.name || '默认'" placement="bottom-start">
<div class="name-text">
{{ formulaInfo?.name || '默认' }}
</div>
</el-tooltip>
</div>
<div v-if="rate" class="title-spend">
<span>速率</span>
<span style="color: #31cb7a">{{ homeStore.disinfectionState.injectedVelocity }}</span>g/分钟
</div>
<el-descriptions :column="1">
<el-descriptions-item label="配方">
<el-tooltip :content="formulaInfo?.name || '默认'" placement="bottom-start">
<div class="text">
{{ formulaInfo?.name || '默认' }}
</div>
</el-tooltip>
</el-descriptions-item>
<el-descriptions-item label="设定注射速率">
<el-tag>
<span style="color: #31cb7a; font-size: 18px; margin: 0 5px">{{ rate }}</span>g/min
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="实时注射速率">
<el-tag>
<span style="color: #31cb7a; font-size: 18px; margin: 0 5px">{{
homeStore.disinfectionState.injectedVelocity
}}</span>g/min
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="目标消毒等级">
<el-tag>
<span style="color: #31cb7a; font-size: 18px; margin: 0 5px">{{ log }}</span>Log
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="实时消毒等级">
<el-tag>
<span style="color: #31cb7a; font-size: 18px; margin: 0 5px">{{ homeStore.disinfectionState.nlog }}</span>Log
</el-tag>
</el-descriptions-item>
</el-descriptions>
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.home-right-title { .home-right-title {
background: #fff;
width: 100%;
border-radius: 10px;
margin: 10px auto;
display: grid;
grid-template-columns: 1fr 1fr;
font-size: 1.5rem;
.title-formula { .title-formula {
width: 100%; width: 100%;
display: flex; display: flex;
@ -79,4 +94,38 @@ watchEffect(async () => {
font-size: 1.5rem; font-size: 1.5rem;
} }
} }
:deep(.el-descriptions) {
width: 100%;
.el-descriptions__body {
background: rgba(0, 0, 0, 0);
}
}
:deep(.el-descriptions__cell) {
display: flex;
align-items: center;
background: #fff;
margin-bottom: 5px;
padding: 5px !important;
.el-descriptions__label {
display: inline-block;
width: 120px;
margin: 0;
font-size: 15px;
font-weight: 600;
color: #606266;
}
.el-descriptions__content {
flex: 1;
text-align: right;
display: flex;
justify-content: flex-end;
}
}
.text {
text-align: right;
width: 150px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
</style> </style>

11
src/components/home/HomeOperation.vue

@ -117,6 +117,7 @@ const doStartDisinfect = async () => {
const onFinishDisinfect = () => { const onFinishDisinfect = () => {
FtMessageBox.warning('请确认是否结束消毒').then(() => { FtMessageBox.warning('请确认是否结束消毒').then(() => {
homeStore.setRate(undefined) homeStore.setRate(undefined)
homeStore.setLog(undefined)
doStopDisinfect() doStopDisinfect()
}) })
} }
@ -264,16 +265,14 @@ const formatSeconds = (seconds: number) => {
background: #ff6767; background: #ff6767;
} }
.home-remain-time { .home-remain-time {
background: #f6fafe;
margin-top: 1.5em;
margin-left: 1rem;
margin-right: 1rem;
height: 8vh;
background: #fff;
margin: 10px;
height: 40px;
border-radius: 12px; border-radius: 12px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
font-size: 24px;
font-size: 20px;
gap: 10px; gap: 10px;
.home-remaini-value { .home-remaini-value {
color: #2892f3; color: #2892f3;

1
src/components/home/HomeSetting.vue

@ -124,6 +124,7 @@ const onSave = async () => {
) )
FtMessage.success('设定成功') FtMessage.success('设定成功')
homeStore.setRate(formData.injection_pump_speed) homeStore.setRate(formData.injection_pump_speed)
homeStore.setLog(formData.loglevel)
} }
} }
/** /**

10
src/components/home/LineChart.vue

@ -50,10 +50,10 @@ watch(
case '相对湿度': case '相对湿度':
unit = ' %RH' unit = ' %RH'
break break
case 'H2O2浓度':
case 'H₂O₂浓度':
unit = ' ppm' unit = ' ppm'
break break
case 'H2O2相对饱和度':
case 'H₂O₂相对饱和度':
unit = ' %RS' unit = ' %RS'
break break
} }
@ -64,7 +64,7 @@ watch(
}, },
}, },
legend: { legend: {
data: ['温度', '相对湿度', 'H2O2浓度', 'H2O2相对饱和度'],
data: ['温度', '相对湿度', 'H₂O₂浓度', 'H₂O₂相对饱和度'],
orient: 'horizontal', // orient: 'horizontal', //
itemWidth: 10, // itemWidth: 10, //
itemHeight: 10, // itemHeight: 10, //
@ -104,7 +104,7 @@ watch(
}, },
}, },
{ {
name: 'H2O2浓度',
name: 'H₂O₂浓度',
type: 'line', type: 'line',
data: newValue.data?.map(item => item.h2o2.toFixed(2)), data: newValue.data?.map(item => item.h2o2.toFixed(2)),
symbol: 'circle', symbol: 'circle',
@ -115,7 +115,7 @@ watch(
}, },
}, },
{ {
name: 'H2O2相对饱和度',
name: 'H₂O₂相对饱和度',
type: 'line', type: 'line',
data: newValue.data?.map(item => item.rs.toFixed(2)), data: newValue.data?.map(item => item.rs.toFixed(2)),
symbol: 'circle', symbol: 'circle',

18
src/libs/constant.ts

@ -3,24 +3,6 @@ export const HEADER_TOKEN_KEY = 'Authorization'
// sessionStorage里token的名称 // sessionStorage里token的名称
export const SESSIONSTORAGE_TOKEN_KEY = 'web_token' export const SESSIONSTORAGE_TOKEN_KEY = 'web_token'
export const formulaNameMap: Record<string, any> = {
stoped_gs: '停止H2o2浓度',
continued_gs: '继续H2o2浓度',
stoped_satur: '停止H2o2饱和度',
continued_satur: '继续H2o2饱和度',
max_humidity: '消毒最大湿度',
injection_pump_speed: '喷射蠕动泵转速',
pre_heat_time_s: '预热时间',
stoped_humi: '停止相对湿度',
continued_humi: '湿度',
proportional_valve_default_value: '正负压比例',
loglevel: '消毒等级',
dvalue_correct_coefficient: 'D值修正系数',
record_period_min: '消毒日志记录间隔',
record_printer_period_min: '消毒日志打印间隔',
}
// 空气压力初始化数据 // 空气压力初始化数据
export const PARSSURE_DATA = { export const PARSSURE_DATA = {
intensitys: { intensitys: {

7
src/stores/homeStore.ts

@ -134,6 +134,7 @@ export const useHomeStore = defineStore('home', () => {
const defaultIntensityTypeValue = ref() const defaultIntensityTypeValue = ref()
const realRate = ref() const realRate = ref()
const realLog = ref()
const allData = ref<any[]>([]) const allData = ref<any[]>([])
@ -141,6 +142,10 @@ export const useHomeStore = defineStore('home', () => {
realRate.value = data realRate.value = data
} }
const setLog = (data: any) => {
realLog.value = data
}
/** /**
* @function updateHomeData * @function updateHomeData
* @param {Home.DisplayrelyMgr[]} data - * @param {Home.DisplayrelyMgr[]} data -
@ -235,7 +240,9 @@ export const useHomeStore = defineStore('home', () => {
return { return {
realRate, realRate,
realLog,
setRate, setRate,
setLog,
isDeviceIdle, isDeviceIdle,
h2O2SensorData, h2O2SensorData,

195
src/views/home/chart.vue

@ -1,12 +1,12 @@
<script lang="ts" setup> <script lang="ts" setup>
import { syncSendCmd } from 'apis/system'
import { sendCmd, syncSendCmd } from 'apis/system'
import homeFinish from 'assets/images/home/home-finish.svg' import homeFinish from 'assets/images/home/home-finish.svg'
import homeSettingSvg from 'assets/images/home/home-setting.svg'
import BtButton from 'components/common/BTButton/index.vue'
import RunFormulaConfig from 'components/formula/RunFormulaConfig.vue' import RunFormulaConfig from 'components/formula/RunFormulaConfig.vue'
import LineChart from 'components/home/LineChart.vue' import LineChart from 'components/home/LineChart.vue'
import { ElLoading } from 'element-plus'
import { stopTimer } from 'libs/countdownTimer' import { stopTimer } from 'libs/countdownTimer'
import { FtMessage } from 'libs/message' import { FtMessage } from 'libs/message'
import { FtMessageBox } from 'libs/messageBox'
import { compareJSON, deviceStateMap } from 'libs/utils' import { compareJSON, deviceStateMap } from 'libs/utils'
import { computed, onMounted, onUnmounted, provide, ref, watchEffect } from 'vue' import { computed, onMounted, onUnmounted, provide, ref, watchEffect } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
@ -26,13 +26,26 @@ const disinfectionState = ref(homeStore.disinfectionState)
const curStateRemainTime = ref(homeStore.curStateRemainTime) const curStateRemainTime = ref(homeStore.curStateRemainTime)
const disinfectFormulaVisible = ref(false) const disinfectFormulaVisible = ref(false)
const isDeviceIdle = ref(homeStore.isDeviceIdle) const isDeviceIdle = ref(homeStore.isDeviceIdle)
const loading = ref(false)
watchEffect(() => {
const rate = ref()
const log = ref()
watchEffect(async () => {
formulaInfo.value = formulaStore.currentSelectedFormulaInfo formulaInfo.value = formulaStore.currentSelectedFormulaInfo
disinfectionState.value = homeStore.disinfectionState disinfectionState.value = homeStore.disinfectionState
curStateRemainTime.value = homeStore.curStateRemainTime curStateRemainTime.value = homeStore.curStateRemainTime
isDeviceIdle.value = homeStore.isDeviceIdle isDeviceIdle.value = homeStore.isDeviceIdle
if (['idle', 'finished'].includes(homeStore.disinfectionState.state)) {
formulaInfo.value = formulaStore.selectedFormulaInfo
rate.value = formulaStore.selectedFormulaInfo?.injection_pump_speed
log.value = formulaStore.selectedFormulaInfo?.loglevel
}
else {
const realForm = (await formulaStore.getRealtimeConfig()).rely
rate.value = homeStore.realRate || realForm?.injection_pump_speed
log.value = homeStore.realLog || realForm?.loglevel
}
}) })
const onDisinfectConfig = () => { const onDisinfectConfig = () => {
@ -41,20 +54,33 @@ const onDisinfectConfig = () => {
// //
const onFinishDisinfect = async () => { const onFinishDisinfect = async () => {
await FtMessageBox.warning('请确认是否结束消毒')
homeStore.setRate(undefined)
homeStore.setLog(undefined)
stopTimer() stopTimer()
const stopParams = {
className: 'DisinfectionCtrlServiceExt',
fnName: 'stop',
params: {
loglevel: formulaStore.loglevel,
},
}
loading.value = true
syncSendCmd(stopParams).then((res) => {
if (res.ackcode === 0) {
loading.value = false
}
const loading = ElLoading.service({
lock: true,
text: '正在结束消毒',
background: 'rgba(255, 255, 255, 0.8)',
}) })
try {
const stopParams = {
className: 'DisinfectionCtrlServiceExt',
fnName: 'stop',
params: { loglevel: formulaStore.loglevel },
}
await sendCmd(stopParams)
const poll = setInterval(() => {
if (operationState.value) {
loading.close()
clearInterval(poll)
}
}, 100)
}
catch (e) {
console.log(e)
loading.close()
}
} }
const chartRef = ref() const chartRef = ref()
const onSave = async () => { const onSave = async () => {
@ -74,6 +100,7 @@ const onSave = async () => {
) )
FtMessage.success('设定成功') FtMessage.success('设定成功')
homeStore.setRate(formData.injection_pump_speed) homeStore.setRate(formData.injection_pump_speed)
homeStore.setLog(formData.loglevel)
} }
} }
@ -151,11 +178,31 @@ const formatSeconds = (seconds: number) => {
<template> <template>
<main class="main-content"> <main class="main-content">
<!-- <div class="line-chart-title"> -->
<!-- <div class="line-chart-formula"> -->
<!-- <HomeFormula style="background: #e0f0ff" /> -->
<!-- </div> -->
<!-- </div> -->
<el-descriptions :column="4">
<el-descriptions-item label="设定注射速率">
<el-tag>
<span style="color: #31cb7a; font-size: 18px; margin: 0 5px">{{ rate }}</span>g/min
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="实时注射速率">
<el-tag>
<span style="color: #31cb7a; font-size: 18px; margin: 0 5px">{{
homeStore.disinfectionState.injectedVelocity
}}</span>g/min
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="目标消毒等级">
<el-tag>
<span style="color: #31cb7a; font-size: 18px; margin: 0 5px">{{ log }}</span>Log
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="实时消毒等级">
<el-tag>
<span style="color: #31cb7a; font-size: 18px; margin: 0 5px">{{ homeStore.disinfectionState.nlog }}</span>Log
</el-tag>
</el-descriptions-item>
</el-descriptions>
<div <div
v-loading="chartLoading" v-loading="chartLoading"
class="line-chart-content" class="line-chart-content"
@ -179,46 +226,21 @@ const formatSeconds = (seconds: number) => {
</div> </div>
</div> </div>
<div class="home-chart-btn"> <div class="home-chart-btn">
<BtButton
v-if="!isDeviceIdle"
button-text="结束消毒"
bg-color="#FF6767"
text-color="#FFFFFF"
width="15vw"
height="3.5rem"
text-size="24px"
border-radius="5px"
@click="onFinishDisinfect"
>
<el-button v-if="!isDeviceIdle" type="danger" @click="onFinishDisinfect">
<template #icon> <template #icon>
<img :src="homeFinish" alt="">
<img :src="homeFinish" alt="" style="height: 20px">
</template> </template>
</BtButton>
<BtButton
v-if="!isDeviceIdle"
button-text="运行参数"
text-size="24px"
border-radius="5px"
height="3.5rem"
text-color="#1989fa"
padding="0.8vw"
@click="onDisinfectConfig"
>
<template #icon>
<img :src="homeSettingSvg" width="15" alt="">
</template>
</BtButton>
<BtButton
button-text="返回"
width="10vw"
height="7vh"
text-color="#1989fa"
text-size="24px"
border-radius="5px"
@click="goHome"
/>
结束消毒
</el-button>
<el-button v-if="!isDeviceIdle" type="primary" @click="onDisinfectConfig">
运行参数
</el-button>
<el-button @click="goHome">
返回
</el-button>
</div> </div>
</div> </div>
<ft-dialog v-model="disinfectFormulaVisible" title="运行参数" width="80vw"> <ft-dialog v-model="disinfectFormulaVisible" title="运行参数" width="80vw">
<div class="formula-config"> <div class="formula-config">
<RunFormulaConfig ref="chartRef" /> <RunFormulaConfig ref="chartRef" />
@ -240,8 +262,11 @@ const formatSeconds = (seconds: number) => {
<style lang="scss" scoped> <style lang="scss" scoped>
.main-content { .main-content {
overflow: hidden; overflow: hidden;
background: $gradient-color;
height: $main-container-height;
background: rgba(147, 203, 255, 0.1);
height: 100%;
border-radius: 10px;
box-shadow: 0 1px 5px 0 rgba(9, 39, 62, 0.15);
padding: 10px;
.formula-config { .formula-config {
display: grid; display: grid;
padding: 10px; padding: 10px;
@ -272,10 +297,10 @@ const formatSeconds = (seconds: number) => {
} }
.line-chart-content { .line-chart-content {
display: grid; display: grid;
height: calc(100% - 60px);
height: calc(100% - 80px);
} }
.line-chart-bottom { .line-chart-bottom {
height: 60px;
height: 40px;
display: flex; display: flex;
padding-right: 20px; padding-right: 20px;
align-items: center; align-items: center;
@ -287,21 +312,55 @@ const formatSeconds = (seconds: number) => {
.home-chart-time { .home-chart-time {
width: 35%; width: 35%;
.home-remain-time { .home-remain-time {
background: #f6fafe;
width: 27vw;
height: 8vh;
background: #fff;
margin: 10px;
height: 40px;
border-radius: 12px; border-radius: 12px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
font-size: 24px;
font-size: 20px;
gap: 10px; gap: 10px;
margin-left: 1rem;
.home-chart-value {
.home-remaini-value {
color: #2892f3; color: #2892f3;
} }
} }
} }
} }
} }
:deep(.el-descriptions) {
width: 100%;
height: 40px;
.el-descriptions__body {
background: rgba(0, 0, 0, 0);
.el-descriptions__table {
tr {
display: flex;
justify-content: center;
gap: 20px;
}
}
}
}
:deep(.el-descriptions__cell) {
display: flex;
align-items: center;
//background: #fff;
//margin-bottom: 5px;
//padding: 5px !important;
//.el-descriptions__label {
// display: inline-block;
// width: 120px;
// margin: 0;
// font-size: 15px;
// font-weight: 600;
// color: #606266;
//}
//.el-descriptions__content {
// flex: 1;
// text-align: right;
// display: flex;
// justify-content: flex-end;
//}
}
</style> </style>

12
src/views/home/index.vue

@ -1,7 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import Environment from 'components/home/Environment.vue' import Environment from 'components/home/Environment.vue'
import HomeFormula from 'components/home/HomeFormula.vue' import HomeFormula from 'components/home/HomeFormula.vue'
import HomeLogLevel from 'components/home/HomeLogLevel.vue'
import HomeOperation from 'components/home/HomeOperation.vue' import HomeOperation from 'components/home/HomeOperation.vue'
import HomeSetting from 'components/home/HomeSetting.vue' import HomeSetting from 'components/home/HomeSetting.vue'
import PressureControl from 'components/home/PressureControl.vue' import PressureControl from 'components/home/PressureControl.vue'
@ -120,14 +119,14 @@ const deviceType = computed(() => {
</div> </div>
</div> </div>
<div class="card-num-g"> <div class="card-num-g">
消毒液剩余:{{ nowLiquid }}g
消毒液剩余:{{ nowLiquid || 0 }}g
</div> </div>
</div> </div>
</div> </div>
<div class="middle"> <div class="middle">
<!-- 选择消毒的等级 --> <!-- 选择消毒的等级 -->
<HomeLogLevel v-if="!formulaStore.selectedFormulaInfo?.name" />
<!-- <HomeLogLevel v-if="!formulaStore.selectedFormulaInfo?.name" /> -->
<!-- 开始消毒停止消毒及状态区 --> <!-- 开始消毒停止消毒及状态区 -->
<HomeOperation /> <HomeOperation />
</div> </div>
@ -143,9 +142,8 @@ const deviceType = computed(() => {
</div> </div>
</div> </div>
</div> </div>
<div v-else>
<router-view />
</div>
<router-view v-else />
</div> </div>
</template> </template>
@ -181,6 +179,7 @@ $input-height: 3rem;
border-radius: 10px 10px 10px 10px; border-radius: 10px 10px 10px 10px;
background: #ffffff; background: #ffffff;
background: linear-gradient(180deg, rgba(147, 203, 255, 1) -190%, #ffffff 24%); background: linear-gradient(180deg, rgba(147, 203, 255, 1) -190%, #ffffff 24%);
background: rgba(147, 203, 255, 0.1);
.title-line { .title-line {
height: 1vw; height: 1vw;
@ -204,6 +203,7 @@ $input-height: 3rem;
.home-right { .home-right {
padding: 10px; padding: 10px;
background: linear-gradient(180deg, rgba(147, 203, 255, 1) -190%, #ffffff 24%); background: linear-gradient(180deg, rgba(147, 203, 255, 1) -190%, #ffffff 24%);
background: rgba(147, 203, 255, 0.1);
border-radius: 10px; border-radius: 10px;
box-shadow: 0 1px 5px 0 rgba(9, 39, 62, 0.15); box-shadow: 0 1px 5px 0 rgba(9, 39, 62, 0.15);
display: flex; display: flex;

Loading…
Cancel
Save